Cracking HEdit 2.0
(using wdasm as a debugger)
(19 August 1997, slightly edited by Reverser)
With an addition by itzMagik1, 4 January 1998
Cracking HEdit version 2.1.11
Courtesy of Reverser's page of reverse engineering
Well, this essay is interesting, for me, because it's the first time that somebody explains how to use Urbanik's disassembler as a "quick and dirty" debugger tool... now, you see, I mostly disassemble files in order to reverse engineer them, and use winice only if really compelled (why burn your eyes on a screen, as +ORC said, when you can crack relaxed in the shadows of your garden, sipping a good cocktail in fresh air?) so the idea of "remaining" inside wdasm to try a couple of probes is not bad at all...
Besides, HEdit is an hexeditor, and for hexeditors the chase is always open!
Yet I'm not happy that an +HCUker "leaves" a crack part to others... PROFESSIONAL PRIDE! If you're a +cracker (or if you want to be one) you should finish your cracks! Therefore I expect an addition to this essay FROM x86 (and nobody else :-)
ADDITION: 20 August 1997. ...and I got it! Good x86, right so +cracker! You'll find it as second part of this essay!
There is also an addition by itzMagik1, 4 January 1998
Cracking HEdit version 2.1.11
Cracking HEdit 2.0
HEdit 2.0 can be found at:
This is my first essay, and I'm still a bit of a beginner, so bear with
me. I decided to do this crack using AS A DEBUGGER wdasm 8.9
instead of SoftIce, simply for a change of pace, and to show how the code
patch utility can be quite a time saver for trying out cracks on the fly.
This protection scheme is really stupid, given the amount of code dedicated
to the registration routines (more on that later).
I started HEdit to get an idea of what I was dealing with. No opening
nag screen, that's nice. Close it down, still no nag screen.
Hmmm, what is there to crack?
Set my clock ahead 1 month, and bingo. A nice message telling me my
14 day trial had expired.
- A quick aside here-
I started off trying to crack the registration functions of the program,
looking for the typical 'cmp good, bad' and 'test eax, eax'.
To make a long story short, this program goes through tons of convoluted
checks all over the place, and after about an hour, I decided screw it.
I'll leave that to one of our more experienced crackers, and besides, once
you crack the time-check mechanism, you're in home free.
So, now we look for the call to Kernel32.GetLocalTime (see, I have
learned something!). There is only one and the code around it looks like
* Reference To: KERNEL32.GetLocalTime, Ord:00E2h
:00409CFC FF1524A94400 Call dword ptr [0044A924]
:00409D02 8D4C2404 lea ecx, dword ptr [esp+04]
:00409D06 51 push ecx
* Reference To: KERNEL32.GetSystemTime, Ord:0121h
:00409D07 FF151CA94400 Call dword ptr [0044A91C]
:00409D0D 668B0DDA7D4400 mov cx, word ptr [00447DDA]
:00409D14 66394C240E cmp word ptr [esp+0E], cx
:00409D19 753C jne 00409D57
:00409D1B 66A1D87D4400 mov ax, word ptr [00447DD8]
:00409D21 663944240C cmp word ptr [esp+0C], ax
:00409D26 752F jne 00409D57
:00409D28 66A1D67D4400 mov ax, word ptr [00447DD6]
:00409D2E 663944240A cmp word ptr [esp+0A], ax
:00409D33 7522 jne 00409D57
:00409D35 66A1D27D4400 mov ax, word ptr [00447DD2]
:00409D3B 6639442406 cmp word ptr [esp+06], ax
:00409D40 7515 jne 00409D57
:00409D42 66A1D07D4400 mov ax, word ptr [00447DD0]
:00409D48 6639442404 cmp word ptr [esp+04], ax
:00409D4D 7508 jne 00409D57
:00409D4F 8B15C87D4400 mov edx, dword ptr [00447DC8]
:00409D55 EB46 jmp 00409D9D
By tracing where this code goes, we eventually get a 'ret' and end up
* Reference To: ADVAPI32.RegQueryValueExA, Ord:00E1h
:00403D55 FF154CA74400 Call dword ptr [0044A74C]
:00403D5B 85C0 test eax, eax
:00403D5D 0F85DE000000 jne 00403E41
:00403D63 83EC04 sub esp, 00000004
:00403D66 8965D0 mov dword ptr [ebp-30], esp
:00403D69 FF75EC push [ebp-14]
:00403D6C 8B4DD0 mov ecx, dword ptr [ebp-30]
:00403D6F E8C5020000 call 00404039
:00403D74 8D45E0 lea eax, dword ptr [ebp-20]
:00403D77 8D4DD4 lea ecx, dword ptr [ebp-2C]
:00403D7A 50 push eax
:00403D7B 51 push ecx
:00403D7C E826320100 call 00416FA7
:00403D81 8BC8 mov ecx, eax
:00403D83 E8BC020000 call 00404044 *** <-- Return here
:00403D88 B980510100 mov ecx, 00015180
:00403D8D 8B45E0 mov eax, dword ptr [ebp-20] <--How many days
:00403D90 99 cdq ; used so far?
:00403D91 F7F9 idiv ecx
:00403D93 83F80E cmp eax, 0000000E <--Less than 15?
:00403D96 0F8E4BFFFFFF jle 00403CE7 <--Good boy!
:00403D9C 6A00 push 00000000
:00403D9E 83F81C cmp eax, 0000001C
:00403DA1 7D33 jge 00403DD6
:00403DA3 8D8D78FFFFFF lea ecx, dword ptr [ebp+FFFFFF78]
:00403DA9 E8120F0000 call 00404CC0
:00403DAE C645FC01 mov [ebp-04], 01
:00403DB2 8D8D78FFFFFF lea ecx, dword ptr [ebp+FFFFFF78]
:00403DB8 E88E6A0100 call 0041A84B
:00403DBD C645FC00 mov [ebp-04], 00
:00403DC1 E805000000 call 00403DCB
:00403DC6 E91CFFFFFF jmp 00403CE7
Now we know what to do! Make this a "jump always", and use the target as long as you want.
To test this theory, set a break point on 00403d96. Run the program and when it breaks, hit
the 'Patch Code' button which is on the lower-right debug window. It will show you the
instruction at the current EIP. In the window below it, type in what you want it to be, in
this case 'jmp 00403ce7'. Hit the 'apply patch' button. Now, notice that the new instruction
is only 5 bytes, where we had 6 originally. So, once again, in the same window you entered
the new jump, enter 'nop'. Now its 6 bytes and all is well. Apply that patch, and hit the
'run' button to test it out. Works like a champ. Ok, so HEdit is all yours for as long as you
want it now. I wanted to show that although most of the time SoftIce is the superior debugger,
W32Dasm does have some very nice features for debugging as well. I know that the same thing
(code patching) can be done under SoftIce as well, but I find it pretty useful to patch our
targets with wdasm. All that's left is to edit the HEdit executable (since the code
"patch.class" is temporary) as follows:
At offset 3196h:
Change 0F8E4BFFFFFF To E94CFFFFFF90
I leave it to the more experienced (or at least those with more time!) to crack the
registration function. Till next time, happy cracking x86
And this is the SECOND part to this session, that x86 sent me one day
later (see: constructive critics works! :-)
'Professional pride', ouch! Got me where it hurts! :)
Anyway, here is the addition to my previous essay. It's now fully cracked,
and (hopefully!) no lame copouts.
Cracking HEdit 2.0 Part II
Ok, Reverser had a good point, I should've finished what I started! I am so
ashamed! Well, rest assured it won't happen again.
Ok, on to the crack. This addendum to my original essay targets the
registration functions of HEdit 2.0 and will allow you to enter any
name/number you want and be fully registered.
I should point out that this crack actually supercedes my previous one,
in that this crack will automatically take care of the expiration problem
since the program will actually think you entered a valid registration
There are a couple of different approaches to consider. You can try to
figure out how the program decides if you are registered (what I originally
tried to do... don't bother) or you can attack the registration key
encrypt/decrypt section directly, which is what we will do!
Once again, I'll be using Wdasm as a debugger to try my patches on the fly,
so load up HEdit and follow along.
To start, I tried to find out what happened when I entered an invalid
I got the message, "The user name and/or registration number you entered
Ok, Wdasm has a string reference listing of all the strings in the data
section, so let's see if we can find a match. Sure enough, and there
are 3 occurrences of it.
Let's set breakpoints on each one, and run the program again.
Enter a name and number into the registration box (Help/About/Register)
and Wdasm will break here:
* String: "The user name and/or registration number you entered are inc"
:00405099 6888000000 push 00000088
:0040509E E8BCFC0100 call 00424D5F ? Display bad msg
:004050A3 EB14 jmp 004050B9 ? Bye bye, try again
We know something is triggering this message so let's find it.
We don't need to look far.
Right above lies this code snippet:
:0040506B 56 push esi
:0040506C 57 push edi
:0040506D 8BF1 mov esi, ecx
:0040506F E808AE0200 call 0042FE7C
:00405074 8B7804 mov edi, dword ptr [eax+04]
:00405077 6A01 push 00000001
:00405079 8BCE mov ecx, esi
:0040507B E870890100 call 0041D9F0
:00405080 85C0 test eax, eax
:00405082 7435 je 004050B9
:00405084 FF7660 push [esi+60] ? The number you entered
:00405087 FF765C push [esi+5C] ? The name you entered
:0040508A 8BCF mov ecx, edi
:0040508C E82DEFFFFF call 00403FBE ? Main reg. check routine!
:00405091 85C0 test eax, eax ? eax != 0 means `Go boy'!
:00405093 7510 jne 004050A5
:00405095 6AFF push FFFFFFFF ? Begin beggar off routine.
:00405097 6A00 push 00000000
Now, at this point, you might be tempted to say, "Hey, we can just change
the jne instruction to a jmp, and away we go!" Well, go ahead and try it,
it won't work.
This is why my previous approach was such a lame way to go.
There are other checks in this program besides this one, so what we need
to do is to crack the main registration checking routine.
Let's have a look.
* Referenced by a CALL at Addresses:00403A3D, :00403CDE, :00403E07, :0040508C
:00403FBE 55 push ebp
:00403FBF 8BEC mov ebp, esp
:00403FC1 81EC00010000 sub esp, 00000100
:00403FC7 6800010000 push 00000100
:00403FCC 8D8D00FFFFFF lea ecx, dword ptr [ebp+FFFFFF00]
:00403FD2 FF7508 push [ebp+08]
:00403FD5 51 push ecx
:00403FD6 E8054F0000 call 00408EE0
:00403FDB 83C40C add esp, 0000000C
:00403FDE 8D8D00FFFFFF lea ecx, dword ptr [ebp+FFFFFF00]
:00403FE4 51 push ecx
:00403FE5 E856200100 call 00416040
:00403FEA 83C404 add esp, 00000004
:00403FED B904000000 mov ecx, 00000004
* Referenced by a Jump at Address:00404015
:00403FF2 8BC1 mov eax, ecx
:00403FF4 41 inc ecx
:00403FF5 99 cdq
:00403FF6 33C2 xor eax, edx
:00403FF8 2BC2 sub eax, edx
:00403FFA 83E003 and eax, 00000003
:00403FFD 33C2 xor eax, edx
:00403FFF 2BC2 sub eax, edx
:00404001 8A940DFFFEFFFF mov dl, byte ptr [ebp+ecx-00000101]
:00404008 30940500FFFFFF xor byte ptr [ebp+eax-00000100], dl
:0040400F 81F900010000 cmp ecx, 00000100
:00404015 7CDB jl 00403FF2
:00404017 8B8500FFFFFF mov eax, dword ptr [ebp+FFFFFF00]
:0040401D 85C0 test eax, eax
:0040401F 7D02 jge 00404023
:00404021 F7D8 neg eax
* Referenced by a Jump at Address:0040401F
:00404023 39450C cmp dword ptr [ebp+0C], eax ***Here! [ebp+0C]
:00404026 7509 jne 00404031 is what the num.
:00404028 85C0 test eax, eax should be and eax
:0040402A B801000000 mov eax, 00000001 is what you
:0040402F 7502 jne 00404033 entered.
* Referenced by a Jump at Address:00404026
:00404031 33C0 xor eax, eax
* Referenced by a Jump at Address:0040402F
:00404033 8BE5 mov esp, ebp
:00404035 5D pop ebp
:00404036 C20800 ret 0008
Ok, so here is what happens. If your number doesn't match what is
expected, the jump to xor eax, eax is executed (remember, the program
expects a non-zero return in eax if the registration number is correct).
If it does match and isn't zero, 1 gets put into eax and we return and
all is well.
So, what we need to do is skip the bad jump if our numbers don't match.
Let's test it to make sure.
Clear all of the breakpoints and set a new one at 00404026 and run it,
and enter something for the name/number. When Wdasm breaks, use the code
patch utility to change the `jne 00404031' to `nop, nop'.
Apply the patch and hit `run'. Presto! You are regged!
Summary of the crack:
Change 75 09
To 90 90
You can use this crack rather than my previous one.
Once again, sorry for my temporary lameness.
I'm going to give myself 0x28 lashes and send myself to
bed with no dessert! Until next time-
Here is an addition to this essay by
itzMagik1, added on 4 Jnuary 1998
Cracking HEdit version 2.1.11
Written by itzMagik1 on December 30, 1997.
Contact itzMagik1(at)aol(point)com for questions/comments.
Introduction: This is my first crack for the +HCU.
Granted it's not very hard, but everyone has to start somewhere.
The crack for HEdit version 2.1.11 was relatively simple thanks
to x861's earlier essay, Cracking HEdit 2.0, that you can read
Tools Required: Windows Disassembler 8.x
A hex editor (why not use HEdit 2.1.11)
SoftIce (or WDASM for debugging)
Program History: HEdit 2.1.11 uses the same protection scheme as it's previous
version. I've never used anything before that, so I can't describe it's
Let's get right to the crack. Start up HEdit, then click Help, then about
HEdit. Notice the button that says register. I love programs that have this
button: they are so easy to crack. Click the button. You'll get another dialog
with a place for your name and registration number. Type your name in the
first box and a 1 in the second. Click OK. You'll see some long, drawn out
error message about how your "registration" number isn't correct. That's our
Now Run hedit.exe through WDASM. I think it's a good disassembler, but it's
not the best debugger, so I'll use SoftIce. Search for the word
"registration." You should find it 3 times. I set breakpoints on each one in
SoftIce (BPX 004017CF, 00402239, 004353DA). Now load it into SoftIce. When
SoftIce breaks, you'll land at 00402239. Here's what you'll see:
:00402239 push 00000088
:0040223E call 00427930
In WDASM, that corresponds to:
* Referenced by Jump at Address:0040221A(C)
:00402235 6AFF push FFFFFFFF
:00402237 6A00 push 00000000
* Possible Reference to "The user name....."
:00402239 6888000000 push 00000088
:0040223E E8ED560200 call 00427930 - display bad message
Let's see where this is getting called from. Look up a few lines and you'll
:00402209 8B4660 mov eax, dword ptr [esi+60] - The number you entered
:0040220C 8B4E5C mov ecx, dword ptr [esi+5c] - The name you entered
:0040220F 50 push eax
:00402210 51 push ecx
:00402211 8BCF mov ecx, edi
:00402213 E878170000 call 00403990 - Call the registration check routine
:00402218 85C0 test eax, eax - If eax != 0, you're good
:0040221A 7419 je 00402235
As with the previous HEdit, it does the same thing. How do we fix this?
The main registration routine is exactly the same as in the previous version.
All we have to do is search for the block of code that checks what you entered
versus what the number should be. Lucky for us, x861 has already provided it
for us. Here's the code:
* Referenced by Jump at Address:004039ED(C)
:004039F1 3B84240C010000 cmp eax, dword ptr [esp+0000010C] - What you entered
vs the "correct" number
:004039F8 7513 jne 00403A0D - You're gone
:004039FA 85C0 test eax, eax
:004039FC 740F je 00403A0D - You're good
:004039FE B801000000 mov eax, 00000001
:00403A03 5B pop ebx
:00403A04 81C400010000 add esp, 00000100
:00403A0A C20800 ret 0008
* Referenced by Jump at Address 004039F8(C), :004039FC(C)
:00403A0D 33C0 xor eax, eax
:00403A0F 5B pop ebx
:00403A10 81C400010000 add esp, 00000100
:00403A16 C20800 ret 0008
What happened in HEdit 2.0 also happens here. If you're number isn't
"correct," the jump to xor eax, eax is executed and you're done. If it does
match, 1 gets put into eax and you're registered. So we can change the jne to
nop. Here's the crack:
At Offset 0x00002DF8
Change 75 13
To 90 90
Once changed, you can use any name and registration number you want.
HEdit 2.1.11 can be downloaded from http://www.yurisw.com/hedit/download.htm.
Hope you enjoyed this easy crack. Thanks to x861 for his previous essay.
Hopefully you'll see more of my essays in the future. I'll aim for something a
little more difficult next time.
(c) itzMagik1 1998. All rights reversed
(c) x86 1997. All rights reversed
You are deep inside reverser's page of reverse engineering, choose your way out:
Back to project 1 (tools of the trade)
Is reverse engineering legal?