456 lines
23 KiB
Plaintext
456 lines
23 KiB
Plaintext
|
||
HOW TO CRACK, by +ORC, A TUTORIAL
|
||
|
||
Lesson 6.1: Funny tricks (1)
|
||
|
||
|
||
LESSON 6 (1) - Funny tricks. Xoring, Junking, Sliding
|
||
EXERCISE 01: [LARRY in search of the King]
|
||
Before the next step let's resume what you have learned in
|
||
the lessons 3-5, beginning with a very simple crack exercise
|
||
(again, we'll use the protection scheme of a game, for the
|
||
reasons explained in lesson 1): SEARCH FOR THE KING (Version
|
||
1.1.). This old "Larry" protection sequence, is a "paper
|
||
protection" primitive. It's a very widespread (and therefore easy
|
||
to find) program, and one of the first programs that instead of
|
||
asking meaningful passwords (which offer us the possibility to
|
||
immediately track them down in memory) asked for a random number
|
||
that the good buyer could find on the manual, whereby the bad
|
||
cracker could not. (Here you choose -with the mouse- one number
|
||
out of 5 possible for a "gadget" choosen at random). I don't need
|
||
any more to teach you how to find the relevant section of code
|
||
(-> see lesson 3). Once you find the protection, this is what you
|
||
get:
|
||
|
||
:protection_loop
|
||
:C922 8E0614A3 MOV ES,[A314]
|
||
...
|
||
:C952 50 0E PUSH AX & CS
|
||
:C954 E81BFF CALL C872 <- call protection scheme
|
||
:C957 5B POP BX twice
|
||
:C959 8B76FA MOV SI,[BP-06] <- prepare store_room
|
||
:C95C D1E6 SHL SI,1 <- final prepare
|
||
:C95E 8942FC MOV [BP+SI-04],AX <- store AX
|
||
:C961 837EFA00 CMP Word Ptr [BP-06],+00 <- good_guy?
|
||
:C965 75BB JNZ C922 <- loop, bad guy
|
||
:C967 8E0614A3 MOV ES,[A314]
|
||
:C96B 26F606BE3501 TEST Byte Ptr ES:[35BE],01 <- bad_guy?
|
||
:C971 74AF JZ C922 <- loop, bad guy
|
||
:C973 8B46FC MOV AX,[BP-04]... <- go on good guy
|
||
|
||
Let's see now the protection scheme called from :C954
|
||
:C872 55 PUSH BP
|
||
...
|
||
:C8F7 90 NOP
|
||
:C8F8 0E PUSH CS
|
||
:C8F9 E87234 CALL FD6E <- call user input
|
||
:C8FC 5B POP BX
|
||
:C8FD 5B POP BX
|
||
:C8FE 8B5E06 MOV BX,[BP+06]
|
||
:C901 D1E3 SHL BX,1
|
||
:C903 39872266 CMP [BX+6622],AX <- right answer?
|
||
:C907 7505 JNZ C90E <- no, beggar_off
|
||
:C909 B80100 MOV AX,0001 <- yes, AX=1
|
||
:C90C EB02 JMP C910
|
||
:C90E 2BC0 SUB AX,AX <- beggar_off with AX=0
|
||
:C910 8BE5 MOV SP,BP
|
||
:C912 5D POP BP
|
||
:C913 CB RETF <- back to main
|
||
|
||
Here follow 5 questions, please answer all of them:
|
||
1) Where in memory (in which locations) are stored the "right"
|
||
passnumbers? Where in memory is the SEGMENT of this
|
||
locations stored? How does the scheme get the OFFSET?
|
||
2) Would setting NOPs instructions at :C965 and :C971 crack?
|
||
Would it be a good idea?
|
||
3) Would changing :C907 to JZ crack? Would it be a good idea?
|
||
4) Would changing :C907 to JNZ C909 crack? Would it be a good
|
||
idea?
|
||
5) Write down (and try) at least 7 OTHER different patches to
|
||
crack this scheme in spades (without using any NOP!).
|
||
Uff! By now you should be able to do the above 5 exercises in
|
||
less than 15 minutes WITHOUT USING THE DEBUGGER! Just look at the
|
||
data above and find the right answers feeling them... (you 'll
|
||
now which one are the right one checking with your debugger...
|
||
score as many points as you like for each correct answer and sip
|
||
a good Martini-Wodka... do you know that the sequence should
|
||
ALWAYS be 1) Ice cubes 2) Martini Dry 3) Wodka Moskovskaja 4)
|
||
olive 5) lemon 6) Schweppes Indian tonic?
|
||
|
||
Let's now come to the subject of this lesson:
|
||
-----> [Xoring] (Simple encryption methods)
|
||
One easy way to encrypt data is the XOR method. XOR is a bit
|
||
manipulation instruction that can be used in order to cipher and
|
||
decipher data with the same key:
|
||
Byte to encrypt key result
|
||
FF XOR A1 5E
|
||
5E XOR A1 FF
|
||
As you can see XOR offers a very easy way to encrypt or to
|
||
decrypt data, for instance using the following routine:
|
||
encrypt_decrypt:
|
||
mov bx, offset_where_encryption/decryption_starts
|
||
xor_loop:
|
||
mov ah, [bx] <- get current byte
|
||
xor ah, encrypt_value <- engage/disengage xor
|
||
mov [bx], ah <- back where you got it
|
||
inc bx <- ahead one byte
|
||
cmp bx, offset_start_+_size <- are we done?
|
||
jle xor_loop <- no, then next cycle
|
||
ret <- back where we came from
|
||
|
||
The encrypt_value can be always the same (fixed) or chosen at
|
||
random, for instance using INT_21, service 2Ch (get current time)
|
||
and choosing as encrypt_value the value reported in DL (but
|
||
remembering to discard the eventual value 0, coz otherwise it
|
||
would not xor anything at all!)
|
||
random_value:
|
||
mov ah,2Ch
|
||
int 21h
|
||
cmp dl,0
|
||
je random_value
|
||
mov encrypt_value,dl
|
||
The problem with XORing (and with many other encryption
|
||
methods), is that the part of the code that calls the encryption
|
||
routine cannot be itself encrypted. You'll somewhere have, "in
|
||
clear" the encryption key.
|
||
|
||
The protectionist do at times their best to hide the
|
||
decrypting routine, here are some common methods:
|
||
|
||
-----> JUNK FILLING, SLIDING KEYS AND MUTATING DECRYPTORS
|
||
These are the more common protection method for the small
|
||
decryption part of the program code. This methods, originally
|
||
devised to fool signature virus scanners, have been pinched from
|
||
the polymorphic virus engines of our fellows viriwriters, and are
|
||
still in use for many simple decryption protection schemes. For
|
||
parts of the following many thanks go to the [Black Baron], it's
|
||
a real pity that so many potential good crackers dedicate so much
|
||
time to useless (and pretty repetitive) virus writing instead of
|
||
helping in our work. This said, virus studying is VERY important
|
||
for crackers coz the code of the viri is
|
||
* ULTRAPROTECTED
|
||
* TIGHT AND EFFECTIVE
|
||
* CLOAKED AND CONCEALED.
|
||
|
||
Let's show as example of the abovementioned protection tactics
|
||
the following ultra-simple decryptor:
|
||
MOV SI,jumbled_data ;Point to the jumbled data
|
||
MOV CX,10 ;Ten bytes to decrypt
|
||
mn_loop: XOR BYTE PTR [SI],44 ;XOR (un_scramble!) a byte
|
||
INC SI ;Next byte
|
||
LOOP mn_loop ;Loop the 9 other bytes
|
||
|
||
This small program will XOR the ten bytes at the location pointed
|
||
to by SI with the value 44. Providing the ten bytes were XORed
|
||
with 44 prior to running this decryptor the ten bytes will be
|
||
restored to their original state.
|
||
In this very simple case the "key" is the value 44. But there are
|
||
several tricks involving keys, the simplest one being the use of
|
||
a "sliding" key: a key that will be increased, or decreased, or
|
||
multiplied, or bit-shifted, or whatever, at every pass of the
|
||
loop.
|
||
|
||
A possible protection can also create a true "Polymorph"
|
||
decryptor, a whole decryptor ROUTINE that looks completely
|
||
different on each generation. The trick is to pepper totally
|
||
random amounts of totally random instructions, including JUMPS
|
||
and CALLS, that DO NOT AFFECT the registers that are used for the
|
||
decryption. Also this kind of protection oft uses a different
|
||
main decryptor (possibly from a selection of pre-coded ones) and
|
||
oft alters on each generation also all the registers that the
|
||
decryptor uses, invariably making sure that the JUNK code that
|
||
it generates doesn't destroy any of the registers used by the
|
||
real decryptor! So, with these rules in mind, here is our simple
|
||
decryptor again:
|
||
|
||
MOV DX,10 ;Real part of the decryptor!
|
||
MOV SI,1234 ;junk
|
||
AND AX,[SI+1234] ;junk
|
||
CLD ;junk
|
||
MOV DI,jumbled_data ;Real part of the decryptor!
|
||
TEST [SI+1234],BL ;junk
|
||
OR AL,CL ;junk
|
||
mn_loop: ADD SI,SI ;junk instr, but real loop!
|
||
XOR AX,1234 ;junk
|
||
XOR BYTE PTR [DI],44 ;Real part of the decryptor!
|
||
SUB SI,123 ;junk
|
||
INC DI ;Real part of the decryptor!
|
||
TEST DX,1234 ;junk
|
||
AND AL,[BP+1234] ;junk
|
||
DEC DX ;Real part of the decryptor!
|
||
NOP ;junk
|
||
XOR AX,DX ;junk
|
||
SBB AX,[SI+1234] ;junk
|
||
AND DX,DX ;Real part of the decryptor!
|
||
JNZ mn_loop ;Real part of the decryptor!
|
||
|
||
As you should be able to see, quite a mess! But still executable
|
||
code. It is essential that any junk code generated by the
|
||
Polymorph protection is executable, as it is going to be peppered
|
||
throughout the decryptor. Note, in this example, that some of the
|
||
junk instructions use registers that are actually used in the
|
||
decryptor! This is fine, providing the values in these
|
||
registers aren't destroyed. Also note, that now we have random
|
||
registers and random instructions on each generation. So, a
|
||
Polymorph protection Engine can be summed up into three major
|
||
parts:
|
||
1 .. The random number generator.
|
||
2 .. The junk code generator.
|
||
3 .. The decryptor generator.
|
||
There are other discrete parts but these three are the ones where
|
||
most of the work goes on!
|
||
|
||
How does it all work? Well a good protection would
|
||
* choose a random selection of registers to use for the
|
||
decryptor and leave the remaining registers as "junk" registers
|
||
for the junk code generator.
|
||
* choose one of the compressed pre-coded decryptors.
|
||
* go into a loop generating the real decryptor, peppered with
|
||
junk code.
|
||
From the protectionist's point of view, the advantages of this
|
||
kind of method are mainly:
|
||
* the casual cracker will have to sweat to find the decryptor.
|
||
* the casual cracker will not be able to prepare a "patch" for
|
||
the lamers, unless he locates and patches the generators, (that
|
||
may be compressed) coz otherwise the decryptor will vary every
|
||
time.
|
||
|
||
To defeat this kind of protection you need a little "zen" feeling
|
||
and a moderate knowledge of assembler language... some of the
|
||
junk instructions "feel" quite singular when you look at them
|
||
(->see lesson B). Besides, you (now) know what may be going on
|
||
and memory breakpoints will immediately trigger on decryption...
|
||
the road is open and the rest is easy (->see lessons 3-5).
|
||
|
||
-----> Starting point number magic
|
||
For example, say the encrypted code started at address 10h, the
|
||
following could be used to index this address:
|
||
MOV SI,10h ;Start address
|
||
MOV AL,[SI] ;Index from initial address
|
||
But sometimes you'll instead find something like the following,
|
||
again based on the encrypted code starting at address 10h:
|
||
|
||
MOV DI,0BFAAh ;Indirect start address
|
||
MOV AL,[DI+4066h) ;4066h + 0BFAAh = 10010h (and FFFF = 10h)!!
|
||
The possible combinations are obviously infinite.
|
||
|
||
|
||
[BIG KEYS] (Complicated encryption methods)
|
||
Prime number factoring is the encryption used to protect
|
||
sensible data and very expensive applications. Obviously for few
|
||
digit keys the decoding is much easier than for, say, 129 or 250
|
||
digit keys. Nevertheless you can crack those huge encryption too,
|
||
using distributed processing of quadratic sieve equations (which
|
||
is far superior for cracking purpose to the sequential processing
|
||
methods) in order to break the key into prime numbers. To teach
|
||
you how to do this sort of "high" cracking is a little outside
|
||
the scope of my tutorial: you'll have to write a specific short
|
||
dedicated program, linking together more or less half a thousand
|
||
PC for a couple of hours, for a 250 bit key, this kind of things
|
||
have been done quite often on Internet, were you can also find
|
||
many sites that do untangle the mysteries (and vagaries) of such
|
||
techniques.
|
||
As References I would advocate the works of Lai Xueejia, those
|
||
swiss guys can crack *everything*. Begin with the following:
|
||
Xuejia Lai, James Massey, Sean Murphy, "Markov Ciphers and
|
||
Differential Cryptanalysis", Advances in Cryptology,
|
||
Eurocrypt 1991.
|
||
Xuejia Lai, "On the Design and Security of Block Ciphers",
|
||
Institute for Signal and Information Processing,
|
||
ETH-Zentrum, Zurich, Switzerland, 1992
|
||
Factoring and primality testing is obviously very important for
|
||
this kind of crack. The most comprehensive work I know of is:
|
||
(300 pages with lengthy bibliography!)
|
||
W. Bosma & M. van der Hulst
|
||
Primality Testing with Cyclotomy
|
||
Thesis, University of Amsterdam Press.
|
||
A very good old book you can incorporate in your probes to build
|
||
very effective crack programs (not only for BBS accesses :=) is
|
||
*the* "pomerance" catalog:
|
||
Pomerance, Selfridge, & Wagstaff Jr.
|
||
The pseudoprimes to 25*10^9
|
||
Math. Comp. Vol 35 1980 pp. 1003-1026
|
||
|
||
Anyway... make a good search with Lykos, and visit the relevant
|
||
sites... if encryption really interests you, you'll be back in
|
||
two or three (or thirty) years and you'll resume cracking with
|
||
deeper erudite knowledge.
|
||
[PATENTED PROTECTION SYSTEMS]
|
||
The study of the patented enciphering methods is also *quite*
|
||
interesting for our aims :=) Here are some interesting patents,
|
||
if you want to walk these paths get the complete texts:
|
||
[BEST] USPat 4168396 to Best discloses a microprocessor
|
||
for executing enciphered programs. Computer programs which have
|
||
been enciphered during manufacture to deter the execution of the
|
||
programs in unauthorized computers, must be decrypted before
|
||
execution. The disclosed microprocessor deciphers and executes
|
||
an enciphered program one instruction at a time, instead of on
|
||
a continuous basis, through a combination of substitutions,
|
||
transpositions, and exclusive OR additions, in which the address
|
||
of each instruction is combined with the instruction. Each unit
|
||
may use a unique set of substitutions so that a program which can
|
||
be executed on one microprocessor cannot be run on any other
|
||
microprocessor. Further, Best cannot accommodate a mixture of
|
||
encrypted and plain text programs.
|
||
[JOHNSTONE] USPat 4120030 to Johnstone describes a
|
||
computer in which the data portion of instructions are scrambled
|
||
and in which the data is of necessity stored in a separate
|
||
memory. There is no disclosure of operating with instructions
|
||
which are completely encrypted with both the operation code and
|
||
the data address portion being unreadable without a corresponding
|
||
key kernel.
|
||
[TWINPROGS] USPat 4183085 describes a technique for
|
||
protecting software by providing two separate program storages.
|
||
The first program storage is a secure storage and the second
|
||
program storage is a free storage. Security logic is provided to
|
||
check whether an output instruction has originated in the secure
|
||
store and to prevent operation of an output unit which receives
|
||
output instructions from the free storage. This makes it
|
||
difficult to produce information by loading a program into free
|
||
storage.
|
||
[AUTHENTICATOR] USPat 3996449 entitled "Operating System
|
||
Authenticator," discloses a technique for authenticating the
|
||
validity of a plain text program read into a computer, by
|
||
exclusive OR'ing the plain text of the program with a key to
|
||
generate a code word which must be a standard recognizable code
|
||
word which is successfully compared with a standard corresponding
|
||
code word stored in the computer. If there is a successful
|
||
compare, then the plain text program is considered to be
|
||
authenticated and is allowed to run, otherwise the program
|
||
is not allowed to run.
|
||
|
||
ELEMENTS OF [PGP] CRACKING
|
||
In order to try to crack PGP, you need to understand how these
|
||
public/private keys systems work. Cracking PGP seems extremely
|
||
difficult, though... I have a special dedicated "attack" computer
|
||
that runs 24 hours on 24 only to this aim and yet have only begun
|
||
to see the light at the famous other end of the tunnel. It's
|
||
hard, but good crackers never resign! We'll see... I publish here
|
||
the following only in the hope that somebody else will one day
|
||
be able to help...
|
||
In the public key cryptosystems, like PGP, each user has an
|
||
associated encryption key E=(e,n) and decryption key D=(d,n),
|
||
wherein the encryption keys for all users are available in a
|
||
public file, while the decryption keys for the users are only
|
||
known to the respective users. In order to maintain a high level
|
||
of security a user's decoding key is not determinable in a
|
||
practical manner from that user's encoding (public) key. Normally
|
||
in such systems, since
|
||
e.multidot.d.ident.1 (mod(1 cm((p-1),(q-1)))),
|
||
(where "1 cm((p-1),(q-1))" is the least common multiple of the
|
||
numbers p-1 and q-1)
|
||
|
||
d can be determined from e provided p and q are also known.
|
||
Accordingly, the security of the system is dependent upon the
|
||
ability to determine p and q which are the prime factors of n.
|
||
By selecting p and q to be large primes, the resultant composite
|
||
number n is also large, and correspondingly difficult to factor.
|
||
For example, using known computer-implemented factorization
|
||
methods, on the order of 10.sup.9 years is required to factor a
|
||
200 digit long number. Thus, as a practical matter, although a
|
||
user's encryption key E=(e,n) is public, the prime factors p and
|
||
q of n are effectively hidden from anyone due to the enormous
|
||
difficulty in factoring n. These aspects are described more fully
|
||
in the abundant publications on digital signatures and Public-Key
|
||
Cryptosystems. Most public/private systems relies on a message-
|
||
digest algorithm.
|
||
A message-digest algorithm maps a message of arbitrary length
|
||
to a "digest" of fixed length, and has three properties:
|
||
Computing the digest is easy, finding a message with a given
|
||
digest "inversion" is hard, and finding two messages with the
|
||
same digest "collision" is also hard. Message-digest algorithms
|
||
have many applications, not only digital signatures and message
|
||
authentication. RSA Data Security's MD5 message-digest algorithm,
|
||
developed by Ron Rivest, maps a message to a 128-bit message
|
||
digest. Computing the digest of a one-megabyte message takes as
|
||
little as a second. While no message-digest algorithm can yet
|
||
be secure, MD5 is believed to be at least as good as any other
|
||
that maps to a 128-bit digest.
|
||
As a final gift, I'll tell you that PGP relies on MD5 for a
|
||
secure one-way hash function. For PGP this is troublesome, to say
|
||
the least, coz an approximate relation exists between any four
|
||
consecutive additive constants. This means that one of the design
|
||
principles behind MD4 (and MD5), namely to design a collision
|
||
resistant function, is not satisfied. You can construct two
|
||
chaining variables (that only differ in the most significant bit
|
||
of every word) and a single message block that yield the same
|
||
hashcode. The attack takes a few minutes on a PC. From here you
|
||
should start, as I did.
|
||
|
||
[DOS 4GW] cracking - This is only a very provisory part of this
|
||
tutorial. DOS 4GW cracking will be much better described as soon
|
||
as [Lost soul] sends his stuff, if he ever does. For (parts of)
|
||
the following I thank [The Interrupt].
|
||
Most applications of every OS, and also of DOS 4GW, are
|
||
written in C language, coz as you'll have already learned or,
|
||
either, you'll learn, only C allows you to get the "guts" of a
|
||
program, almost approaching the effectiveness of assembler
|
||
language.
|
||
C is therefore the LANGUAGE OF CHOICE for crackers, when you
|
||
prepare your tools and do not directly use assembler routines.
|
||
Besides... you'll be able to find VERY GOOD books about C for
|
||
next to nothing in the second hand bookshops. All the lusers are
|
||
throwing money away in spades buying huge, coloured and
|
||
absolutely useless books on unproductive "bloated" languages like
|
||
Visual basic, C++ and Delphy. Good C new books are now rare
|
||
(books on assembler language have always been) and can be found
|
||
almost exclusively on the second hand market. Find them, buy
|
||
them, read them, use them for your/our aims. You can find a lot
|
||
of C tutorials and of C material on the Web, by all means DO IT!
|
||
Be a conscientious cracker... learn C! It's cheap, lean, mean and
|
||
very productive (and creative) :=)
|
||
Back to the point: most stuff is written in C and therefore
|
||
you need to find the "main" sub-routine inside the asm. With
|
||
DOS/4GW programs, search the exe file for "90 90 90 90", almost
|
||
always it'll be at the start of the compiled code. Now search for
|
||
an INT_21 executed with 4C in AH, the exec to dos code (if you
|
||
cannot "BPINT 21 AH=4C" with your tool, then search for the
|
||
sequence "b4 4c cd 21". This is the equivalent to [mov AH,4C &
|
||
int 21]: it's the most direct call, but as you'll have already
|
||
learned, there are half a dozen ways to put 4C in AX, try them
|
||
all in the order of their frequency).
|
||
A few bytes above the INT_21 service 4C, you'll find the
|
||
call to the "main" subroutine: "E8 xx xx". Now place a "CC" byte
|
||
a few bytes above the call in the exe and run the exe under a
|
||
debugger. When the computer tries to execute the instruction
|
||
you'll be throw back in the debugger coz the "CC" byte acts as
|
||
INT_01 instruction. Then proceed as usual.
|
||
|
||
[THE "STEGONATED" PASSWORD HIDEOUT]
|
||
A last, very nice trick should be explained to every wannabe
|
||
cracker, coz it would be embarrassing to search for passwords or
|
||
protection routines that (apparently) are not there. They may be
|
||
hidden INSIDE a picture (or a *.waw file for that matter). This
|
||
is steganography, a method of disguising messages within other
|
||
media.
|
||
Depending on how many shades of grey or hues of colour you want
|
||
to have, a pixel can be expressed using 8. 16, 32 or even more
|
||
bits. If the least significant bit is changed. the shade of the
|
||
pixel is altered only one-256th, one-65,OOOth or even less. No
|
||
human eye could tell the difference.
|
||
What the protectionist does, is hijack the least significant
|
||
bit in each pixel of a picture. It uses that bit to store one bit
|
||
of a protection, or of a password (or of a file, or of a secret
|
||
message). Because digitized pictures have lots of pixels, it's
|
||
possible to store lots of data in a single picture. A simple
|
||
algorithm will transfer them to the relevant parts of the program
|
||
when it needs be, and there we'll intercept them. You'll need to
|
||
learn very well the zen-cracking techniques to smell this kind
|
||
of stuff though (-> see lesson B).
|
||
|
||
Well, that's it for this lesson, reader. Not all lessons of my
|
||
tutorial are on the Web.
|
||
|
||
You 'll obtain the OTHER missing lessons IF AND ONLY IF you
|
||
mail me back (via anon.penet.fi) with some tricks of the trade
|
||
I may not know that YOU discovered. Mostly I'll actually know
|
||
them already, but if they are really new you'll be given full
|
||
credit, and even if they are not, should I judge that you
|
||
"rediscovered" them with your work, or that you actually did good
|
||
work on them, I'll send you the remaining lessons nevertheless.
|
||
Your suggestions and critics on the whole crap I wrote are also
|
||
welcomed.
|
||
|
||
an526164@anon.penet.fi (+ORC)
|
||
|