![]() |
| [[ Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us ]] |
|
|
#1 |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Splashscreens can be important for demos and freeware applications, since advertisement is often the only reward the developer gets for them. But splashscreens are very easy targets for crackers. They often don't care about the reason behind 'nag'-screens...
But since we are the developers, we should protect ourselves from them. While it is impossible to create uncrackable code, there are some nice anti-crack tricks. You just have to anticipate on what the cracker will do. The primary tool a cracker uses is a debugger, or similar program which allows to see the application's assembly code in a convenient format. A debugger also automatically translates binary addresses into readable strings, so-called symbols. The trick in this code spotlight attacks exactly those symbols. Many splashscreens use a Windows dialog. It's easy, just create a dialog resource, copy your picture into it, add some copyright notice, call CreateDialog, and you're done. Crackers know this. They especially know that you're going to call CreateDialog. So even a newbie cracker can place a breakpoint on this function, and wait till it gets called by your application. He doesn't have to understand a lot of assembly code to find exactly where you call CreateDialog. He removes that call, maybe remove a simple timer, and he's done! Their strength, namely being able to place a breakpoint at CreateDialog, can be turned into a weakness. We can't change the fact that they'll place a breakpoint at the address of CreateDialog, but we do can prevent that breakpoint from being hit! Here's the trick: skip the first instruction(s). Sounds crazy? It isn't. All we have to do is compensate for the skipped instruction. Luckily, for CreateDialog, I'll show you this is easy... First you have to know that CreateDialog actually is a pointer to another function, called CreateDialogParamA. You can easily see this by (ironically) placing a breakpoint at CreateDialog, and tracing through the assembly code. It doesn't take a lot of assembly knowledge to see that it actually translates into a call to CreateDialogParamA. This is also the function the cracker will really place a breakpoint on. Now, if you trace into this function, you'll find that the first instruction is "mov edi, edi". It should be clear that this instruction does... nothing! And if you look at the binary code, you'll see this instruction takes two bytes. So we can just skip these two bytes and execute our function from there. The newbie cracker will never notice this, since even in our code it won't find the CreateDialogParamA symbol any more. But how do we do that? Don't panic, there's no self-written assembly code involved here, just some advanced C++. To summarize, what we really want to do is call CreateDialogParamA plus two bytes. Unfortunately you can't just write it in C++ like this: Code:
Code:
Now keep quite so the crackers don't learn about this trick... Well, don't get too excited. This trick will only stop the newbie cracker. An experienced cracker will sooner or later figure out what happens. Either way, this simple trick can become a powerful weapon. Every method that fools the tools they use, make it much harder for them to do their 'job'. Assembly code without symbols is almost just as useless as looking at a sequence of zeros and ones. With many functions you won't be so lucky that it starts with an instruction that does nothing. Most start with "push ebp", one byte long. It modifies the stack so you can't simply call one byte further. But it's not impossible. A "call" instruction only places the return address on the stack, and then performs a "jmp". So let's just do the same thing, using inline assembly: Code:
Enjoy! Nicolas "Nick" Capens |
|
|
|
|
|
#2 |
|
Senior Member
Join Date: Jan 2003
Posts: 868
|
Nice one, but it's a little crazy don't you think? The implementation of CreateDialogParamA might differ across systems so this might work on, say, WinXP SP1 or something like that.
Anyway, it does the trick! I remember also seeing more tricks like that somewhere. One of them was to use memory leak in one the blit functions to gain access to cool windows stuff ![]() |
|
|
|
|
|
#3 | ||
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Quote:
But you're right, it's not safe to assume that the implementation of dynamically linked functions has remained the same. But that's no problem either. We can simply check whether they start with the byte(s) we try to skip, "push ebp" is simply 0x55. So we can probably make a macro that applies this trick automatically. But note that this can become a weakness. If they spot this code sequence everywhere, they'll very quickly figure out how it works, remove them 'automatically' and continue the ususal cracking work with breakpoints on interesting symbols. Quote:
|
||
|
|
|
|
|
#4 |
|
Senior Member
Join Date: Aug 2004
Location: USA
Posts: 829
|
That is quite an impressive hack. However, what I would be even more impressed with is good statistics about how many sales are actually generated by this sort of thing. In other words, does it actually significantly increase the number of people buying it?
I am all for making people stop cracking your stuff, but this seems a bit extreme. (though not more extreme than some of the stuff I have seen commercially) I dont mean this to be flame or flamebait, but I wonder if we can come up with solutions such that it wont matter if people crack our software or there won't be a compelling reason to use a crack that someone made. I use cracks regularly, but this is usually nocd cracks for games that force me to continually swap between my collection of cds each time adding another scratch until the game wont work anymore. I like to keep an image of the play cd on disk or simply perform a full install, and not have to risk ruining yet another disk. Perhaps this post is just idle wishing, feel free to ignore me, but I cant be the only one who hopes for something better can I?
___________________________________________
Jesse Coyle |
|
|
|
|
|
#5 | |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Quote:
So, if anyone knows other anti-crack tricks like this, please share! More specifically I'm looking for ideas that are easy to implement, yet give the cracker a headache... |
|
|
|
|
|
|
#6 |
|
Senior Member
Join Date: Aug 2004
Location: USA
Posts: 829
|
Fair enough, sometimes the cat and mouse chase is fun just for the chase.
___________________________________________
Jesse Coyle |
|
|
|
|
|
#7 |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
I just noticed how devilish this trick can really be made. If you apply it to many calls, it's going to be easy to spot and undo. But, there can be an infinite number of variants. Between the push'es and jmp, you can place dummy code, or even real code that does something else like an important calculation. This will make it harder for the cracker to separate the splashscreen code from the code he shouldn't touch. You can even place (lots of) code between the jmp and label! This is really confusing for the cracker since it will be even harder to figure out where the 'call' happened. He'll look at the call stack and see the return address, not where the jmp was made. And to make him completely loose his mind, you can make the return address point to another function.
![]() Use your imagination! |
|
|
|
|
|
#8 |
|
Senior Member
Join Date: Jan 2003
Posts: 868
|
Right about one thing: if they want to crack it - they will!
|
|
|
|
|
|
#9 |
|
Valued Member
Join Date: Aug 2004
Posts: 120
|
The best tricks I have seen are described here (free registration required, but this great site is well worth it)
The short of it is that they had various advanced ASM tricks and one particuarly innovative simple trick. This simple trick operates on the debugging premis that randomly occuring bugs are the hardest to fix. Basically, what they did was implement several different types of exe checksums. The application run different checksums at different times and then if any of these checksums failed they would RANDOMLY break different aspects of the game. For example, a cracked version of the game would result in being unable to pass the 3rd level. Since it took the crackers precious time to get up to the third level and then once they got there they had no concrete way of telling if their crack worked perfectly, they had a difficult time creating a working crack. |
|
|
|
|
|
#10 |
|
Valued Member
Join Date: Jan 2004
Location: England
Posts: 265
|
I think that was the route taken by Operation Flashpoint, published by codemasters a few years back. Apparently, the random issues that using a hacked version caused were very hard to pin down, especially, when some of the issues just made it look like you were just plain crap at playing the game.
Bit of a winner idea if you ask me, not sure how hard it is to implement though Spree |
|
|
|
|
|
#11 |
|
Senior Member
Join Date: Aug 2004
Location: USA
Posts: 829
|
It actually might be a fun way to play a game, if it just gave you a handicap. You could steal the game, and get relatively good at it, and then when you bought the full version, you would be awesome, because you wouldn't have to deal with the handicap.
I learned tennis this way with a very heavy racket with a long neck and very small head.
___________________________________________
Jesse Coyle |
|
|
|
|
|
#12 |
|
DevMaster Staff
Join Date: Jul 2003
Location: Northern Ireland
Posts: 1,250
|
You stole a tennis racket?
|
|
|
|
|
|
#13 |
|
Senior Member
Join Date: Aug 2004
Location: USA
Posts: 829
|
Sortof, it was my parent's. Good thing was, that I didn't have to crack it in order to use it, otherwise I would have been in trouble.
___________________________________________
Jesse Coyle |
|
|
|
|
|
#14 |
|
Valued Member
Join Date: Aug 2004
Posts: 120
|
lol :-P
well it is probably really easy to implement, but I would definitly make it IMPOSSIBLE to get past a certain point. Maybe just pick one of 10 random ways to die or crash or lose health and do it randomly every so often... Then ALSO do some other stuff like remove all the powerup items and cut all the ammo by one third and do some other crazy shit. Make it that its so hard htat its impossible because someone who plays a harder version of your game illegally is still playing your game illegally... |
|
|
|
|
|
#15 |
|
New Member
Join Date: Dec 2004
Location: Netherlands
Posts: 2
|
Alternatively, (being the cracker) you can just send a few WM_TIMER messages to the dialog followed by a WM_COMMAND to speed things up.
I tried it using Spy++ on some program with a "countdown button" and it seemed to work. I just hope nobody is smart enough to actually check how long the dialog has been open before closing it :P If you really want to that check can be foiled too (I'm too dumb to do it though). |
|
|
|
|
|
#16 | |
|
Senior Member
Join Date: Aug 2004
Location: Ghent, Belgium
Posts: 1,056
|
Quote:
![]() |
|
|
|
|
|
|
#17 | ||
|
New Member
Join Date: Dec 2004
Location: Netherlands
Posts: 2
|
Quote:
Sure it is - fun to code too :P. I think most shareware authors don't bother though. |
||
|
|
|
|
|
#18 | |
|
New Member
Join Date: Nov 2005
Location: Finland
Posts: 2
|
Quote:
There's one problem. If a gamer is using a cracked version, and it starts breaking randomly, he might just think that the game is crap, and delete it. That way you still wouldn't get paid for it. So I therefore believe, that you should let the user know the reason of failure is cracked version. They might already be addicted to the game and thus ready to pay. Of course you should do these checks with different code blocks when the game advances. Most 0-day crackers don't have time to playtest and find the check which happens just before you defeat the final boss for example. |
|
|
|
|
|
|
#19 |
|
Senior Member
Join Date: Sep 2005
Location: .nl
Posts: 504
|
dude, you replied on a post that is more than one year old!
|
|
|
|
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
|