PDA

View Full Version : Making my EXE 'save' (from Cheats and hacks...)



Firlefanz
16-01-2006, 01:48 PM
Hi!

My game is nearly finished.

When my last game came out, some days later there was a Cheat tool, that ran in the background and changed energy etc or could even change into my scene where the player could watch a hidden map etc.

Sometime later I also found a hack which turned the shareware version into a full version.

This is not nice! :evil:

How can I make my Exe 'save' (as far as possible) from Trainers etc?

Are there tools that can crypt the EXE (I think I have seen something like this somewhere) or can I do something in the Exe itself to prevent Trainers and Hacks?

Thanks,
firle

XProger
16-01-2006, 02:16 PM
Every time changing address of variable
type
TPlayer = ...
health : ^Integer;
...
end;
...
var
hp : ^Integer;
begin
New(hp);
hp^ := Player.health;
Dispose(Player.health);
Player.health := hp;
...
end;

or use static array of variables and change current REAL index of variable

User137
16-01-2006, 07:22 PM
Then you might try packing your exe with UPX. It not only make exe smaller but i'd guess it is harder to decompile.

If possible, try leaving some graphics/sound material out of shareware too, maybe resulting in difficult_to_fix_even_delphi_way access violation or other nasty trick to prevent hacking it :twisted:

Firlefanz
16-01-2006, 08:03 PM
Sounds both very good. Have to find out what UPX is. :wink: Thanks!

Is there a sense in having other variables set when energy is set also and having energy a coded value?

Or is it all senseless when it comes to trainers?

Firle

Traveler
16-01-2006, 08:23 PM
I did some research a couple months ago when you last mentioned this 'hacking' (cracking is actually the correct term) on the omega forums.

With tools such as GameCheater it is possible to modify values of processes currently running in Windows.

For example, you have a game xxxx which currently holds a score value of 100. After submitting the game process to GameCheater together with the value 100 it will seek all adresses within the process with the value of 100.
After the first test you'll need to continue playing until the score changes, and then rerun the test. GameCheater will then perform the same test but only with the addresses of the previous tests. After a couple tests 1 will come out eventually and you'll be able to modify it.

The whole approach stands on the continued changing of fixed addresses. If you are someone able to change the address that holds your score GameCheater will never be able find it.

Firlefanz
16-01-2006, 08:30 PM
Thanks a lot for the info! But how do I do that?

I am not sure if I make a pointer for the score or the energy,
it also is in the memory on a certain adress, or am I wrong?

Can I disturb it somehow, coding these values, changing other 'dummy' values when changing them?

Firle

AthenaOfDelphi
16-01-2006, 09:55 PM
I've never done it, or been involved with this kind of discussion before, but I'd say you need to move anything that can be tweaked to give the player an advantage.

You could probably do it quite quickly with something like this...


const
_movingDataItems = 2;

type
PInt = ^Integer;

TMyMovingData = class(TObject)
protected
fMovingData : array[1.._movingDataItems] of PInt;
function getData(index:integer):integer;
procedure setData(index:integer;value:integer);
public
constructor create;
destructor destroy; override;

property armour:integer index 1 read getData write setData;
property gold:integer index 2 read getData write setData;
end;

....

constructor TMyMovingData.create;
var
loop : integer;
temp : PInt;
begin
inherited;

for loop:=1 to _movingDataItems do
begin
new(temp);
temp^:=0;
fMovingData[loop]:=temp;
end;
end;

destructor TMyMovingData.destroy;
var
loop : integer;
temp : PInt;
begin
for loop:=1 to _movingDataItems do
begin
temp:=fMovingData[loop];
dispose(temp);
end;

inherited;
end;

function TMyMovingData.getData(index:integer):integer;
var
temp : PInt;
newTemp : PInt;
begin
if (index in [1.._movingDataItems]) then
begin
temp:=fMovingData[index];
result:=temp^;
new(newTemp);
dispose(temp);
newTemp^:=resuilt;
fMovingData[index]:=newTemp;
end
else
raise exception.create('Index out of bounds in TMyMovingData.getData ('+intToStr(index)+')');
end;

