RegSpy v1.51 - Patched


by NchantA [PGC]


Published by +Tsehp July 2001


Current URL:


tools needed:


- PeEditor

- Windasm / IDA

- softice ;)


- Win 32 API List

- icedump (optional)


Sorry for the extravagant list of tools, but they were all used. They can all be found at or or ;P


this program looks nice, when its not crashing ;P another handy util that may eventually equal regmon, it certainitly has a nicer interface ;)




Finally! a protection a little different from the rest.


I found this protection interesting, very different from the rest, so to me it was tutorial worthy ;)


Attack! I installed the program and got straight down to business. Enable icedump (just in case it has some fucked up anti-softice code. Hi Bi-Tarts!)


hrmm a handy nag (note this as a possible attack point), press ‘try’ and continue, loads fast, nice program :o)


goto Help->About and check it out, unregistered (of course), wow, It has a place to enter a serial! Well nothing too it, set a bpx hmemcpy after u type in a serial and before u press OK. Hit OK. It breaks here:


* Reference To: USER32.GetDlgItemTextA, Ord:0107h


:00409329 FF152C444200              Call dword ptr [0042442C]

// compares your serial with nothing:

:0040932F 803E00                           cmp byte ptr [esi], 00     

// if it is, then bugger off:

:00409332 741C                               je 00409350

// if you typed in anything, pop up message box:

:00409334 8B4F04                           mov ecx, dword ptr [edi+04]

:00409337 6A00                               push 00000000

:00409339 6888A74200                   push 0042A788


* Possible StringData Ref from Data Obj ->"Thank you for registration"


Well that sux. You have to restart to see if its registered, this generally means that the serial check is somewhere in the programs initialization code.


No matter. We simple have to find another place to attack! Before u read on, I would like anyone blindly following this tutorial to have a solid go at:


- patching the program so its registered

- finding a valid serial (for your computer ?????)

- keygening it


I personally took the easy way out by stopping after step one, but thats laziness and not ignorance (I hope haha).


Have u had a go at cracking this? Failed miserably? Keygenned it without problem? Oh well no matter, continue reading for one of the many many possible solutions.




Allright. Now my reasoning was that there had to be a way of registering the damn program. I went searching for the serial algorythm, but I hit a different sort of goldmine.




Remember the nag as a possible attack point? Well I reasoned, that if the nag pops up, then we obviously havent cracked it have we! So firstly, we pinpoint the nag creation routine in the code, and then we backtrack using Windasm or (preferably) IDA.


Also remember this:


* Reference To: USER32.GetDlgItemTextA, Ord:0107h


:00409329 FF152C444200              Call dword ptr [0042442C]


when we tried to get serial? Well that shows us that the program was created as a dialogbox, probably using resources stored in the .exe.


so do this before you run the program:


bpx dialogboxparama


( exp dialogbox for a list of possible bpx’s )


start the program.


It breaks before the nag pops up yay!


Press F12 (  Important! )


F12 does a ‘p ret’ which means it is will execute/trace every piece of code (like you press F10) until it reaches a RET ( return from a CALL ) ,when it reaches the RET it will pop up sice. Handy huh!


Press ‘Try’ on the nag. Sice pops up nicely at the end of the dialogbox call!


Lovely. Take note of the the calling address and press F5. Open IDA/Windasm and Goto the address we just recorded.


* Reference To: USER32.DialogBoxParamA, Ord:0095h


:0040E6CD FF1528444200            Call dword ptr [00424428]


look upwards. Only one call to this window, so lets go down a level.


* Referenced by a (U)nconditional or (C)onditional Jump at Address:



// weird compare

:0040799B 6683BE6C06000000          cmp word ptr [esi+0000066C], 0000

// jump over the nag ( we are registered?! )

:004079A3 752E                                   jne 004079D3

:004079A5 8D4DD8                             lea ecx, dword ptr [ebp-28]

:004079A8 E8E38C0000                      call 00410690

:004079AD 6A00                                  push 00000000


* Reference To: USER32.GetActiveWindow, Ord:00DFh


:004079AF FF15F8424200                  Call dword ptr [004242F8]

:004079B5 50                                       push eax

:004079B6 8D4DD8                             lea ecx, dword ptr [ebp-28]

// nag

:004079B9 E8C26C0000                      call 0040E680


traces upwards too 407991.


// this is our boy

:0040798A E851F5FFFF                      call 00406EE0

// test if eax == 0

:0040798F 85C0                                   test eax, eax

// if not then jump

