Here's my approach featuring a persistently fully unlocked program; probably there are many better ways but damn it runs...
At first I wanted to crack the registering process, so that I would have complete access for further reversing approaches. It's as easy as in the last part: Just NOP the jmp in front of our good boy ("Registration Successful"). Search for the string to find it.
That's not required for the final cracked version, but it heavily helps with reversing.
The next thought of mine was that there has to be a part of the code which activates all functions and removes the annoying "demo" stuff; so I began to dig around and found this by clicking my way through the program:
It seems to be responsible for making the program look registered; but sadly it's not enough for activating the program...
Anyway, that's already enough for us to want it getting called at the program's startup - this would make the program look registered persistently. Search for the place where the main MessageBox gets created; it should be similiar to this one:
You see the highlighted line? This TEST and JE instructions are not important for the program; probably a good place for injecting our own code! A JMP to the previously found register-stuff would be cool; but sadly there's not enough space for a long JMP (It takes more bytes than a short JMP), so we have to find a near code cave where we can place it.
Let's have a look at the code below:
You see the first two instructions? They're probably used to jmp to the code at the bottom when an error occurs. Okay, but what? If we assume there are no errors (Because we're cool; our program doesn't throw errors!
) we could use this free space for our own malicious purposes! There are enough bytes for a long JMP, so our schema looks like this:
MessageBox setup -> Our injected short (!) JMP to the error handling (used as code cave) -> Long JMP to the registering stuff -> Registering stuff registers stuff (Pure black magic...) -> Finally JMP which takes us back right behind our first injection -> MessageBox continues
Cool, isn't it? Yeah, maybe a bit complex, probably there're better ways, but it's always good to understand the difference between long and short JMPs and how to circumvent issues by using code caves .
We found a place to inject into, we got a code cave, but where can we jump back from the registering process? The instructions right before the RETN are a good choice:
Okay, now just patch the instructions to the JMPs I talked about and see how automagically our program gets "registered" everytime we run it .
But we're not finished yet, now comes the easy part. If you read the other's solutions you can stop here; I also NOPed the two JMP instructions.
I had to search for the check in front of the nag telling us that we're not allowed to save the file when we try to. Just open this nag, pause your debugger (I use Immunity) and press Alt+K to show the recent calls; you'll see the one responsible for the MessageBox. From there click your way up through the returns - just be patient, you'll find it . When you got it it should look like this:
Yep, one byte gets compared to zero; if that's true we jump right into our bad boy.
So we can tell that this byte is probably the one responsible for checking whether we're registered - or not. Maybe it's used at other places in the code too? Set a hardware breakpoint on access and try it; you'll see our assumption seems correct!
Of course I thought patching this byte would be the easiest way, so I edited my code cave to INC it on startup, making it not zero and our program correctly registered (Nah, correctly without paying money ). But due to errors when exporting the changes to a new exe I gave up after half an hour of testing and just NOPed the two JMPs in front of this bad boy and the About dialog; then everything is working too...