procedure TMyMovingData.setData(index:integer;value:integer) ;
begin
if (index in [1.._movingDataItems]) then
begin
fMovingData[index]^:=value;
end
else
raise exception.create('Index out of bounds in TMyMovingData.setData ('+intToStr(index)+')');
end;



Using this object you could store a lot of integer data that will change location in memory every time you read it, I think thats the essence of whats been suggested.

I haven't tested this code, I've just written it to give you a method you could use.

Hope it helps

Firlefanz
17-01-2006, 06:18 AM
Hello Athena,

thanks a lot for the suggestion.

Do you think it would that be much slower or no problem at all? I have all Data stored in a TPlayer Record, then should I do that to every single value in the record or can I make a ^ on the record itself, would that also help?

The record of TPlayer contains long lasting data, can be saved etc.
The other records both contain data for space and planet missions are new created each level.



TPlayer=record
nscore,nface: integer;
sname: string[20];
sstatement: string[32];
srank: string[20];
nExp,nXRunlong,nXRunfast,
nXWalkfast,nXShootfast,
nXEnergy: integer;
nrank,
ncredit: integer;
yco: single;
control: tcontrol;
nshieldtime: integer;
colshipr,colshipg,colshipb: byte;
colmanr, colmang, colmanb : byte;
nchosenprimary,nchosensecondary: byte;
npainkiller,nmanweapon,nmanarmor,
nshiparmor: byte;
priweapon1f,priweapon1s,
priweapon1r,priweapon1fd,priweapon1rd,
spapriweapon2, spapriweapon3,
surpriweapon2, surpriweapon3,
surpriweapon1: byte; //Waffe StAŹ§rke
prienergy1, prienergy2, prienergy3: byte; //Waffe Energie
prienergy1r,prienergy2r,prienergy3r:byte; //Waffe Energie Reload
nsatelite1,nsatelite2: byte;
ndrone1,ndrone2,ntracers,ntracertime: byte;
// secweapon1, secweapon2, secweapon3: byte;
spapriammo1, spapriammo2,
spapriammo3: integer; //Ammo Anzahl
surpriammo1, surpriammo2,
surpriammo3: integer; //Ammo Anzahl
sursecammo1: single;
sursecammo2, sursecammo3: integer;
spasecammo1,spasecammo2,
spasecammo3: integer;
nengine, nreload,nbot,ndef: byte;
charE,charX,charT,charR,charA: boolean;
proR,proB,proY: boolean;
end;
TPlayerMan = class(TSprite)
Xco,Yco,nshootnr,
LastXco,LastYco: single;
SaveXco,SaveYco: single;
SaveSaveXco,
SaveSaveYco: single;
SchattenX,SchattenY,
LastX,LastY: single;
nlastscrolly: single;
nWavelapsed: single;
Status: Tstatus;
nEnergy: Integer;
nBullet,nRocket: Byte;
nEnergya,nBulleta,
nRocketa: Byte;
RichtLauf, RichtFeuer, Lastr: TRicht;
nAnimation,
nAniWait,
nAniSpeech,
naniHit: byte;
nHurt: single;
nshootindex,
nimageindex: single;
naniNohit,
naniKill,
nAniBonus,
naniFreeze: integer;
nspeedindex,
nspeedcount: byte;
nplayerdran: byte;
boolfeuert,
boolsprint: boolean;
boolisdead: boolean;
constructor Create(const AParent: TOmegaSprite; nPlayernr: byte); overload;
procedure draw; override;
procedure move(const movecount: single); override;
procedure oncollision(const sprite: tsprite; const colx,coly: integer); override;
end;
TPlayerShip = class(TSprite)
nanim: single;
nWavelapsed: single;
xhit,yhit: single;
nEnergy,nLasertime: single;
nshootnr,nruettel,nrauch: single;
nEnergya,nShootwaita: Byte;
nplayerdran: byte;
// neigleft,neigup: byte;
constructor Create(const AParent: TOmegaSprite; nPlayernr: byte); overload;
procedure draw; override;
procedure move(const movecount: single); override;
procedure oncollision(const sprite: tsprite; const colx,coly: integer); override;
end;


