My final post
Sunday, 30-May-1999 16:07:08
I promissed Eternal Bliss I'll post a tutorial,so here is something pretty close to it (I don't have time to explain how to revers the check routine)
First, load the exports from ddraw.dll
To get in "bpx directdrawcreate"
softice will break :
0137:004018DE RET <=look here 0137:004018DF PUSH EBP 0137:004018E0 MOV EBP,ESP 0137:004018E2 PUSH ECX 0137:004018E3 PUSH 00 0137:004018E5 LEA EAX,[EBP-04] 0137:004018E8 PUSH EAX 0137:004018E9 PUSH 00 0137:004018EB CALL DDRAW!DirectDrawCreate 0137:004018F0 PUSH EAX <=you are here 0137:004018F1 CALL 00403545 0137:004018F6 ADD ESP,04 0137:004018F9 PUSH 11 0137:004018FB MOV ECX,[004063B8] 0137:00401901 PUSH ECX 0137:00401902 MOV EDX,[EBP-04] 0137:00401905 MOV EAX,[EDX] 0137:00401907 MOV ECX,[EBP-04] 0137:0040190A PUSH ECX 0137:0040190B CALL [EAX+50] 0137:0040190E PUSH EAX
the RET instructions means that we are inside a function,so get out of it: F12
0137:004023E0 PUSH 00 0137:004023E2 PUSH 004037D0 0137:004023E7 CALL [004050B8] 0137:004023ED ADD ESP,0C 0137:004023F0 CALL 004018DF 0137:004023F5 TEST EAX,EAX <=you land here 0137:004023F7 JZ 00402410 <=did DirectDrawCreate Succeed ? :) 0137:004023F9 PUSH 004061AC 0137:004023FE CALL 00403834 0137:00402403 ADD ESP,04 0137:00402406 MOV EAX,00000001 0137:0040240B JMP 004027F0
trace through the code,using F10,until here:
0137:00402721 PUSH 000000AF <=you are here 0137:00402726 PUSH 000000D2 0137:0040272B PUSH 0000008C 0137:00402730 PUSH 00406278 0137:00402735 CALL 00402F89<=displays "SECURITY CODE" 0137:0040273A ADD ESP,10 0137:0040273D PUSH 00
now take a look at the code that's going to be executed:
0137:004027B0 PUSH 00 0137:004027B2 PUSH 00 0137:004027B4 PUSH 00 0137:004027B6 LEA ECX,[EBP-4C] 0137:004027B9 PUSH ECX 0137:004027BA CALL [USER32!GetMessageA] <=a translatemessage/dispatchmessage loop 0137:004027C0 TEST EAX,EAX 0137:004027C2 JZ 004027DF 0137:004027C4 LEA EDX,[EBP-4C] 0137:004027C7 PUSH EDX 0137:004027C8 CALL [USER32!TranslateMessage] 0137:004027CE LEA EAX,[EBP-4C] 0137:004027D1 PUSH EAX 0137:004027D2 CALL [USER32!DispatchMessageA] 0137:004027D8 CALL 00403FD0 0137:004027DD JMP 004027B0 0137:004027DF MOV ECX,[EBP+08] 0137:004027E2 PUSH ECX 0137:004027E3 PUSH 0040628C 0137:004027E8 CALL [USER32!UnregisterClassA] 0137:004027EE XOR EAX,EAX 0137:004027F0 MOV ESP,EBP 0137:004027F2 POP EBP 0137:004027F3 RET 0010
Now how to get to the function that processes te messages: Notice that when you press a key,a * is displayed,so we got to find where this * is stored in memory. Look at the code:
0137:00402730 PUSH 00406278 <=interesting value to push :) 0137:00402735 CALL 00402F89<=displays "SECURITY CODE"
so "db 406278"
there you should find all the strings displayed,including the '*' character.Notice all strings start with a funny character (so W32dasm doesn't recognise them as strings :). BPR on the memory location of the '*' (in my case "bpr 406294 406296 rw"):
0137:78002A97 ADD EAX,00000000 0137:78002A9C MOV EAX,[ECX] <=you land here 0137:78002A9E MOV EDX,7EFEFEFF 0137:78002AA3 ADD EDX,EAX 0137:78002AA5 XOR EAX,-01
press F10 twice to get to the WndProc:
0137:004027F3 RET 0010 <=first ret 0137:004027F6 PUSH EBP <=start of WndProc 0137:004027F7 MOV EBP,ESP 0137:004027F9 SUB ESP,08 0137:004027FC MOV EAX,[EBP+0C] 0137:004027FF MOV [EBP-08],EAX 0137:00402802 CMP DWORD PTR [EBP-08],1C 0137:00402806 JZ 00402816 0137:00402808 CMP DWORD PTR [EBP-08],00000100 0137:0040280F JZ 0040288F 0137:00402811 JMP 004029C8 ....................................................... 0137:004028DB CALL 00402F89 0137:004028E0 ADD ESP,10 <=you land here 0137:004028E3 JMP 004029C8 0137:004028E8 JMP 004029C8
At the start of the WndProc,there are some conditional jumps (402816,40288f).EBP-8 in the message recieved.
bpx 40288f,and enter a code (Sice will break at every character pressed but trace through the code only when you have pressed RETURN).
0137:0040288F CMP DWORD PTR [EBP+10],2F <=you land here 0137:00402893 JBE 004028ED <=this jump will be taken if you press 0137:00402895 CMP DWORD PTR [EBP+10],7B 0137:00402899 JAE 004028ED 0137:0040289B CMP DWORD PTR [0040651C],0D
so:
0137:004028ED CMP DWORD PTR [EBP+10],0D 0137:004028F1 JNZ 004029C8 0137:004028F7 CMP DWORD PTR [0040651C],00 0137:004028FE JLE 004029C8 0137:00402904 CALL 00401DCA <=trace until here 0137:00402909 TEST EAX,EAX 0137:0040290B JNZ 004029BB <= NOTICE THE CONDITIONAL JUMP :)
Try to take the jump at 40290B and you'll see a congrat. message (unfortunately the colors are screwed if you do this :( ) so th function at 401dca is the checkfunction.
0137:00401DCA PUSH EBP 0137:00401DCB MOV EBP,ESP .................. 0137:00401E3A MOV CL,[00406518] <=important 0137:00401E40 CDQ 0137:00401E41 IDIV ECX .................... 0137:00402023 CMP ECX,EAX 0137:00402025 JZ 0040202B <= good guy,badguy :) 0137:00402027 XOR EAX,EAX 0137:00402029 JMP 00402032 0137:0040202B JMP 00401FFE 0137:0040202D MOV EAX,00000001 0137:00402032 POP EDI 0137:00402033 POP ESI 0137:00402034 POP EBX 0137:00402035 MOV ESP,EBP 0137:00402037 POP EBP 0137:00402038 RET
After reversing this function,you will find out there is NO valid code.So start searching for some anti-debuging tricks. There are 3 non-local variables used: Security code Hardcoded code weird variable [406518]
so "bpm 406518 rw" and start again
SICE will break here:
0137:00403EF4 PUSH ESI 0137:00403EF5 PUSH EDI 0137:00403EF6 MOV AH,43 0137:00403EF8 INT 68 <= SICE check !!! 0137:00403EFA CMP AX,F386 0137:00403EFE JNZ 00403F15 0137:00403F00 JMP 00403F02 0137:00403F02 MOV BYTE PTR [00406518],26 <= you are supposed to be here 0137:00403F09 MOV DWORD PTR [0040611C],00000000 0137:00403F13 JMP 00403F26 0137:00403F15 MOV BYTE PTR [00406518],34 <= you are here 0137:00403F1C MOV DWORD PTR [0040611C],00000032 0137:00403F26 POP EDI 0137:00403F27 POP ESI
after bypassing this protection,you will be able to find the right code :)
hope this helps, Andy
Andy^
|