|
I want to explain you how to disable this quite good protection
and, in the second part,
how to perform the real crack of this target!
|
|
|
|
Well done mr. McClanahan ! I’ll have to work hard ! And only two days ago I decided to stop smocking !
Quickly searching for an iced beer and for a box of my favourite cigarettes
and I’m ready to restart my study from beginning.
Now I tried the ‘dead listing approach’ using WDASM and searching, trought
the IMPORTED FUNCTION, for one named EXITWINDOW or EXITWINDOWSEX and, as
you can see, the disassembler
shows me this interesting snippet of code :
* Possible StringData Ref from Data Obj ->"You shouldn't try to crack
shareware, "
->"what should I do with you?"
:0040429A 681C594600
push 0046591C
:0040429F 6A00
push 00000000
* Reference To: ADVAPI32.InitiateSystemShutdownA, Ord:00ACh
:004042A1 FF15C8F84600
Call dword ptr [0046F8C8]
:004042A7 81C4A8000000
add esp, 000000A8
:004042AD C3
ret
:004042AE 6A00
push 00000000
:004042B0 6A0D
push 0000000D
* Reference To: USER32.ExitWindowsEx, Ord:00CBh
|
:004042B2 FF1504FF4600
Call dword ptr [0046FF04]
:004042B8 81C4A8000000
add esp, 000000A8
:004042BE C3
ret
We can, of course, nopping the entire call but the next instruction
that adjusts the stack causes an error of page fault, and so I prefer to
change the CMP/JNE istruction you can find at :00404236
(see the reference).
:00404231 837C242402
cmp dword ptr [esp + 24], 00000002
:00404236 7576
jne 004042AE
like that :
:00404231 C644242402
mov dword ptr [esp + 24], 02
:00404235 90
nop
:00404236 90
nop
About the INITIATESYSTEMSHUTDOWNA we can do the same thing but I breakpointed
it, and, I don’t know why, the program never arrives to execute this call
! Strange but true !
We done a good step ahead so get on with it !
Launch the program and have a look at what happens...
Windownload starts and the check routine immediatly close it !
But, finally, it doesn’t reset the computer !
Launch the program again but this time through SoftICE, after breakpointing
the call to the API functions named POSTQUITMESSAGE and POSTMESSAGEA.
Everytime you jump into the ICE check with F4 if the program’s window
is on the screen or not and it will be easy to find out the guilty call
!
Here it is :
* Reference To: USER32.PostMessageA, Ord:01B1h
:00403DCC FF1508FF4600
Call dword ptr [0046FF08]
:00403DD2 56
push esi
:00403DD3 E8BEBB0200
call 0042F996
:00403DD8 83C404
add esp, 00000004
:00403DDB EB8B
jmp 00403D68
Nopping the call is enough to obtain a normal and full functional program,
that now is, more or less, like any other password protected shareware,
and you can work inside it without the loss of time the reboot routine
gives you.
I reckon this is the most interesting part of my essay
and I believe that even
a newbie could now crack this target successfully!
Anyway, for a little bit of glory
and for those who have a lazy brain I’m going to explain the
complete reverse
engineering of this program! Naturally you can jump over this second part
and try to do it yourself!
I don’t want to bore you explaining all attempts I’ve made before finding the right way, but you can probably immagine how many they were ! So I’ll explain to you only my last, winning, effort !
If you run a register monitor utility like REGMONEX before launching the program, you can obtain a lot of information about it, but the most interesting one is the underlined below :
Windownl OpenKey
HKCU\Software\WinDownload hKey:
0xC2B94B98 SUCCESS
Windownl CloseKey
HKCU\Software\WinDownload
SUCCESS
Windownl QueryValueEx
0xC2B94B98\Password
NOTFOUND
Windownl CloseKey
0xC2B94B98
SUCCESS
It’s easy to understand what that means? Isn’t it ?
The program looks for a string stored in your register which is, obviously, the password. Knowing that, we can easly hang the execution of the program just before the check routine, by setting a breakpoint each REGQUERYVALUEEX call and watching when the call is refered to the string mentioned above!
To understand this you have to know how the call at this API function
works :
Look at this snippet of code taken from the file WINDOWNLOAD.EXE :
:004498B9 50
push eax
; the parameters
:004498BA 57
push edi
; passed to the call
:004498BB 51
push ecx
; by the stack
:004498BC 57
push edi
:004498BD FF7510
push [ebp+10]
; look at this value
:004498C0 56
push esi
* Reference To: ADVAPI32.RegQueryValueExA, Ord:0136h
:004498C1 FF15C0F84600
Call dword ptr [0046F8C0]
:004498C7 8BD8
mov ebx, eax
:004498C9 85DB
test ebx, ebx
:004498CB 752B
jne 004498F8
The last value but one pushed into the stack is an indirect address
where you can find the string that the query are looking for, and, in particulary,
we must pay attention to it !
Well, all right ? Let’s open an iced beer and...go on in the right order !
The first thing to do is to open the REGEDIT.EXE and to create a subkey called ‘PASSWORD’ into the key HKEY_CURRENT_USER/Software/Windownload exactly where the program espects to find it, if not, the application will jump over the heart of the code where the checking routine is executed, and we will not be able to examine it ! And, logically, you must stuff it with a string you prefer, as well !
Next step is to run your SoftICE and breakpoint the REGQUERYVALUEEXA ( to do this remember to include in your WINICE.DAT the following string : EXP=C:\Windows\System\Advapi.dll ) and every time ICE stops, simply press F-12 to return from the call.
Just after ...25 or 30 times (patience is a great quality for a cracker), when your ashtray is full of cigarettes, you finally find out what you’re looking for exactly in the same snippet of code I used as my example before :
:004498BD FF7510
push [ebp+10]
; look at this value
:004498C0 56
push esi
* Reference To: ADVAPI32.RegQueryValueExA, Ord:0136h
:004498C1 FF15C0F84600
Call dword ptr [0046F8C0]
Really, you’ll land here two or three times, but you have to check where
the address stored in [ebp+10] point to, (use the Dump command), because
only when you find the occurance of string ‘PASSWORD’ you are at the end
of your effort !
Soon after you can see another call like the previous one because the
program, before, tests if the subkey is present and only if it is the next
one gets the value stored in.
C’mon guys ! We are on the right way !
After a few STEP (F-10) we arrive more or less here :
:00403923 E878FAFFFF
call 004033A0
:00403928 8B00
mov eax, dword ptr [eax]
:0040392A 8B4DDC
mov ecx, dword ptr [ebp-24]
:0040392D C645FC04
mov [ebp-04], 04
:00403931 8B40F8
mov eax, dword ptr [eax-08]
:00403934 8B11
mov edx, dword ptr [ecx]
:00403936 C645FC01
mov [ebp-04], 01
:0040393A 2B42F8
sub eax, dword ptr [edx-08]
; Check if your key’s lenght
:0040393D 83F801
cmp eax, 00000001
; are as the right one
:00403940 1BC0
sbb eax, eax  !
;
; 0 = OK let’s go on !
:00403942 40
inc eax
ß 1 = Bye ! Bye !
:00403943 8945D8
mov dword ptr [ebp-28], eax
:00403946 E80A030000
call 00403C55
:0040394B 837DD800
cmp dword ptr [ebp-28], 00000000
:0040394F 744F
je 004039A0
We are, now, in front of the first check the program made between your wrong key and it’s right one using the length of the string, so if you entered a password with a non correct number of chars you have to modify the flag Z ( r fl z in the command line of SoftICE) before the JE instruction at address 0040394F and you’d take note of the instructions just above the jump (this time it’s not necessary because I’ve done it for you !) .
After a little thinking about how to change the code in a permanent way I decided to proceed as follows to prevent a possible joke by the program more ahead.
:0040393D 83F801
cmp eax, 00000001
:00403940 1BC0
sbb eax, eax
:00403942 40
inc eax
Change to :
:0040393D B800000000
mov eax, 00000000
:00403942 90
nop
Let’s go on ! (I have my third beer).
If you correctly do the jump and advance a little you’ll find yourself here :
:00403A1D E87EF9FFFF
call 004033A0
:00403A22 C645FC08
mov [ebp-04], 08
:00403A26 8B4DDC
mov ecx, dword ptr [ebp-24]
:00403A29 8B55F0
mov edx, dword ptr [ebp-10]
:00403A2C 8B19
mov ebx, dword ptr [ecx]
:00403A2E C645FC01
mov [ebp-04], 01
:00403A32 8A0C13
mov cl, byte ptr [ebx + edx]
; Get one byte of your key
:00403A35 884DEC
mov byte ptr [ebp-14], cl ; Store it
in a temporary address
:00403A38 8B00
mov eax, dword ptr [eax]
:00403A3A 8B55F0
mov edx, dword ptr [ebp-10]
:00403A3D 320C10
xor cl, byte ptr [eax + edx]
; Check it with the right key
:00403A40 884DEC
mov byte ptr [ebp-14], cl
; Store it in a temporary address
:00403A43 E867000000
call 00403AAF
:00403A48 0FBE4DEC
movsx ecx, byte ptr [ebp-14]
:00403A4C 85C9
test ecx, ecx &nbs!
p;
; Test if the result is 0
:00403A4E 7508
jne 00403A58 ß if
not jump out
:00403A50 FF45F0
inc [ebp-10]  !
;
; If yes increase the pointer and repeat
:00403A53 E94FFFFFFF
jmp 004039A7
This is the heart of the test routine and you can notice the strange way to compare the single item.
Only if the two chars are the same the XOR instruction give back the 0 result it’s waiting for, and so, we have to change it with XOR [ebx + edx] in so as now the program compare your password with itself indipendently of whatever it is, and give us the green trafic light !
I wanna underline that you can find the right password of your copy of WINDOWNLOAD, simply searching where the register EAX + EBX are pointing to when you arrive just before the first XOR instruction, but I dont’ work for a warez site, and I like to reverse the code to the end and make it completely functional with every password.
Follow me ! There’s only a few streets to walk !
Now we’ll encounter only another two hurdle before winning our match !
Here they are :
The 1st
:00403AEA E8C1810100
call 0041BCB0
; Compare the two string
:00403AEF C645FC01
mov [ebp-04], 01
:00403AF3 83C408
add esp, 00000008
:00403AF6 83F801
cmp eax, 00000001
:00403AF9 1BC0
sbb eax, eax
:00403AFB 40
inc eax
:00403AFC 8945D8
mov dword ptr [ebp-28], eax
; Store the result temporarly
:00403AFF E831010000
call 00403C35
:00403B04 837DD800
cmp dword ptr [ebp-28], 00000000
; Zero ? OK !
:00403B08 744F
je 00403B59
The 2nd
:0403B8C E81F810100
call 0041BCB0
; Compare the two string
:00403B91 83C408
add esp, 00000008
:00403B94 8B4DE4
mov ecx, dword ptr [ebp-1C]
:00403B97 C645FC01
mov [ebp-04], 01
:00403B9B 83F801
cmp eax, 00000001
:00403B9E 194DE4
sbb dword ptr [ebp-1C], ecx
:00403BA1 F75DE4
neg [ebp-1C]
:00403BA4 E87C000000
call 00403C25
:00403BA9 837DE400
cmp dword ptr [ebp-1C], 00000000 ; Zero ?
BAD !
:00403BAD 741F
je 00403BCE
:00403BAF C645FC00
mov [ebp-04], 00
In both cases the program uses a little subroutine to compare two strings
but if you disassemble the file with WDASM you can observe that, that call
is used in many other sides of the program and so we can’t modify it or
the results it gives back !
The only thing to do is to change the answer of the program in front
of a bad result by modifing it after the call, as shown below :
About the first you have to nopping the INC EAX instruction to obtain
a zero result !
:00403AFB 40
inc eax
Change to : 00403AFB 90
nop
About the second it’s unnecessary to work around the result, it’s enough
to change the jump instruction with a (typical nopping) INC EAX, DEC EAX
:00403BAD 741F
je 00403BCE Change to :
00403BAD 40 inc eax
00403BAE 48 dec eax
|
I hope you’ll find my essay interesting and helpful!
Thanks to all who helped me to bring about my little work
with their great tutorials and essays, death to all the useless wannabye
crackers groups
that don't teach anything and only leech material from the good sites
Search : Change :
C645FC012B42F883F8011BC040
B80000000090
884DEC8B008B55F0320C10884D
320C13
C645FC0183C40883F8011BC040
B80000000090
837DE400741FC645FC00E8AD00
4048
85C00F8487000000837C2424027576
C6442424029090
FF1508FF460056E8BEBB0200
404840484048
|