:00407991 7508                                    jne 0040799B


now, because all this code formatting is killing me, I will simply tell u what happens in the call above.


First is create’s another instance of ITSELF. It then maps the view to memory and here is where it gets interesting:


// wtf is this u might ask?

* Reference To: IMAGEHLP.CheckSumMappedFile, Ord:0002h


:00406F89 FF15B0404200                   Call dword ptr [004240B0]

// um ok.

:00406F8F 660FB6481B                      movzx cx, byte ptr [eax+1B]

:00406F94 8B542418                           mov edx, dword ptr [esp+18]

:00406F98 33C0                                   xor eax, eax

:00406F9A 57                                       push edi

// important! In softice type d edx+66c and take note of this address.

:00406F9B 66898A6C060000              mov word ptr [edx+0000066C], cx

:00406FA2 8B4C2414                          mov ecx, dword ptr [esp+14]

// hrmm. Comparing something? Its correct atm. Means the call will return One.

:00406FA6 3B4C2418                          cmp ecx, dword ptr [esp+18]

:00406FAA 0F94C0                             sete al

:00406FAD 8BF0                                 mov esi, eax


* Reference To: KERNEL32.UnmapViewOfFile, Ord:02Deh


when you exit this call, continue until we hit the compare/conditional jump that we KNOW will jump straight over our nag:


// weird compare

:0040799B 6683BE6C06000000          cmp word ptr [esi+0000066C], 0000

// jump over the nag ( we are registered?! )

:004079A3 752E                                   jne 004079D3


type d esi+66c and we notice that address is the same from inside the mapping file call!


00406F9B 66898A6C060000              mov word ptr [edx+0000066C], cx


That means if we change CX to 1 before it is moved, all will be well!. Now. Where in gods name is CX getting its value from?


:00406F8F 660FB6481B                      movzx cx, byte ptr [eax+1B]



To understand this more fully, load up your win32api help reference ( if u dont have it get it! ). Here it is for the handicapped:




    IN LPVOID BaseAddress,               

    IN DWORD FileLength,                   

    OUT LPDWORD HeaderSum,        

    OUT LPDWORD CheckSum           



Important: ‘If the function succeeds, the return value is a pointer to the IMAGE_NT_HEADERS structure contained in the mapped image.’


What does that mean?


:00406F8F 660FB6481B                      movzx cx, byte ptr [eax+1B]


that means that the program is getting the BYTE at PE_HEADER + 0x01B, and putting it in cx, which is later put into our magic registered address. Well thats easy to fix!


Open up HIEW and load the RegSpy.exe program. Press enter once to get to Hex mode.


You see the little “PE” at hex offset 0x0100 ? ok thats the start of the PE_HEADER. Simply add 0x01B to it. We get: 0x011B.


hit F5, type 11B, press enter


press F3 to edit, and then type 01.

Hit F9 to save and F10 to exit. Dont u just love HIEW ;D


run the program. Wtf? If never starts. Something is wrong here, bpx MapViewOfFileA. It breaks, trace down and CX is equal to 1!!!!!!! We did it!, but why isnt it starting?


Wait do u see this:


// hrmm. Comparing something? Its correct atm. Means the call will return One.

:00406FA6 3B4C2418                          cmp ecx, dword ptr [esp+18]

:00406FAA 0F94C0                             sete al

:00406FAD 8BF0                                 mov esi, eax


Its not returning one anymore! That means that that compare above must be wrong. Damn!


From the winapi help, we can see that the compare is simply comparing the CORRECT checksum with the checksum thats located in the PE_HEADER. How do we fix that? Easy PEEditor! Load up your file in PEEditor and click ‘checksum’, and then ‘correct’. Optionally u can fix the checksum manually.


Perfect! The program runs, and now its fully registered! Now for fun, you can find out yourself if/how the serial is checked to be correct, or if its even used.




Not a bad protection because of its ability to check if its registered without external files, or with easily accessed keys in the registry. But the author should have made maybe a few of his own checksum routines, instead of relying on an easily duplicated one ;)


Whew long tutorial


This goes out to all my online buddy’s.


Group Greetz: PGC EVC UCF CORE TMG DAMN UG and every group trying to make a difference.


PPl Greetz: Kilby ;) r!sc, MackT, nu, nroc, WarezPup, CrackZ, tsehp+, splaj+, webby, SV, deamon, Maud dib,  KW,   and ive already gone blank. ;P everyone in #cracking4newbies and #pgc on efNET.


PGC 4 L1FE ---- ----