I would need to make it hard to 'hack' into all TPlayer values, and some of the Playership/Playerman values like Energy. A main problem could be the shop scene, where you click a button then loose money and get a new weapon or something.

Thanks a lot,
Firle

czar
17-01-2006, 07:23 AM
How about compressing your executable? For example upack, aspack or asprotect?

Upack is free and will prevent amateur hackers from changing your code.

You can make hacking harder but you will not prevent someone with skill from hacking your program. Many game companies spend millions on copy protection and yet often hacked versions of their game hit the streets before the legit version goes on sale.

Firlefanz
17-01-2006, 07:37 AM
Hi Czar,

thanks for the info. I understand I cannot make it impossible to hack or crack, but I can make it harder. :wink:

But this won't help againt trainers, right?

Firle

AthenaOfDelphi
17-01-2006, 09:30 AM
Hi Firlefanz,

There will be some kind of trade off in terms of performance. It depends on how often you access the properties and how. If you read them more than you write, then you may want to move the memory moving code to the write access method.

With regards to your question about moving individual items or the whole record... moving the whole record would achieve the same thing, but I would say that the chances of some kind of trainer locating the data are increased. The reason being, the values will always be in the same order in the block, so pattern matching may turn up the block. If you move each item, then they will move around each other in memory making pattern matching on unchanged values harder.

There are a lot of options to make it very difficult for trainers, but there will be some kind of performance hit. The level of that hit depends on how much protection you want.

K4Z
17-01-2006, 09:34 AM
Packers, Upack, UPX, etc, will only slightly hinder people from hacking and patching your exe. Most have no effect on preventing Memory hacking.

I haven't tested it, but Athena's example looks really good, and should annoy amature crackers. But there are techneques and memery hacker programs that can automatically adjust to offsetting and moving addresses, especially if the move is predictable.

One technique you could try is shadowing the data, having duplicate variables (preferably encrypted, a simple xor with a random value should do). When one variable changes, change the duplicate as well. Either real-time or every now and then (or during a screen switch, Alt-Tab, etc), just check the variable values to the (encrypted) duplicates.
Something like that, coupled with Athena's sample, should be simple and quick enough to implement.

Ofcourse, it may be best to apply the protection to critical values, would be overkill to apply to all those variables :shock: :o.

and... :P :P, if data is written to the harddrive, it can be easily modified, so preventing memory hacking is useless unless the save files are aslo protected.

Geeewd Luck!

:P Game Hacking is inevitable :P

Firlefanz
17-01-2006, 09:39 AM
Hi!

this suggestion is also good, having two energy variables and changing both each time, having them coded somehow and look from time to time if they are still the same, did I understand that right?

I only care about that 'cheating' stuff because I have an online HiScore-List.

Thanks,
Firle

K4Z
17-01-2006, 09:45 AM
this suggestion is also good, having two energy variables and changing both each time, having them coded somehow and look from time to time if they are still the same, did I understand that right?


Yep, that's it. Just remember that the duplicate should not be directly equal to the original (If they are, then they would both be found and changed together). So they'd have to be encrypted.

:wink:

