home *** CD-ROM | disk | FTP | other *** search
- A solution to RTQ's crackme
- ---------------------------
-
- Written by Prophecy (prophecy_@usa.net)
- 13th June 1998
-
- (Basic knowledge of Softice is assumed)
-
- Part 1: Tools required
- -----------------------
-
- All you need is Softice :)
-
- Part 2: Breaking into the target and locating the main code checking routine
- -----------------------------------------------------------------------------
-
- Well this is the first DOS proggie I've ever looked at, so I took a little time
- here. Basically what I did was:
-
- (1) set bpx bpint 21 if ah==9
- (2) typed in a bogus code
- (3) softice broke when i hit 'enter' (by this time it's already too late, the
- code has already been checked)
- (4) i searched for my code in memory and by chance it found it in 0:e8b
- (5) i then put a bpr on 0:e8b
- (6) i then entered a new code, each char i pressed, softice broke, i hit <F5>
- to go back to the crackme and enter a new char.
- (7) when i finished my entering my code by pressing enter, softice broke here:
-
- FF03:5463 AA STOSB
- FF03:5464 E84602 CALL 56AD
- .
- .
- FF03:5476 F3A4 REPZ MOVSB
- FF03:5478 C3 RET
-
- (8) tracing the code, i soon reached what we were looking for: the place where
- the crackme checks to see if the code is valid!!!
-
- Part 3: How the target manipulates the code entered by the user
- ----------------------------------------------------------------
-
- Basically, the crackme consists of a few simple checks to see if the code is
- valid.
-
- 0EE4:07B0 MOV SI,DX
- 0EE4:07B2 MOV AL,[SI] ;put length of code into AL
- 0EE4:07B4 SBB AL,0B ;subtract from 0xb
- 0EE4:07B6 JNZ 0859 ;jump bad_guy if not zero (Condition 0)
-
- Pretty simple, code has to be 0xb (11) chars long, which you'll note fits
- perfectly inside the [ ] ... so no surprises here. Either go back
- and enter a new 11 char code or reverse the jump (r fl z).
-
- 0EE4:07BA MOV SI,DX
- 0EE4:07BC XOR BX,BX ;set bx=0
- 0EE4:07BE MOV CX,0005 ;do 5 loops
- 0EE4:07C1 LODSW ;load word at ds:si (which is your code)
- 0EE4:07C2 ADD AL,AH ;add high byte to low byte
- 0EE4:07C4 XOR AH,AH ;set ah=0
- 0EE4:07C6 ADD BX,AX ;add ax to bx
- 0EE4:07C8 LOOP 07C1 ;go back to 07c1
- 0EE4:07CA XOR AX,AX ;set ax=0
- 0EE4:07CC LODSB ;load byte at cs:dx
- 0EE4:07CD ADD BX,AX ;add 10th char of code to checksum
- 0EE4:07CF CMP BX,042D ;compare total with 0x42d
- 0EE4:07D3 JNZ 0859 ;jump bad_guy if not zero (Condition 1)
-
- Ok, this is pretty simple too...
-
- cs:dx is your code with the length of the code in front, ie if you entered
- 12345678901 as your code, then cs:dx is this:
-
- 0b 31 32 33 34 35 36 37 38 39 30 31 <- code and length
- 0 1 2 3 4 5 6 7 8 9 10 11 <- char number i use as reference
-
- So the above code segment takes the first word 310b, adds 0b to 31 giving
- 3c which is stored in al. it then adds ax to bx which is initally zero.
- it then takes the 2nd word 3332 and adds the 32 to 33, giving 65. It then
- adds that 65 to bx, which is 3c, giving a1 etc... it does this with chars
- 0 thru to 9. It finally adds the 10th value to the sum and compares it
- with 0x42d. So basically all this is doing is:
-
- char 0 + char 1 + char 2...+char 10 = 0x42d, so 0x42d is just a checksum.
-
- i now typed r bx and entered 42d and continued tracing.
-
- 0EE4:07D7 INC DX
- 0EE4:07D8 ADD CX,02
- 0EE4:07DB MOV SI,DX
- 0EE4:07DD MOV DI,AX ;moves ax which is char 10 into di
- 0EE4:07DF REPZ MOVSB
- 0EE4:07E1 MOV DI,AX
- 0EE4:07E3 MOV AX,[DI] ;moves what di points to into ax
- 0EE4:07E5 XOR AH,AL
- 0EE4:07E7 OR AL,AH
- 0EE4:07E9 NEG AX
- 0EE4:07EB SUB AX,FFE0
- 0EE4:07EE JNZ 0859 ;if ax not equal to ffe0, jump bad_guy (Condition 2)
-
- So, basically it takes the 10th char and puts into di, then it retrieves
- what di is now pointing to and sticks in ax. So lets say ax is now equal
- to XY , where X,Y are the two bytes of ax. So X get xored with Y, result Z
- is stored in ah, giving ZY as the new value of ax. Then al is ored with ah,
- result Q is stored in al giving ZQ as new value of ax. Then ax is negated
- and compared with FFE0. So we want XY to be a number that after the above
- steps equals FFE0... you dig? What is that number you say? Well i just
- decided to negate E0 (? -e0 in softice) and i got 20... So i looked in the
- general area of di which was 0x30 at the time (10th char of my code) and
- noticed further down a whole buch of 20 20 20 20 20... it became evident
- the necessary XY values were 20 and 20.
-
- There were 2 rows of 20: one starting at 0x5d going to 0x66 and
- one starting at 0x6d gonig to 0x76
-
- So the 10th char must be in that range!
-
- At this stage i typed r ax and entered ffe0 and then continued on:
-
- 0EE4:07F0 NOP
- 0EE4:07F1 NOP
- 0EE4:07F2 ADD CX,02 ;set counter=2
- 0EE4:07F5 MOV DI,AX ;ax=0000 from above... as you can see it was a good
- idea to change the value of the register as opposed to just reversing the
- jump or else it would have stuffed up here.
- 0EE4:07F7 LODSW
- 0EE4:07F8 OR AL,AH
- 0EE4:07FA SUB AL,AH
- 0EE4:07FC STOSB
- 0EE4:07FD LOOP 07F7
- 0EE4:07FF MOV CX,0002
- 0EE4:0802 PUSH DX
- 0EE4:0803 SUB DI,02 ;set di back to zero because of the loop
- 0EE4:0806 MOV AX,[DI] ;move contents of di into ax
- 0EE4:0808 DEC AX ;decrease ax by 1
- 0EE4:0809 OR BX,AX ;or the checksum (42d) with ax
- 0EE4:080B OR AX,BX ;or ax with the checksum
- 0EE4:080D SUB AX,24ED ;ax=ax-24ed
- 0EE4:0810 POP DX
- 0EE4:0811 JNZ 0859 ;jump bad guy if ax not equal to 24ed (Condition 3)
-
- This is pretty self explanatory. If you had changed the contents of the
- registers to what they were suppose to be instead of simply just reversing
- the jump, then ax would equal 24ed at the end.. no extra work required!
-
- 0EE4:0813 NOP
- 0EE4:0814 NOP
- 0EE4:0815 MOV SI,DX
- 0EE4:0817 LODSW
- 0EE4:0818 MOV BX,AX
- 0EE4:081A LODSW
- 0EE4:081B LOOP 0817
- 0EE4:081D SUB AX,BX
- 0EE4:081F SUB AX,01F8
- 0EE4:0822 JNZ 0859 ;jump bad_guy if ax not equal to zero (Condition 4)
-
- This is a simple check which does this:
-
- if ax-bx-0x1f8 not equal to zero, jump bad_guy... ax=RS, and bx=TU, where:
- R=char 8, S=char 7, T=char 6, U=char 5. So this is pretty braindead stuff,
- just make sure the above condition holds to bypass the protection section.
-
- i type r ax and entered 01f8 and continued tracing.
-
- 0EE4:0824 NOP
- 0EE4:0825 NOP
- 0EE4:0826 SUB SI,02
- 0EE4:0829 LODSW
- 0EE4:082A ADD AH,AL
- 0EE4:082C ADD AH,AH
- 0EE4:082E MOV BH,AH
- 0EE4:0830 LODSB
- 0EE4:0831 SUB AH,BH
- 0EE4:0833 JNZ 0859 ;jump if ah-bh not equal to zero (Condition 5)
- 0EE4:0835 NOP
- 0EE4:0836 NOP
- 0EE4:0837 CALL 0755
-
- This check is kinda pointless as it will never jump. Probably designed
- to fool crackers who have reversed all the previous jumps successfully and
- on reversing the last jump, it will stuff up!! So just step over that
- last JNZ and bang, RTQ's crackme says "WELL DONE".
-
- Part 4: Calculating a valid code
- ---------------------------------
-
- Well there are many codes that will work for this crackme. I only calculate
- a possible code.
-
- (1) satisfied condition 4:
-
- if ax-bx-0x1f8 not equal to zero, jump bad_guy... ax=RS, and bx=TU, where:
- R=char 8, S=char 7, T=char 6, U=char 5.
-
- i set ax=6941 and bx=6749. Hence, chars 5-8 of my code are: IgAi
-
- and 0x6941-0x6749=1f8, hence, condition satisfied.
-
- (2) satisfy condtion 0, 1, 2, 3 and 5
-
- well, we know the sum of the first 10 chars + length of code must equal 0x42d.
- also the 10th char must be >= 5d and <=66 or >=6d and <=76. and the code must
- be 11 chars long.
-
- So, it was just a simple matter of trial and error before i got a valid code:
-
- vvvvIgAizv!
-
- The hex ascii values of the letters are: v=76, I=49, g=67, A=41, i=69 and z=7a.
- The length of the code is 0xb. (condition 0 satisfied)
-
- So, 4(76)+49+67+41+69+7a+76=42d (condtion 1 satisfied)
-
- Then, the 10th char of the code is 0x76 which is within the valid range
- specified above. (condition 2 satisfied).
-
- The '!' can be any char, it's just a place holder to make sure the code is 11
- chars long.
-
- And that's it... simple eh?
-
- Part 5: Greetz
- ---------------
-
- Greetz fly out to the #cracking4newbies crew on efnet.
-
- Part 6: Conclusion
- -------------------
-
- I hope you enjoyed the tut. You can send me email to prophecy_@usa.net if you
- have any problems etc... -Prophecy (13th June 1998)
-
- Veni Vedi Vici.
-
-
- ------ end of soln ------
-
-