Target: | Hyperionics Hypersnap-DX v3.30.00 |
Difficulty: | Easy |
Tools used: | SoftIce SmartCheck Your favourite hex editor |
Date: | 14-03-'99 |
Section: | Other reverse engineering essays |
PLEASE KEEP IN MIND THE FOLLOWING!
1) The essence of this essay isn't about the serial protection scheme of Hypersnap but about it's
anti-debugging trick and about it's CRC check.
2) When you install Hypersnap-DX, make sure softice isn't resident, otherwise Hypersnap won't
install properly.
Poppin the hood.
When you try firing up HSDX.EXE while softice is resident you'll notice it won't start. How come?
To answer that question we have to know what the program does before it quits. So how are we going
to find that out? Well we'll have to use a program flow analyser and what's the best program
flow analyser we know? Smartcheck! Ok fire up smartcheck and open HSDX.EXE (make sure supress system
API and OLE calls is off), press the play button and after Smartcheck is finished click on the show
all events button. We want to know which API calls we're called right before the exitprocess call.
So scroll to the end of the list and take a good look around. Hmm OuputDebugStringA and CreateFileA
with lpFileName pointing to \\.\SICE ?? Very suspicious don't you think ? Let's see what the API
says about the return value of OuputDebugStringA. Hmm the API says it doesn't return shit so it has
to be the CreateFileA call that does the trick. Let's put a bpx on OutputDebugStringA (since using
CreateFileA will cause softice to pop up a lot of times). Ok now start Hypersnap and... bang! Back
in Softice. Press F12 to get out of the call, and this is what you'll see:
* Reference To: KERNEL32.OutputDebugStringA, Ord:01F5h
|
:6302120F FF1540500263 Call dword ptr [63025040]
:63021215 55 push ebp
:63021216 6880000000 push 00000080
:6302121B 6A03 push 00000003
:6302121D 55 push ebp
:6302121E 6A03 push 00000003
:63021220 68000000C0 push C0000000
:63021225 68F0670263 push 630267F0
:6302122A FFD3 call ebx ; CreateFileA
:6302122C 83F8FF cmp eax, FFFFFFFF ; Is SI resident?
:6302122F 7406 jz 63021237 ; if so exit else continue
:63021231 55 push ebp
:63021232 E8D6060000 call 6302190D
Hmmz the only thing we have to do is change the jz at 6302122F to a jmp by changing 7406 into EB06.
Fire up your favorite hex editor, make the change, fire up HSDX.EXE and... DONE! It works!
There's also a check for NTICE a bit further down the code and it works exactely the same, so it
shouldn't be a problem to disable that one too. So what's up next?
Removing the CRC check.
If you try to make a change in HSDX.EXE and try running it afterwards you'll get a message box saying
something like:"Can't load Hshelper.DLL". How come? Well probably Hypersnap uses some kind of CRC
protection to keep the program from being changed. So how are we going to remove it? Simple we want
to know the difference between what the program does when it encounters an incorrect CRC and what it
does when it encounters a correct CRC. So how are we going to do that? Smartcheck! We can use it to
compare the differences between the flow of Hypersnap when HSDX.EXE is changed and when HSDX.EXE isn't
changed.
Ok first open the unchanged HSDX.EXE in smartcheck, run the program and save the results. Next change a
string in HSDX.EXE using your hex editor. Open it in smartcheck and run the program, open the saved
results of HSDX.EXE running unchanged. Tile the result windows and compare the differences (could it
get any easier ? :-) You'll soon see the first difference between both flows, it occurs when the
ReadFile loop is finished. In the unchanged version it calls the API call CloseHandle, in the changed
version it doesn't call it. So what are we going to do? We're going to put a bpx on OuputDebugStringA
(the ReadFile loop comes right after the OutputDebugStringA) get out of the loop and look for jumps
that will take us out of the call. Using this method you'll soon get here:
:63021329 8815E5670263 mov byte ptr [630267E5], dl
:6302132F 8B1544600263 mov edx, dword ptr [63026044] ;load the CRC in edx
:63021335 33D5 xor edx, ebp ;edx xor ebp = esi
:63021337 33D6 xor edx, esi
:63021339 740F je 6302134A ;if edx = esi CRC is correct
:6302133B 5F pop edi
:6302133C 5E pop esi
:6302133D 5D pop ebp
:6302133E 33C0 xor eax, eax
:63021340 5B pop ebx
:63021341 81C404040000 add esp, 00000404
:63021347 C20C00 ret 000C
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:63021339(C)
|
:6302134A 8A4006 mov al, byte ptr [eax+06]
Hmm it's pretty simple to solve that problem, you could for example change the je in a jmp by changing
740F into EB0F. There are many more ways of solving this problem ofcourse but hey we don't care
about that do we?
For suggestions,corrections or just to say hello mail me at:
douby(at)newmail(dot)com
Or visit us at #dread on EFNET.
Have fun.
DREAD is NOT responsible for any abuse of the information we provide. Members of DREAD don't crack to get programs registered. As a matter of fact, we don't crack at all, since we are reverse engineers. Our only objective is to further our knowledge. If you want to use a program you reversed, you have to buy it!
This essay is © copyright 2000 by douby.