Sly
17-01-2006, 11:11 PM
Anti-Cracking FAQ (http://www.inner-smile.com/nocrack.phtml) from a Delphi perspective.

Firlefanz
18-01-2006, 07:18 AM
Veryvery interesting read. Thanks Sly.
I will create a licence that is no license and built in a few warnings that will never be called, this will cause some confusion perhaps.

I know I cannot make it impossible, I cannot even make it hard, but perhaps a bit harder. Then a possible hacker might lose interest because it is no professional game after all.

Thanks!

Firle

JSoftware
18-01-2006, 09:13 AM
indeed very interesting read. Bookmarked

Traveler
18-01-2006, 10:44 AM
Agreed! I vote for addition in the Library.

Sly, any chance you have more of these little gems?

Sly
18-01-2006, 12:07 PM
I first found that page several years ago.

What others do I have hidden around here.
Photoshop-style blend modes in Delphi (http://www.pegtop.net/delphi/articles/blendmodes/). A description of the different types of layer blends you can do in Photoshop and sample Delphi snippets to reproduce each effect.

Blambot Comic Fonts and Lettering (http://www.blambot.com/). Very high quality fonts in comic book styles. Half of his fonts are free to download and use, but that's still a lot of fonts.

Not much more that I have here at the moment. I might check on my work machine tomorrow to see what bookmarks I have there.

Robert Kosek
18-01-2006, 02:40 PM
Heh, I remember that article. :D Read that a long time ago, now.

Question for ya'll though, mainly those who understand DLLs better. Say I have a hashing function I want to use in my app, as well as the protection algorithms and would like to place it in a seperate DLL. Can the DLL with the protection codes use the function within the hash DLL?

Just a food for thought item.

LP
18-01-2006, 04:04 PM
Say I have a hashing function I want to use in my app, as well as the protection algorithms and would like to place it in a seperate DLL. Can the DLL with the protection codes use the function within the hash DLL?
I see no reason why not. However, I think it's a lot easier to "crack" your DLL than your application. Crackers will be able to brute-force your DLL and/or replace the DLL with some sort of fake DLL.

Robert Kosek
18-01-2006, 04:08 PM
Well, if you UPX it and spaghetti code it then it should be fine. As well as certain DLL check functions named "GetWindowText" and whatnot.

Can we code special DLL loading functions?

LP
18-01-2006, 04:55 PM
Well, if you UPX it and spaghetti code it then it should be fine. As well as certain DLL check functions named "GetWindowText" and whatnot.
Unpacking UPX is easy: it comes with unpacker, right? :)
As for function names, I doubt crackers will look at function names anyway, so it can be "GetWindowText" or "HelloThere" - makes no difference.

Besides, "GetWindowText" name will be quite suspicious anyway, since it's usually located in "User32.dll". :)

Robert Kosek
18-01-2006, 05:17 PM
But when called it is harder to tell where you're calling it from. Thus using things using names that imitate your form functions for instance.

But yes, UPX does have an unpacker. Which is why I asked if there is a way to write your own DLL loader functions. Then I could encrypt my DLLs in a strong fashion.

BytePtr
23-01-2006, 08:25 PM
Ha, seems that you guys dont know anything about cracking and how they beat protections. UPX is useless. It only packs your exe, it does not protect.
UPX can be unpacked with 1 minute, even less.
If u want serious protector then purchase Execryptor or Armadillo, use maximum protection that they give. ASPR: crc check, debugger check, time changing etc, ARMA: copymem, nanomites, anything it gives to you. Also try to use FindWindow API to find cheating tools windows by its name etc. Also game hacking tools. Like "Trainer creation kit" etc. If this window is active then kill this window or just dont load game. Do not display messageboxes like: Game cheating program is active, Please close it before running game". By these messages, the cheating tool check can be busted with changing one byte.
Need more inf? Just ask me.

Remember! There is no BEST protector!! EVERYTHING is crackable but with my tips u can make it harder!

Robert Kosek
23-01-2006, 10:31 PM
You're missing the point. We're mostly small timers, and I know I can't afford a protection package. Thus the discussion on how to protect it ourselves.

Crackers/Hackers often take the bread from our mouths.

Just who do you think you are? If I actually had money I'd buy a copy of Delphi '06 first, so I could make some money. Protection I can code for myself, and you didn't give any real tips, just a recommendation to get a component set.

Want to help us? Then talk in methods and code, not "get this and turn it fully on". I'd buy ICE License before I get "EXECryptor".


Sorry for the tone, but today I'm in a "don't mess with me" mood.

LP
24-01-2006, 12:31 AM
Also try to use FindWindow API to find cheating tools windows by its name etc.
I doubt this will ever work. Think of it, you create a game, then someone makes a trainer with window name "G@me Trainer by ThR-ash". How would you know such window name in the first place? What if they change window name to something like "Mega C00l Helper"?


Do not display messageboxes like: Game cheating program is active, Please close it before running game".
Just curious. Is there any game doing that? :)



Need more inf? Just ask me.
If you have time, you might want some article about protecting programs or at least give some suggestions (preferably not related to commercial software). This could be very handy ;)

hackbart
24-01-2006, 12:26 PM
Hi,

i also have had a lot of trouble with "hackers" who spread my software. Similar like Erik i tried to make the application secure. In my opinion i think the easier a protection works, the better it is. Just put pieces of the key checks all around the application, add some parts in your sprite class for example and never ever combine the "enter key" with a "check key" routine. Just close the app and restart it again. This way it is harder to find the logic :)
UPX is also fine and if you edit the header you can not decompile it via upx -d filename.exe.
Finally, i know this link is not very serious but the author has had damn cool ideas: http://www.iamaphex.cjb.net/
Especially the "load an encrypted dll out of a ressource" sample.

Christian

Sly
24-01-2006, 10:33 PM
Do not display messageboxes like: Game cheating program is active, Please close it before running game".
Just curious. Is there any game doing that? :)

Yes. Spyro the Dragon on PSX. It had CRCs of sections of code embedded in the section of code that it was doing the CRC on. These CRC'd sections of code would also overlap with other CRC'd sections of code. When it detected that a CRC did not match, it did not inform the user straight away. It removed a few gems from the level so the user could not complete the level, or later on a NPC character would mention that you are using a cracked version of the game. That was just one of the anti-crack methods they used. It took the crackers over three months to release a properly cracked version of Spyro with several dud versions released beforehand (the majority of a game's sales are in the first three months), and the crackers thanked the Spyro developers for making it such a challenge.

Here's the article on Gamasutra.
Keeping the Pirates at Bay: Implementing Crack Protection for Spyro: Year of the Dragon (http://www.gamasutra.com/features/20011017/dodd_pfv.htm)

L505
27-01-2006, 05:53 AM
UPX is extremely easy to unpack - use a custom UPX implemenation of your own. I.e. scramble the alogorithm a bit and customize it so no hacker can find a decompressor for your packing alogorithm.

He can still unpack your program by looking into the assembly, but it is much harder when it is your own custom packing alogorithm.

Get the program called Stud_PE and find the site called "pro tools". Use all the tools you can, and pretend you yourself are the cracker.

M109uk
27-01-2006, 10:46 AM
With my project im using MD5 digests to check if any of the files have been modified.. it has its problems, mostly being that i cant store the MD5 digest in the application because of course it changes everytime i build the application.

To make it harder to hack, i have the verifying functions in an inc file and include it in to the create events of the most classes and the a lot of other events during the creation, initialization and rendering stages of the game..

e.g.
[/pascal]constructor TuPlayers.Create;
{$include uMD5DigestVerify.inc}
begin
If DoMD5Verify(Application.ExeName) Then
Legal else
Hacked;

// do some stuff
end;
[/pascal]

It probably isnt the greatest of ideas..

--

Im adding some other ideas from what i seen in the spyro topic :)

Firlefanz
10-02-2006, 09:43 AM
Hello,

I made some 'random' licence methods that don't do much at all, some additional variables to make score, energy and credits harder to find and so on.

I now downloaded UPX and upxed my Exe.
It was 1037 kbyte before and now it is only 373 kbyte, very nice :D

A first small test run showed no differences.

First of all can I be sure that everything still works or do I have to test everything again?

Do I lose frames because it is packed? I saw no difference...

Last point: I heard it can be unpacked again, any way to make it impossible? Changing the header somebody said? How?

Thanks a lot!

Firle

K4Z
14-02-2006, 04:53 AM
UPX really only compresses exe's, you shouldn't rely on it to protect your exe's alone. There are some programs that can encrypt your exe, but just like UPX has unpackers, most have decrypters.

When you run a UPX compressed exe, it automaticaly decompresses the program to it's original state, so there's no real loss of performance while running.

Yes, you should test everything, not only test that the protection hasn't caused bugs in your code, but also the protection itself. Grab a memory editor and/or a hex editor and just tinker around, see if the security actually does anything to hinder cracking.

Good Luck!