Beruflich Dokumente
Kultur Dokumente
Mihai Eminescu
Know more link? Email me razali_bie@hotmail.com with subject line "More Link For Gamehacking Archive", email with different subject will be ignore.
Devious
Extalia
CES
GHU
X2
Gamehacker Homepage:
Sheep - Trainer for PC and Xbox, Tutorial on PC and Xbox, Gamehacking Tool
Eedok - Trainer, Gamehacking and programming tutorial, Java Games
Bie - Simple game Trainer, downloadable tutorial [GHA], Simple Gamehacking tool
Brzi -Trainer, Tutorial, Gamehacking Tool
Dopey - aka Tsongkie
Shinero - Trainer, Gamehacking and programming Tutorial.
Shaikh Adeel - Trainer, Gamehacking tutorial.
DDH - Tutorial, source code.
Victor D Wolverine - Trainer and Trainer source code, Gamehacking tutorial.
Rainy - Source code, Trainer and tutorial.
NTSC - The person who inspired me to involve with Gamehacking. Tutorial & Trainer.
Primal Secret - Trainer, Gamehacking and hacking tutorial.
Snake & Max Power - Trainer, Gamehacking and Programming Tutorial, Source code and Gamehacking tools
Whiteys - Trainer and Tutorial
eVoByte - Tutorial, Crackme and Tools
Programing Homepage:
Memory Searcher:
Tsearch
Artmoney
Gamehack
Misc Tools
Gamecheater Homepage:
http://www.xcheater.com/
http://gameguru.box.sk/
http://www.pccheater.co.uk/
http://happysurfer.com/cheats.html
http://www.cmgsccc.com/ps2/
User Comment
Shinero Pretty fuc.kin nice
.empty. cool now all the Newbie here download read it love it and do it.
[3y3]$!nn3r really gr8 work! keep it up
Neat stuff.
Sorin SUPERB
hey! that's me!!!: real picture of us. other gamehacker who want to put they picture here, send zip picture & email to me razali_bie@hotmail.com
erhan
Killing DMA and making Trainer
I- Table of contents:
I- Table of contents :)
II- Thanks
III- Needed Tools
IV- Basic about Game Hacking
V- Kill DMA with TSearch 1.4a
VI- How to kill DMA in your trainer with Trainer Maker Kit
VII- Using Anti-TrainerSpy in your Trainer
VIII- Contact
MiCRaL
Shaikh Adeel
Tsongkie
Vivien Abner
MacDeath ťť Thanks for fixing errors with my english...
Now we have the address. Let's add it in to TSearch hack table. First of all you need select select
Monopoly Tycoon in the process list.
If you don't know how to select it, read my tutorial about TSearch.
P.S.: You can get the address with differents tools and use TSearch to kill DMA only.
Now we need the Description (Money Hack) of the cheat, Address (Yet? Yeah!!!) and Type (Float)
Cool. We have total control of this address now. Let's remove the DMA!
Click "AutoHack" / "Enable Debugger"
Back to TSearch (ALT+TAB). Click "Money Hack" (with the right button) and click "AutoHack"
Well, now you'll need to go back to "AutoHack" window (ALT+TAB)
You'll see "crazy codes". hehehe ;)
Now it is easy to kill DMA. Back to the game (ALT+TAB) and build any item. Go back to the AutoHack
window and BINGO!!!
To test if it will work, you'll use the two selected images.
Freeze image: Click here and go back to game (ALT+TAB), build any item, and see if your money
doesnt decrease.
Unfreeze image: Click here and go back to game (ALT+TAB), build any item, and see if your money
decreases.
If the two icons work, CONGRATULATIONS! You have killed DMA!
Now you can make a trainer. Use any programming language or TMK....i'll help you with TMK.....Let's go!
contact : dna.netz@ig.com.br
Gamehacking Tutorial
Alrighty, lets get started. The target game for todays tutorial is 3D Pinball.
The game is ideal for us, basically because most people will have it (it comes
with Windows XP, 2000 etc), and its easy as hell to train.
Our object today is to train the game using a "code cave" (gah! I hate that
phrase) that we add to the program with our trainer, rather than the usual
process of searching through the program for one that already exists. This is
useful for when you want to do things like using entire c++ functions, or for
launching custom dlls into a process.
oh yeah, and you'll need tsearch or some other memory searcher and a debugger
Once you have found your balls, whop a 4 in (so we have some balls to play
with) and then fire up autohack (go to the autohack menu and hit the enable
debugger item, then the autohack window item). In the autohack window set
a breakpoint on the address you found (just a write breakpoint will do)
and then go and lose a ball. Once you've lost the ball autohack should
have the line which modified the ball count. It should be remarkably similair
to:
which means move the value in eax into the memory location pointed to by [esi+0x146]
Fire up the tsearch easywrite thing, and put the following in the top section
(don't bother with the <-- stuff)
offset 0x10bc0
cmp eax,0x1 <-- compare the number of balls left to 1
jg 0x10bca <-- if we have more, skip the next line
mov eax,0x3 <-- if we have less, give em 3 balls
mov [esi+0x146],eax <-- write the number of balls left back
jmp 0x1015f08 <-- and return to just after we jumped
here
offset 0x1015f02
jmp 0x10bc0 <-- jump to our injected code above
nop <-- do nothing (for neatness)
Alrighty, try it out. For those whos assembler isn't crash hot, here is whats
going to happen when the game goes to write the new number of balls back: it
jumps to our code, where its compared to 1 (i.e 1 ball remaining). If there is
more than 1 ball left the number is written back as normal, otherwise 3 balls
are written back. That code is much more complex than it needs to be for our
purposes, but it will help to illustrate relative addressing (later).
At this point we have successfully trained the game, using a "code cave" to
"defeat" "DMA" (lots of phrases i hate). Everything beyond this point is
optional, and you'll probably only use it when your injecting complex code,
such as an entire c++ function.
Breaking that down the E9 is the jump instruction and the B9ACFFFE bit is the
address to jump to, or more accurately, the distance to the address to jump to
from the end of the instruction.
This means is the trainer is going to have to figure out what these 4
bytes are at run time. Lucky you - i'm going to provide you with a function to
do that (in c - i'm sure you asm gurus can convert it on your own):
For those who prefer calls to jmps, change the *code++=0xe9 to *code++=0xe8 and
it will work the same.
LPVOID VirtualAllocEx(
HANDLE hProcess, // process to allocate memory
LPVOID lpAddress, // desired starting address
SIZE_T dwSize, // size of region to allocate
DWORD flAllocationType, // type of allocation
DWORD flProtect // type of access protection
);
We then have a chunk of memory in the remote preocess allocated just for us
where we can write our code with WriteProcessMemory, pretty much the same as we
normally would, with our trainer adding the jumps on the fly. A function to do
this is as follows:
Of course you should add better error checking, but I can't be stuffed. In
order to use the function you just pass it the hex values from your code block
(the one we created earlier) without a returning jmp and it will do the rest of
the work for you. So, going back to our pinball code from earlier we would
pass in the hex for the following asm:
note that the jg is still there. This will still function, because the jg used
a relative offset, meaning it says jump over the next 5 bytes. i.e to the 2nd
mov instruction.
The hex we would pass to the function is:
83f8017f05b8030000008986646010000
And thats it, pretty simple really. Some source code to implement a very basic
trainer for pinball is below. There is lots left for the
Note that it is simpler to use the call/retn method, rather than the jmp, jmp
method shown here.
Enjoy
Sain
-------------------------------------------------------------------------------
File: main.cpp
-------------------------------------------------------------------------------
/* Pinball 3D trainer
** By Sain
*/
/*
** Okay, this is really untidy, but hey, its just to demonstrate how to use the
** dynamicly allocated chunk of memory. Use this for whatever you want, if you
Game-Hacking Tutorial
Target : Heroes II
~~~~~~~~~~~~~~~~~~
Tools Needed :
~~~~~~~~~~~~~~
- Hex Workshop
Level : Beginner
~~~~~~~~~~~~~~~~
INTRO
~~~~~
Hello again ! - Tell me I'm not speaking alone - hehehe - I'm not krazy - huhu
Or at least I think so...
Want to learn some saved-game hacking techniques ? If yes then follow this tut
else go and bake a pizza ! I
Let's Begin
~~~~~~~~~~~
First, let's think at our hack method -> saved-game_file hacking. This means you
don't need memory searchers or something, just a hex editor (HEXWORKSHOP). I
would make your life "miserable" by throwing SoftIce in the battle, but it
simply refused to collaborate with his video-adapter on this old (but great)
game. So, lucky you - No SoftIce :)
Remark : Maybe you think why would I use SoftIce (a debugger) on this kind of
hacking. Answer is simple : We could trap the game when it reads
data inside that save file after we modify it. For a better understanding,
of course. So a debugger would bring more understanding to you..
Unfortunately, I have only SoftIce and only with it I feel "read
battle", but as I told you, it refused to cooperate... No cookie
you, mister SoftIce ! You're a bad guy !
Ok.... What are you waiting then ? Enter the game, choose to play a campaign and
the good_guy - Roland (the portrait in the right).
Now, pay attention : DON'T do anything in the game ! Don't even scroll the screen
save it under "abc", let's say.
We now have a saved-game file. But what to do with it ? We can search for the
of gold/crystals/gems etc... This will be boring... (I'll show you how to do
too).
Let's try something else... But first note on a piece of paper the amount of each
resource you have : gold/wood/sulfur etc. Now build the "Foundry" in your castle,
and without doing anything else, save the game under "abc1".
The smart-ones of you already guessed what we'll hack - the buildings :) Enter He
and compare the 2 files - abc.gmc and abc1.gmc ! Here's what it should look l
Now... Comes some thinking : We are not interested in "matches", but in replaceme
(because when we build, we don't have only the same buildings, but a new one)
Also, take a look at the replacements number. There are 4 repl. Why's that ?
But what's the 4th replacement meaning ? Heh.. The game keeps the name of the sav
inside the files. So the repl. is that "abc.gmc" <> (is different from) "abc1
Also, if your mind is sharp enough, would have noticed that when you build a stru
some "monsters" will be available too inside that structure JUST AFTER YOU BUILD
(without being necessary to wait a new week to be able to recruit the monster
This is a VERY IMPORTANT remark, and with it we can distinguish between the
replacements (this replacement is for money, that is for buildings etc).
But with this repl. we have 5. And HexWorkshop says there are only 4. Maybe i
'involved' with one of the 4 repl...
After you noticed, this is because we have 2 saved-files with different names abc
This is not important to us.
Do you still got that piece of paper where you noted the resources amount ? Take
on them. What ? You get no match ? Hehe, that's because in the save_files the
are in HEX format. Take a look at first 1E. If you convert it in decimal, you get
Look on the paper for 30 and tell me what resource it is. It's wood, right ?
be ore ? Look at the second 1E... Hmm, one could be for wood and the other fo
I bet the first is for wood and the second for ore. :)
In "abc1" file we have 19 instead of 1E. Decimal of 19 is 25. When you build
the "Foundry", the game substracts 5 wood, 5 ore and 1500 gold-> check it in
Now look at E02E. To find it's decimal we take it backwards : 2EE0. And 2EE0 in d
is 12000 (the gold). 12000-1500(foundry_cost)=10500 that is in hex 2904. And
"abc1" file is hold as 0429 (the backwards of 2904). See ? And the other reso
those "000A". If you don't believe me, modify them, then load the respective
then see for yourself !
First look at that 04 in "abc1". Can it be the amount of new monsters that you ca
JUST AFTER you build something ? To be sure go back in the game and click on
"Foundry". You can recruit 4 Golems. YES ! Change that 4 in 20, for example,
result :) And take a closer look at the following 00 (with a red underline).
be the amount of other monsters you can recruit from the other structures. So
build their respective structures, modify their amount as you please. (they a
as word).
Now look at that 38. It doesn't look familiar to us. It can be that "no more buil
flag, or the "Foundry"'s ID. Because it is near to that "4 golems", we can pr
it's the ID.
But it is not changed from 00, but from 18 (look in "abc"). So here we make anoth
supposition : if we want to have all the buildings, we could try to set that
a big number (it was 18 when we hadn't had the "Foundry", it is 38 when we have t
"Foundry", let's set it to FF hoping to have all buildings :) ). But usually
use just a single byte for this, but a word or d-word. Let's try with d-word.
next 4 bytes from that 2C into this : First byte in FE and the next 3 in FF.
Because I tried with FF to all, but the game crashed :(. So you'll have this
Load the saved and voila ! All buildings except... MageGuild :(. No problem. Buil
Guild, then compare the new saved file (with Mage-Guild) with the one in whic
don't have Mage Guild. Then compare.... But to save you from this I'll tell y
to work with the MageGuild. Remember the above bytes that I told you to trans
FF ? After the last FF it comes a 00, right ? Change that 00 to 04.
Like this :
Why ?
To have level 4 Mage-Guild. Why level 4 and not level 5 ? Because YOU MUST bu
least a level of Mage-Guild to let the game initialize the spells, or else you wi
not have any spell in the guild (or you could "initialize" them yourself by c
the next ~22 bytes after the last monster recruiting_amount (see above the re
to any numbers that you might think of.
Then go back in the game too see the result. You can crash the game or :
- you can get all the spells in the MageGuild;
- you can get some ultimate artifacts like 'Ultimate Sword of Dominion' o
EVERY HERO that you hire from that castle (a programming bug?);
- some skrewling like "Expert on Set Water Guardian" as a SKILL;
- you can upgrade, for example, the boar to golem then to steel_golem (an
- many many other kool things.
As you might noticed, these are castle specific. They can be called "castle prope
you scroll down from the replacement, you'll see the castle name. So, when yo
castle name, you can edit its properties by changing the bytes above its name
If you scroll up from the replacement, you'll notice some FFs followed by some 00
them too, to see what's happening. The FF means nobody is in the garrison of
in the FF's slot. There are 5 slots where you can leave some army. Change the
other values (monsters IDs) to have army in respective slot, and change the r
00 to desired amount of troops. So FF place stands for monster type and 00 st
monster quantity in the garrison of the respective castle.
Speaking of sun, let's try to make a map hack in Heroes 2, using this saved-game_
hacking method. This map_cheating will be all we need, cause we've just found
hack resources/army/castles/spells (we can cheat as well on enemy_castles/her
your imagination ;) ).
So, restart Heroes 2 and like above, choose to play a campaign and select the goo
Roland. Now, you know the trick : DON'T DO ANYTHING in the game, just save it
"def". Ok... We want a map_hack, so let's discover a little map, by moving yo
down from the castle, but just a bit. And without doing anything else, save t
under "def1".
And here comes the 'technique' you've just learnt : compare the 2 files ("def.gmc
"def1.gmc"). We start, as usual, by thinking what can be changed between thes
- first of all is your hero position on them map (you moved your hero to disc
some map, right ?)
- then maybe your hero facing (where is his 'face' : left/right/up/down)
- then some map changes (undiscovered is discovered in the second file)
You could have less or more replacements, depending on how much you moved your he
darkness. Also, when you're trying to map-hack, you must know that you don't
'strange' replacements, but something like this :
- a lot of bytes (one after another) representing the map. Usually, one by
one little square on the map. Majority of these bytes are the same in both
save files (in our case "def" and "def1") because we have walked jus
with our hero, and this majority also represent the darkness (in bot
darkness is 'more present' than the reveal)
So, it is now clear for everybody : 00 stands for square_with_darkness and 01 for
reveal_square.
As I told you in a previous essay, games hold their map in matrix. We have just f
Heroes2's map_storing matrix. To reveal the map, just change all these 00s in
NOTE : Some bytes holding 80 value could be in the matrix. Don't worry about
overwrite them with 01 to reveal the map in that square.
Now, look at above replacement (the one with 'Mandigal' string). Mandigal is the
my hero in the game. And the replacement could be because we changed his posi
the game (we moved him). Hehe... I bet it is... So, like the castles, heroes'
are near their names (that bunch of bytes you see up and down the hero's name
the army he's carrying, his artifacts, spells, skills etc. I let you discover
Final words
~~~~~~~~~~~
Man... I worked a bit on this tut. Even if it sounds simple : "saved-game hacking
it's not like this. This game (Heroes2) was an easy "target" because it store
in classic format in the saved_files. Some games encrypt their data when they
and decrypt the data when they load the respective file. So there you can't g
with a hex-editor, you'll most likely need a debugger and A LOT of patience a
nerves.
2004
eof
How do you make a trainer? DDH There are a few ways to make a trainer. You can use a trainer making program or you can program your own. A couple of trainer making programs are MTC
(Magic Trainer Creator) and TMK (Trainer Maker Kit). TMK is the newest. If you really want to make a good trainer and better understand what you're doing, you can learn how to create a trainer
in a programming language. Visual Basic is easy, but requires large DLLs. C/C++ is the most common language used. Assembly isn't used by many, but produces the smallest/fastest trainers.
What is DMA?
DMA (Dynamic Memory Allocation) causes the offsets of the variable information in a program to change each time it's run. Since only the variable information offsets change, you can still defeat
DMA. All you need to do is load a debugger and modify the code of the game (Which the offset never changes) instead of poking the offset you had before. This requires at least a small
knowledge of assembly. When you're making a trainer, you just poke the code offset with your op codes. Op codes are the hex representation of assembly.
What is a debugger?
A debugger is basically a program that allows you to set breakpoints on memory and act on them. A debugger is required for getting by DMA.
Binary is a base 2 number system. 1001110011100111 is a binary number. You will most likely not have to use this in game hacking.
Decimal is the number system you are probably most familiar with. It is the standard number system and uses a base 10 format. 1,2, 3, 4, 5, 6, 7..etc
Chapter 1 overview
Chapter 8 conclusion
CHAPTER 1 OVERVIEW
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
You might be wondering what type of programming skills you need to become a
cracker. Knowing a higher level language such as Basic, Pascal, or C++ will
help you somewhat in that you will have an understanding of what's involved in
the process of writing a program and how certain aspects of a program
function. If you don't have any programming skills at all, you have a long
road ahead of you. But even if you can program in a high level language, in
order to crack you have to know assembly...
How proficient you are at assembly will determine how good of a cracker you
become. You can get by on learning a few basic instructions, how to use a
debugger, and one or two simple techniques. This will allow you to remove a
few shareware nag screens, and maybe you'll luck out and remove the copy
protection from a game or two, but that's it.
It's much much easier to learn to crack in DOS than windows. DOS is the
easiest environment to debug in. This guide will focus on DOS programs as
cracking windows apps is a little bit overwhelming unless you are already an
experienced cracker. And if you are, your wasting your time by reading this.
This manual is geared towards the raw beginner who has no clue as to where to
start and needs a little hand holding in order to get going.
There are several good beginners manuals out there, but most of them assume a
person has at least some experience in cracking or knows how to use the
different tools of the cracker, and the raw beginner usually becomes
frustrated with them very quickly because they don't understand the concepts
contained in them.
I wrote this guide as sort of a primer for the beginner to read before reading
the more comprehensive guides. I tried to keep it as simple as possible and
left a great deal of information out so as not to overwhelm anyone with too
much information at once. Hopefully after reading this guide it will be easier
for the beginner to understand the concepts of the more arcane guides out
there. So if you are reading this and it seems a little bit remedial,
remember, at one time you didn't know what a debugger was used for either.
Now in case your not familiar with the debugger and disk editor and what their
different roles in cracking are, I'll give a brief explanation of each. As
these are the crackers most used tools.
The debugger is what you will use to actually crack the program. When you load
a program you wish to crack into the debugger, it will load the program and
stop at the first instruction to be executed within the code segment. Or, you
can also optionally break into an already running program and it will halt the
program at the instruction you broke into it at and await further input from
you. At this point, you are in control of the program.
You can then dynamically interact with the program and run it one line of code
at a time, and see exactly what the program is doing in real time as each line
of code is executed. You will also be able to re-assemble instructions (in
memory only), edit the contents of memory locations, manipulate the cpu's
registers, and see the effects your modifications have on the program as it's
running. This is also where all your system crashes will occur... There is a
lot of trial and error involved in cracking.
As stated above, the debugger will only modify the program while it's up and
running in memory. In order to make permanent changes, you need to load the
program file to be patched into the disk editor and permanently write the
changes you've made to disk. A detailed explanation of how to do this will be
made in chapter 5.
So, with this in mind, you need a few essential tools... The first one is a
good debugger. The original draft of this guide gave explicit instructions on
how to use my favorite debugger. After considerable deliberation, I decided to
re-write it and make the instructions more generic so you could apply them to
most any debugger. You will also need a disk editor, it doesn't matter which
one you use as long as it will load the program file, search for and edit the
bytes you want to change.
I uuencoded a few cracking tools that you will find indespensible and placed
them at the end of this guide. I won't go into the use of the cracking tools
right now. But believe me, you absolutely need one of them, and the other one
will save you a lot of effort. I also uuencoded the program that we will crack
in the walk through and included it in this guide as well.
As you get better, you'll have to write programs that will implement your
patches if you decide to distribute them. The patches themselves don't have to
be written in assembly.
The source code I included in this manual for the byte patcher is the first
patcher program I ever wrote, and is extremely simple. It's written in
assembly because that's the only language I know how to program in. but if you
are already proficient in a higher level language, it should be trivial for
you to duplicate it's methods in your preferred language.
Ok, before I begin, I'd just like to stress how important it is that you know
at least some assembly before trying to continue. If you don't, you will get
lost pretty quick from here on out. Comprehension of the base 16 (hexadecimal)
number system is also required.
I'm not about to give a remedial course on assembly or hex math, that would
take too long and I'd probably leave too many questions un-answered. Besides,
there is enough information on them available from a myriad of other sources.
So, from now on in this guide, I'm assuming you have a fair working knowledge
of assembly and hexadecimal. If I say something you don't understand or you
cannot grasp some concept, look it up somewhere...
You should be able to translate these instructions to the actual key strokes
and commands that your debugger uses... If you don't know how to use a
debugger, PAY ATTENTION!!! If you already know how to use a debugger you can
skip this section as it is only a general overview of different windows and
functions designed for the absolute beginner who has no clue as to what he is
looking at.
The reason I included this section is because most manuals for debuggers tell
you how to use the various features of the debugger, but they don't give any
insight on how to apply those features, as they assume the person reading them
already knows how to debug a program.
First, I'll give an overview on the different windows that most debuggers use.
REGISTER WINDOW:
The register window contains the general purpose and flags registers of the
cpu. You will notice that the general purpose registers contain hexadecimal
values. These values are just what happened to be in there when you brought up
the debugger. you will also notice that some of the flags are highlighted
while some are not. Usually, the highlighted flags are the ones that are SET.
While the ones that are not highlighted are CLEARED. The layout of this window
will vary from debugger to debugger, but they all basically are the same.
From this window you will be able to manipulate the contents of the cpu's
registers. some debuggers accomplish this by clicking on the register to
modify with the mouse and then entering a new value. Other more powerful
debuggers use a command line interface, you'll have to discover how your
debugger goes about this yourself.
You can change the values of the registers while debugging a program in order
to change the behavior of the running program. Say you come across a JNZ
instruction (jump if not zero), that instruction makes the decision on whether
or not to make the jump based on the state of the (Z)ero flag. You can modify
the condition of the (Z)ero flag in order to alter the flow of the programs
code.
By the same token, you can modify the general purpose registers in the same
manner. Say the AX register contains 0000, and the program bases it's actions
on that value, modifying the AX register to contain a new value will also have
the effect of modifing the flow of the code. After you become comfortable with
using a debugger you'll begin to appreciate just how powerful this window is,
and you'll aslo discover soon enough just how totally it can screw your
system.
DATA WINDOW:
The data window will display data as it exists in memory. From this window you
can usually display, search, edit, fill, and clear entire ranges of memory.
The two most common commands for this window are display and edit. The search
command is also useful in cracking. But for the level of debugging I'll be
teaching you in this guide, we won't make much use of this window. You have a
lot to learn before this window becomes an asset to you.
CODE WINDOW:
The code window is the window in which you will interact with the running
program. This is the most complex window, and it is where the bulk of
debugging occurs. I'll just go over some keystrokes and a few commands here,
as the majority of learning how to use this window will come when I show you
how to crack a program.
The layout of the window is pretty simple, the group of 8 numbers with the
colon in the middle of them to the far left of the window is the
address:offset of that line of code. Each line of code in this window is an
instruction that the program will issue to the microprocessor, and the
parameters for that instruction. The registers that contain the address for
the current instruction waiting to be executed are the CS:IP registers (code
segment and instruction pointer).
You will also notice a group of hex numbers to the right of the addresses,
this group of numbers is the hexadecimal equivalent of the mnemonic
instructions (pronounced new-mon-ik). The next group of words and numbers to
the right of the hex numbers are the mnemonic instructions themselves.
Now we'll move onto the HOTKEYS. I won't go into all of them, only the most
useful ones, same for the commands.
The RESTORE USER SCREEN KEY: This key will toggle the display between the
debugger and the program you are debugging without actually returning control
to the program itself. it's useful to check what the program is doing from
time to time, especially after stepping over a CALL.
The HERE KEY: This key is the non-sticky breakpoint key. To use it, Place the
cursor on a line of code and hit it. The program will then run until it
reaches that line. When (and if) the program reaches that line, program
execution will halt, control will be returned to the debugger and the
breakpoint will be removed.
The TRACE KEY: This key will execute one line of code at a time and will trace
into all calls loops and interrupts.
The BREAKPOINT KEY: This is the sticky breakpoint key. This will enable a
permanent (sticky) breakpoint on the line of code that the cursor is on. When
a sticky breakpoint is enabled, program execution will halt and control will
be returned to the debugger every time that line of code is encountered within
the running program until you manually remove it.
The SINGLE STEP KEY: The most used key on the keyboard. This key will execute
one line of code at a time but will not trace into calls loops or interrupts.
When you step over a call interrupt or loop with this key, all the code
contained within the sub-routine is executed before control is returned to the
debugger. If the program never returns from the sub-routine, you will lose
control and the program will execute as normal.
The RUN KEY: This key will return control to the program being debugged and
allow it to execute as normal. Control will not be returned to the debugger
unless a breakpoint that you've set is encountered.
Now for a few commands. The GO TO command functions like the HERE key in that
it will insert a non-sticky breakpoint at the specified address.
When you enter this command the debugger will return control to the program
until the line of code you specified in the GO TO command is reached. When
(and if) the CS:IP registers equal the address you typed in, the program will
halt, control will be returned to the debugger and the breakpoint will be
removed.
You might be wondering why you would want to type all this in when you can
just hit the HERE KEY instead. The answer is this; the HERE KEY is great if
you want to set a local breakpoint. By a local breakpoint I mean that the
breakpoint you want to set is somewhat close to your current location in the
program.
But what if you want to set a breakpoint on a line of code that isn't in the
current code segment? You wouldn't want to use the HERE KEY cause the address
is no where near the point you are at in the program. This, among other uses
is where the GO TO command comes in.
The ASSEMBLE command is the command you will use to re-write the programs
instructions. This command will allow you to assemble new instructions
beginning at the address you type in, or at the current CS:IP. The
instructions you enter will replace (in memory only) the existing program code
at the address you specified. This is another method you will use to alter the
running program to behave as you wish and not as the programmer intended it
to.
EXAMPLE: Lets say that there is a line of code that reads JNZ 04FC, and we
want to change it to read JMP 04FC. You would issue the ASSEMBLE command and
specify the address of the code you wish to change, then type in JMP 04FC.
Now the line of code in the code window who's address you specified in the
ASSEMBLE command will be overwritten with the code you typed in. Some
debuggers automatically default to the address contained in the CS:IP for this
command.
There are a whole host of other commands available in this window depending on
what debugger you are using, including commands to set breakpoints on
interrupts, memory locations, commands that list and clear breakpoints,
commands to un-assemble instructions etc etc...
The first thing I want to do before going into some simple techniques is to
explain the purpose of one of the uuencoded cracking tools at the end of this
guide. And also to go over some general procedures you should perform before
actually loading a program you wish to crack into the debugger.
This is the reason I encrypt all of the cracks that I distribute. The routines
I write are not that hard to defeat, but I figure anyone with the skill to
crack them is far above having to hack their name into them...
Ok, back to the file, the name of the program is UNP and it is an executable
file expander. It's purpose is to remove the compression envelope from
executable programs. And it supports most of the compression routines
currently in use...
A lot of the compression routines will cause a debugger to lock up if you try
to step through the compressed file, especially PKLITE v1.15. And seeing as
how the file is compressed, if you load it into a disk editor it will just
look like a bunch of garbage and you'll not be able to find the bytes you want
to edit anyway.
UNP is very easy to use, just type UNP [filename] and if there is any type of
compression envelope that UNP understands on the file, UNP will remove it. You
can then load the file into a debugger and hack away...
But before you load a program into the debugger you should run the program a
few times and get a feel for it. You want to see how the protection is
implemented. Whether it's nag or delay screens and at what point in the
program they fist appear, or where in the program does the first mention of
being unregistered or an evaluation copy appear?
This is important. Because before the program displays the first mention of
being unregistered, it has to do the protection check. and this is where you
will usually want to concentrate. Also look for registered functions being
disabled, and sometimes date expirations. The program could also be looking
for a registration key.
There are basically three categories that shareware programs fall into... They
are begware, crippleware, and deadware.
The begware category is comprised of programs that have all the registered
features enabled but every time you run them they will display screens that
bug you to register. This is usually the easiest form of protection to remove
and it's the type I'll go over in the walk through.
The sample code fragments in this section are not taken from actual programs.
I just made them up off the top of my head while I was writting this guide,
and there are bound to be some errors in them. Please dont write me and tell
me this, I already know it.
Most forms of copy protection have one weak spot, and this is the spot you
will concentrate on. They have to perform the protection check and then make a
decision based on the results of that check. And that decision is usually a
conditional jump. If the check was good the program will go in one direction,
if it was bad it will go somewhere else.
So, you've run the program through a few times and you know at what point the
routines you want to modify first appear, you've also run UNP on it and have
removed any compression envelopes. Now you load the program into the debugger
and wonder what to do next...
What you want to do is to step through the code until something significant
happens like a nag screen gets displayed, or a doc check comes up or the
program tells you that the function you just tried to use is only available in
the registered version. When you reach that point you can then start to
evaluate what portion of code to begin studying.
Let's say you have a program that displays a nag screen and you want to remove
it. You step through the program until the nag screen pops up, you now think
you know the location of the instructions that are causing it to be displayed.
So you reload the program and trace back to a point a few instructions before
the call to the nag screen, and this is what you see:
Now, let's assume that the memory location referenced by the first line of
code does indeed contain 00 and that it is the default value placed in there
by the programmer to indicate that the program is unregistered.
The first line of code is checking the value contained in the memory location
to see if it is 00 or not. If the location does contain 00, the compare
instruction will cause the Zero flag to be set. If the location contains any
other value than 00, the Zero flag will be cleared.
The second line of code makes the decision on how to proceed based on the
results of the compare instruction. The JNZ instruction will make the jump to
the fourth line of code if the zero flag is cleared. This will bypass the call
to the nag screen on the third line. If the zero flag is set, no jump will
occur and the call will be made.
The third line of code contains the call to the nag screen. If it is executed
the nag screen will be displayed. The fourth line of code is just the next
instruction in the program.
Once you have found and analyzed this piece of code within the program, you
can now decide on how to bypass the call on the third line. There is no single
way to do this. I can think of a half dozen different ways to patch the
program so it will not make the call. But there is a best way...
First, you could just replace the JNZ 014B with JMP 014B. This is an
unconditional jump and it will bypass the call on the third line no matter
what the memory location that the first line of code is referencing contains.
You could also change it to read JZ 014B so that the jump will be made if the
location contains 00, and not the other way around. You could even change the
CMP BYTE PTR [A76C],00 instruction to JMP 014B.
Or you could just NOP out the call on the third line altogether seeing as how
it's a local call. By a local call I mean that the code contained within the
call resides in the same code segment as the call instruction itself.
This is an intersegment call. You will see other calls that reference lines of
code outside of the current code segment. These are intrasegment calls, and
have to be handled differently. They will look something like CALL 0934:0AC5,
or CALL FAR 0002. I'll go over how to handle intrasegment calls later on.
The compare instruction is 5 bytes and the jump instruction is only 2 bytes,
so you would have to add 3 nops in order to equal the length of the original
compare instruction. Otherwise you would throw off the address of every
instruction after it in the program and end up with a bunch of unintelligible
garbage. Not to mention a major system crash...
When the NOP instruction is encountered no operations will take place and the
CS:IP will then be incremented to the next instruction to be executed. A lot
of compilers leave nop's in the code all the time and it's a great instruction
you can use to wipe out entire lines of code with.
The above methods of bypassing the call are called 'dirty' cracks in that they
have only modified the end result of the protection check and have done
nothing to alter the actual protection check itself.
All the techniques I showed you above are only implemented after the check is
made. They will bypass the nag screen, but what if the program also has
registered features that are disabled or displays another nag screen upon
exit? The above methods only remove the original nag screen and don't address
the reason the screen is being displayed in the first place.
A much cleaner way to crack the above piece of code would modify the cause and
not the effect. And could be written like this:
09D8:0140 CMP BYTE PTR [A76C],00 09D8:0140 MOV BYTE PTR [A76C],01
09D8:0145 JNZ 014B 09D8:0145 JMP 014B
09D8:0148 CALL 0C50 09D8:0148 CALL 0C50
09D8:014B MOV AH,18 09D8:014B MOV AH,18
Remember that the protection check is basing it's actions on the value
contained in the memory location that the first line of code is checking. The
original code displayed the nag screen if the value of that location was 00,
meaning it was unregistered. So that means a value of 01 indicates a
registered copy. It could be the other way around as well, it just depends on
how the programmer worded the source code. But we know in this case that
00=false so 01=true. These are Boolean expressions and most compilers use the
AX register to return these values.
By changing the first line from CMP BYT PTR [A76C],00 to MOV BYTE PTR
[A76C],01 the program no longer performs the protection check. Instead, it
places the correct value in the memory location to indicate a registered copy.
Now if the program checks that memory location again later on it will think
that it is registered and activate all of it's disabled features, or not
display a second nag screen upon it's exit if it has one.
I changed the second line of code to an unconditional jump because the compare
instruction on the first line no longer exists, and the conditional jump on
the second line may still access the call to the nag screen on the third line
if the Z flag was already set before the old compare instruction was
encountered.
Don't think that all programs are this easy, they're not. I just
over-simplified this example for instructional purposes. And I really wouldn't
patch the code like that, although the last method should work fine for all
registered features to be enabled. Remember I told you there was a best way to
crack this?
What I would actually do is to trace further back into the program and find
the line of code that sets up the memory location referenced by line one of
the code for the protection check in the first place and modify it there. This
is an example of a 'clean' crack.
I just did it in the above manner to try and show you the difference between
clean and dirty cracks without totally confusing you. And to give you a
general idea on how to creatively modify existing code.
If you are using soft ice as your debugger, an easy way to find the
instruction that sets up the memory location for the protection check is to
set a breakpoint on the location when it gets 00 written to it. The syntax
would be BPM XXXX:XXXX W EQ 00, where XXXX:XXXX is the address of the memory
location referenced by the compare instruction on line 1.
Now when the program wrote 00 to that memory location, soft ice will pop up
and the CS:IP will be sitting at the next instruction after the one that wrote
00 to the memory location. You will now be able to evaluate the code around
the instruction that writes to the memory location and decide on how to
proceed.
This also could just be a general purpose location that the program uses for
generic references (especially if it's in the stack segment), and it could
write 00 to it several times throughout the course of the program for a
variety of different functions. You should let the program run normally after
soft ice broke in to see if it will trigger the breakpoint again. If it
doesn't you know that the location is only used for the protection check. But
if the breakpoint gets triggered several more times, you will have to figure
out which set of instructions are being used to set up for the protection
check before proceeding.
The above examples were based on shareware programs. Now I'll go over a few
techniques to remove copy protection from commercial games that have doc
checks in them as the methods are slightly different...
shareware programs are usually coded so that they check a variable in memory
before deciding if they are registered or not and how to proceed. Commercial
games with doc checks take a different approach as they check nothing before
calling the copy protection. It always gets called every time you play the
game no matter what. As a result, the doc check routine is usually easier to
find, and there are basically two types of doc checks... The passive check,
and the active check.
The passive doc check is easier to defeat than the active. In the passive doc
check, the program will issue a call to the copy protection routine. And if it
is unsuccessful will either abort the program, or loop back to the beginning
of the routine and give you a few more tries before aborting. The entire
protection routine will be included in a single call, so merely nopping out
or bypassing the call will be sufficient to remove the copy protection.
A few good examples of this are Spear of Destiny by ID, and the Incredible
Machine by Sierra. Yes I know that they are old, but if you happen to have a
copy of either one laying around they are excellent examples of passive doc
checks to practice on.
The first three lines of code are just setting up for the call, the call on
the fourth line is the protection check itself. It will display the input
window asking for a word from the manual, will perform the protection check,
and will display an error message if you input the wrong word. It can also
optionally give you a few more tries if you type in the wrong word.
If you fail the protection check, the program will abort without ever having
returned from the call. The fifth, sixth, and seventh lines are the next
instructions to be executed if the protection check was successful and the
program returns from the call.
Simply nopping out the call to the protection routine will be sufficient to
crack this type of doc check. No window asking for input will appear, and the
program will continue on as if you had entered the correct word from the
manual. Remember that I told you that the NOP instruction is only one byte in
length, so you have to enter as many nop's as it takes to equal the length of
the code you are modifying.
The active doc check is more complex. The program will issue the check and
unlike the passive protection, will set a variable in memory somewhere and
reference it later on in the program.
You can crack this type of protection somewhat using the methods for the
passive check and it might run fine for a while. But if you didn't crack it
right, later on when the next episode gets loaded or you reach a crucial point
in the game, the program will reference a memory location and bring up the
copy protection again, or abort. This type of protection is more akin to how
most shareware programs operate and MUST be done with a CLEAN crack.
The above code is the outer loop of the protection routine. Look at the call
on the seventh line and the compare instruction on the eighth line. When the
call to the input routine or in the case of shareware, the check routine is
paired with a compare instruction in this manner, You can bet that the program
set a memory variable somewhere inside the call. Especially suspicious is the
unconditional jump on line 10 that jumps backwards in the code.
This won't always be the case as no two programs are alike, and simply
changing line 9 of the code from JNZ 0B6E to JMP 0B6E to force the program to
run even if you fail the doc check may allow the program to run just fine.
Let's say that this is how you patched the program and it runs. Great, your
work is done... But what if before the first level loads, or at some other
point within the program the input window pops up again asking for a word from
the manual?
You realize that you should have patched it right in the first place as you
now have to go back in there and fix it. This is why so many groups have to
release crack fixes, they patch the program in a hurried manner and don't even
run it all the way through to see if it's going to work.
Ok, back to the problem at hand... The above method of patching the program
didn't work, so you now have to load the program back into the debugger and
trace into the call on line seven to see whats going on in there. And you
can't NOP this kind of call out either, this is an intrasegment call.
And when a program does a FAR call (a call to a segment of memory outside the
current code segment), The program goes to the address that was assigned to
that segment at run time. The CS, DS, ES, and SS will be different on every
computer for the same program.
And seeing as how these addresses don't get assigned until run time, the
actual bytes for the addresses of far calls don't exist in the program file as
it resides on your disk. That's why you can't just NOP a CALL FAR instruction
out.
However, the bytes for calls that are within the same segment of code as the
calling instructions themselves will be contained within the file as it
resides on disk. And that is because even though the program doesn't get the
addresses for the actual segments until run time, the offsets within those
segments will always be the same.
Back to the example, let's say you've traced into the call on line seven and
this is what you see:
Again, this code is over simplified as I figured all of the code would be
overwhelming and really is not needed to get my point across. And as I've
stated before, every program will be different anyway, so the actual code
wouldn't help you. Instead, I want to give you a general overview on what to
look out for.
So, what do you think is the best way to patch the above piece of code? Take a
few minutes to study the code and formulate some ideas before reading on. Then
compare your methods to mine. And remember, as with any code there is no
single way. But as always, there is a best way... I'll go over few of them one
at a time, starting with the dirtiest and finishing up with the cleanest.
The dirtiest crack for this piece of code also happens to be the method you
will use to nop out intrasegment calls. It really isn't nopping out, but
seeing as how you can't nop it out, just let the program make the call and
change the first line of the code within the call to RETF. This will return
from the call without ever having executed any of the code contained within
it.
Remember that this call only displays the input window and sets the memory
variable. The outer loop of the routine makes the decision on how to proceed
based on the results of the call.
To do this, you would change line one of the call from MOV [324F],BX to JMP
116B. This will restore the registers and return from the call without ever
having executed any of the code within the call. But seeing as none of the
code got executed, you'll have to patch line 9 of the outer loop from JNZ 0B6E
to JMP 0B6E as you now need an unconditional jump to force the program to
continue. This doesn't address the problem of the memory variable though, and
the program won't be completely cracked. That's why if you did it like this
you would end up releasing a fix.
A cleaner crack would be to change line 11 of the call from JCXZ 1154 to JMP
1154. Now when the window pops up and asks for a word, it will set the correct
memory variable and the program will run no matter what word you type in. This
method is still not desirable because the end user will get the input window
and have to type something every time they play the game.
The cleanest way to crack this, and the way I would do it is to change line 4
of the call from CALL F157 to JMP 1154. This method will totally bypass the
input window, place the correct variable in memory and return from the call
without the end user ever having seen even a hint of copy protection.
With this method, the outer loop does not need to be patched cause the program
now thinks that it displayed the input window and the correct word was typed
in. Now when the program checks that memory variable later on, it will think
that you successfully passed the original check and skip the second protection
check.
There is also an added benefit to the last method... Some games will bring up
the protection check between each and every level of the game even though you
type the correct word in every time. But if you've completely killed the
routine as in the last example, you'll never be bothered by it again no matter
how many times the program tries to bring it up.
Please be aware of the fact that these are not the only methods that
programmers will use in copy protection schemes. These are just the basics and
there are several variations on these routines. The only way to be able to
know what any given routine is doing at any time is to master assembly
language.
Before we move onto the walk though, there is one other technique I want to go
over with you. And that is how to get out of a loop. You will get stuck in
loops constantly during the course of debugging a program and knowing how to
get out of them will save you a lot of time and frustration. You will find
that programs contain loops within loops within loops etc... Some loops can
execute hundreds of times before the program will advance, especially ones
that draw screens.
When you realize that you are stuck in a loop, execute the loop several times
and keep an eye on the highest address the loop reaches before jumping
backwards within the code. Once you have found the end of the loop, write down
the address of the jump that re-executes the loop, and then look for
conditional jumps inside the loop that will put you past the address of that
backwards jump. You will want to set a breakpoint on the address this
instruction jumps to and then let the program run normally. The HERE KEY is
excellent for this type of situation.
If you guessed right, control will be returned to the debugger when the
program reaches that instruction. If you guessed wrong, you will lose control
of the program and will have reload it and try again. This is where writing
down the address comes in handy, just reload the program and then issue the GO
TO command and supply it the address of the backwards jump that you wrote
down.
The program will run until it reaches that address and control will then be
returned to the debugger. This will save you from having to trace all the way
through the code again in order to reach the point where you lost control of
the program in the first place. You could just use sticky breakpoints instead,
but what you will end up with is a half dozen or so breakpoints in as many
different locations in the code, and it's very easy to loose track as to which
breakpoint is which.
That's why I use non-sticky breakpoints and write down the address I'm
currently at before executing suspicious looking calls and jumps. My desk is
usually scattered with scraps of paper filled with notes and addresses. I only
use sticky breakpoints for specific situations. It's much easier to just
reload the program and use the GO TO command to get back to the point in the
program where I lost control.
First of all, I want to go over some of the criteria I used in choosing the
program I used for the walk through. An important factor was the programs
size. I want to keep this manual as small as possible, and I chose the program
that is included in this guide because among other things it is the smallest
one I could find that best illustrated the example of a simple nag screen.
Whether or not the program was one that you would actually find useful was not
a consideration, as you should eventually be able to crack just about any
program you wish if your serious about cracking. If you come across a program
that has you stumped, leave it alone for a while and then try again after
you've cracked something else. You may find that whatever you were having
problems with is now easier to understand.
Before we start I want to go over one other thing. When you load a program
into a debugger, the debugger will load the program and halt at the very first
instruction to be executed within the program. You can also at this point let
the program run normally and then break back into it at a later point.
When you use the second method it will halt the program at the current
instruction and return control to the debugger, but you may not end up in the
program itself. You could have broken into the program while it was in the
middle of executing either a DOS or BIOS interrupt, and the code you are in
belongs to either DOS or BIOS and not the program you are debugging.
You can tell by looking at the addresses of the instructions in the code
window where you are, low segment addresses indicate you are in DOS, and
addresses that start with FXXX indicate a BIOS routine.
If you break into the program while it is in one of these interrupt routines
you will have to trace your way back into the programs code, this will usually
be indicated by an IRET (interrupt return) instruction. When you do get back
to the program code, you will then have to trace your way back to the top of
the call that issued the interrupt you broke into. Then you may also have to
trace back to the top of that call, and to the top of that call, etc etc,
until you reach the top level of the program. After you've done this a few
times you'll begin to recognize when you've gotten back to the main flow of
the program...
On the other hand, when you load a program into the debugger and begin
stepping through the code from the very first instruction to be executed
within the program, you have the best picture on the overall flow of the
program as you are sitting on top of everything.
But some programs don't access the copy protection until they are further
along in the code. In this case, it's best to let the program run normally and
then break into it at a later point. Otherwise, you will have a ton of code to
trace through before the protection routine is accessed, and this can become
quite tedious. Which method you choose will be determined after you've run the
program through a few times and decide how and where you want to break into
it.
One last thing, DOS will always load a program into the same memory range
provided that no other programs are run in the interim. It's important that
you always boot with the same config files and don't run any other memory
resident programs between cracking sessions.
If you load a program into the debugger and start tracing, then quit. And
before The next time you load that same program into the debugger, you boot
with a different config or load a memory resident program that you didn't have
loaded the first time you started cracking that program, the segment addresses
will change and the addresses you wrote down will be useless. This is because
the memory map of your computer will change.
When I boot with my debugging config (when I use my DOS debugger, Windows
manages memory differently and these steps are not needed), the only things I
load are a mouse driver, 4DOS, my debugger and ansi.sys (needed for cracking
bbs doors). This way I'm assured that the program I want to crack gets loaded
into the same memory region every time I run it, providing I don't run any
other memory resident programs before loading the program to be cracked into
the debugger.
Take soft ice as an example, if you load a program into it using LDR.EXE and
begin debugging, then later on you decide to just execute the program and
break into it without first loading it with LDR.EXE, the segment addresses
will change. That's because LDR.EXE is a program and using it will throw the
segment addresses off by one word as opposed to just breaking into an already
running program without first loading it with LDR.EXE.
From now on, when I say step, step through, or step over, I want you to use
the SINGLE STEP key. When I say trace, I want you to use the TRACE key once
and only once!!!! The TRACE key is a highly specialized key and is not
intended to be used multiple times like the SINGLE STEP key. If you don't
follow these instructions, your gonna get lost...
OK, once you've run budget minder a few times you will notice that it displays
a nag screen before the main program is executed. You will also notice that
this nag screen is the only type of protection that the program has. It
doesn't contain any features that are disabled, nor does it display an
additional nag screen upon exit.
It's okay to apply a dirty crack to this program as all you want to do is kill
the nag screen, so you have a little more leeway on how to patch it. And if
you want to try different methods of patching it than the ones I give, it
should still work fine.
That was the most important factor in my decision to use this program for the
lesson. I wanted to walk you through a program so you would become comfortable
with it's flow, and I also wanted the program to be easy enough so that once
you became familiar with it, there was enough room for you to experiment and
try out your own methods.
In this case, it's best to load the program into the debugger and start
stepping through it right away. The protection is implemented very close to
the beginning of the program, and this method of loading the program will put
you right on top of everything.
Allowing the program to run and breaking into it later on will not serve any
useful purpose. You'll just end up having to trace your way back to the top.
Besides, the nag screen comes up so fast you'll probably miss it if you try
the second method anyway.
Before you load it into the debugger, run UNP on BUDGET.EXE... AHA! The file
was compressed with EXEPACK. It's now ready to debug as you've removed the
compression envelope. Just for the hell of it, run UNP on it again. I've come
across a few programs that have had multiple compression routines on them. If
it shows up negative, your set to go.
Now load BUDGET.EXE into the debugger, the program will be sitting at the
first instruction to be executed awaiting your next command... Use the SINGLE
STEP key to start stepping through the code and keep an eye on the
instructions as you are stepping through them.
Shortly you will come to a couple of calls, before you step over the first
one, write down it's address. Now step over the first call with the SINGLE
STEP key. Nothing happened, so you have to continue stepping through the code.
But if something did happen when you stepped over this call like the nag
screen being displayed or if you lost control of the program, you could just
reload the program and issue the GO TO command to get back to that point using
the address you wrote down.
Step over the second call, nothing again. Ok, keep stepping through the code
and keep an eye on the instructions. You will encounter a third call about 6
instructions or so after the second call, step over it with the SINGLE STEP
key... Bingo, you have found the call to the nag screen. Hit a key to exit the
nag screen and you will now be sitting in the main program screen.
But you no longer have control of the program. Remember I said you would loose
control if you step over a call loop or interrupt and the program never
returns from it? Hopefully you wrote down the address of that last call before
you executed it. Now you can just quit out of the program and reload it. Then,
once it's reloaded, issue the GO TO command to get back to the call without
having to trace your way back there. So go ahead and do this before reading
on...
Ok, we are all back at the third call. It's address will be CS:0161, remember
that the segment adresses will always be different for every computer, but the
offsets will be the same. So from now on I'll write the addresses in that
manner...
We know that the last time we executed this call, the program never returned
from it. So now we are going to have to trace into it for a closer look. Trace
into the call with the TRACE key, don't use the SINGLE STEP key this time or
you'll loose control again.
You will now be inside the code for that call, start stepping through it again
with the SINGLE STEP key, you will see some calls. Better write down your
address before you step over them.
Step over the first two calls, nothing... Use the RESTORE USER SCREEN key to
toggle the display between the debugger and the program. Still a blank screen,
so nothing important has happened yet. Now toggle the RESTORE USER SCREEN key
to get the debugger screen back and continue stepping through the code.
You will see another call and some more code, just step through them until you
reach the RETF instruction and stop there. Toggle the display with the RESTORE
USER SCREEN key, the screen is still blank...
But we executed all of the code within the call and are ready to return
without anything happening. The nag screen didn't get displayed nor did we
loose control and end up in the main program, How come?
Step over the RETF instruction with the SINGLE STEP key and you'll see why...
The address that we return to is not the next instruction after the original
call. Part of the code within the call we traced into revectored the return
address for the original call and sent us to an entirely different location
within the program.
This is why we lost control when we first stepped over the call, the debugger
was expecting the program to return to the next instruction after the original
call, but it never did...
So the instruction that we returned to was not the original line of code that
was expected, instead we are at another far call. If you haven't gotten lost
you should be at CS:0030 CALL CS:28BC.
Write down the address of the CS:IP and then step over this call with the
SINGLE STEP key, there is that annoying nag screen again. Hit a key to exit
the nag screen and control will be returned to the debugger. This time the
program returned from the call and you are in control again. So you now know
that this call is the one that displays the nag screen and it is the one you
want to kill.
Hit the RUN key and let the program run, now quit out of it from the main
program screen and reload it into the debugger. Use the GO TO command and
supply it the address for the call to the nag screen.
Ok, now lets see if the program will run or not if we don't execute the call
to the nag screen. The call is at CS:0030 and the next instruction after the
call is at address CS:0035... A quick way to jump past this call without
executing it is to just increment the instruction pointer register to the next
instruction.
If you are using turbo debugger, place the mouse cursor on the line of code at
CS:0035 and right click the mouse. A window will pop up, then left click on
new IP, or increment IP. If you are using soft ice, type rip=0035 and hit
enter. Any other debugger, I have no clue...
Now that we've moved the IP past the call to the nag screen let's see if the
program is going to run. Hit the RUN key, this time the nag screen doesn't
come up, instead you are brought right into the main program screen.
It looks like getting rid of that call is going to do the trick. Now that we
know the program will run without making that call, it's time to decide on how
to patch the program so the call is never made again.
Think back to the original call we traced into for a minute, that call was the
one that revectored the return address and brought us to the call to the nag
screen. Therefore, it's reasonable to assume that that call is the protection
check, and it might be a good idea to have another look at it.
Before we do that there is one other thing I want to show you, and that's how
to allow the program to make the call to the nag screen and return from the
call without executing any of the code contained within it.
This isn't the method we will use to patch this program, but it's an important
concept to grasp as you'll end up doing it sooner or later on some other
program anyway. Remember that this is a far call and you can't just nop it
out.
Quit the program, reload it, and get to the address of the call to the nag
screen. Last time through we just incremented the IP to bypass it. Now we will
trace into it to see what it is doing.
Hit the TRACE key and trace into the call. Now start stepping through it with
the SINGLE STEP key, don't bother writing any addresses down for now. There
are several dozen calls in this routine along with shitloads of other code.
Toggle the display with the RESTORE USER SCREEN key after you step over a few
of the calls and you will see that the program is in the process of drawing
the nag screen.
Keep stepping through it and you'll see more and more of the screen being
drawn as the code progresses. This is getting boring, so stop stepping through
the code and start scrolling the code window down with the down arrow key and
watch the code. If you are using soft ice, the F6 key toggles the cursor
between the code and command windows, and the cursor must be in the code
window in order to scroll it.
What you are looking for is the RETF instruction as this is the end of the
call. Keep scrolling, I told you this call had a ton of code in it. When you
do find the RETF instruction write down it's address, it is CS:2B0E in case
your having trouble finding it. Ok, you've got the address of the RETF far
instruction written down so now just let the program run, quit out of it,
reload it, and get back to the call for the nag screen.
You should now be sitting at the call to the nag screen, trace into it and
stop. The first instruction of the call is MOV CX,0016 and this is where the
CS:IP should be pointing to. What we want to do now is to jump to the RETF
instruction and bypass all of the code within the call itself. So let's
re-assemble the MOV CX,0016 instruction and replace it with a new one.
First, make sure you are at this instruction, if you've traced passed it your
gonna have to reload the program and get back to it... OK, we are all sitting
at the MOV CX,0016 instruction and it's address is contained in the CS:IP
registers.
Now ASSEMBLE JMP 2B0E (the offset address of the RETF instruction) and specify
the address of the CS:IP. The MOV CX,0016 instruction will be replaced with
JMP 2B0E. And seeing as how both of these instructions are the same length we
didn't have to pad it out with any nop's.
Now hit the RUN key, you are brought into the main program and the nag screen
didn't get displayed! We allowed the program to make the call, but we didn't
allow any of the code within the call to be executed. And as far as the
program is concerned, it made the call and the nag screen was displayed.
Now let's go back and take another look at the call that we suspect is the one
that contains the protection check itself. Reload the program and go to the
original call that revectored the return address, now trace into it. I've
traced into the calls that are contained in here and they are setting up the
addresses for the RETF instruction at the end of this call among other things.
You don't need to trace into them as you might not understand what's going on,
but if you feel up to it, go right ahead.
What I want to concentrate on are the last four lines of code in the call as
they are the ones that finally set up the address to return to. Step through
the code until you are at CS:00A8 and take a look:
CS:00A8 8B04 MOV AX,[SI] DS:SI=0000
CS:00AA 053000 ADD AX,0030
CS:00AD 50 PUSH AX
CS:00AE CB RETF
The first instruction is loading the AX register with the contents of the
memory location that the SI register is pointing to. And you can see by
looking at the memory location that the DS:SI pair is pointing to that it
contains 0000. (this is where the display command and data window come in
handy).
The third instruction is placing the contents of the AX register onto the top
of the stack.
The fourth instruction is returning from the call, and where do you think that
the RETF instruction gets the address for the return? Yep, you guessed it, it
gets it off the top of the stack. Funny that the instruction right before it
just placed something there isn't it?
Also funny is that it happens to be the address of the nag screen. Look at
what is being added to the AX register on the second line of code. Boy that
sure looks like the offset address to the nag screen to me.
Remember that the next instruction after the nag screen is CS:0035, now look
at the first line of code. The contents of the memory location it's
referencing contains 0000, and I'll bet that if your copy was registered it
would contain 0005 instead.
Why? because if the first instruction placed 0005 in the AX register, when the
second line of code added 0030 to it, you would end up with 0035 which happens
to be the address of the next line of code after the nag screen.
Then the third instruction would place 0035 on the stack and that is where the
RETF instruction would go to. If this were the case, the nag screen would
never get displayed...
Well, what do you think we should do? We could trace further back in the
program and try to find the instructions that place 0000 in that memory
location and modify them to place 0005 in there instead, but this process is
somewhat involved and I don't want to throw too much at you at once.
Instead, I have an easier solution. Seeing as how the memory location will
always contain 0000, why don't we just change the ADD AX,0030 instruction to
ADD AX,0035? This should get the correct address placed on the stack for the
RETF instruction to bypass the nag screen...
Let's try it and see how it works. SINGLE STEP through the code until the
CS:IP is at the instruction ADD AX,0030. Now, ASSEMBLE the instruction to read
ADD AX,0035 and hit the RUN key. We are placed in the main program screen
without any stinkin' nag screen getting displayed!
Congratulations! you have just cracked your first program :) Try other methods
of patching the program besides the ones I went over. The next chapter will
deal with how to make the changes you've made permanent.
Ok, we cracked budget minder in the debugger and know it's going to work. Now
we need to make those changes permanent. The first thing we have to do before
we load the file into the disk editor is to create a search string.
So we are going to have to reload budget.exe into the debugger and trace back
to the location where we want to make the patch in order to get the hex bytes
of the instructions we want to search the disk file for.
Load budget.exe back into the debugger and trace back to the last four
instructions of the original call that revectored the return address. You
should be looking at this:
The group of numbers to the right of the addresses are the hexadecimal
representations of the mnemonic instructions. These are the bytes that we will
use for our search string. So write them down beginning from top left to
bottom right so you end up with this: 8B0405300050CB
This is the byte pattern that we will search for when we load the file into
the disk editor. We have a search string, but we also need to make a patch
string as well. In order to do this, we will have to assemble the new
instructions in memory, and then write down the changes we've made to the
code.
So ASSEMBLE ADD AX,35 and specify the address for the old ADD AX,0030
instruction. The new code should look like this:
Notice that we only re-assembled the second line of code and that is the only
difference between the new code and the original code. So what I want you to
do is to write down the changes under the old code it replaced so it looks
like this:
Now we are all set to load the file into the disk editor. We have a string to
search for and another one to replace it with. Load budget.exe into your disk
editor, select the search function, and input the search string.
NOTE: some disk editors default to an ASCII search so you may have to toggle
this to hex search instead. If your in the wrong mode, the disk editor will
not find the byte pattern your looking for.
Once the disk editor finds the byte pattern of the search string, just replace
the bytes of the old code with the bytes to the new code and save it to disk.
The program is now permanently cracked.
Sometimes however, the code you want to patch is generic enough that the
search string will pop up in several different locations throughout the file.
It's always a good idea to keep searching for the byte pattern after you've
found the first match. If the disk editor doesn't find any more matches your
all set.
If the string you are searching for is contained in more than one location and
you patch the wrong one the crack will not work, or you will end up with a
system crash when you run the program. In this case, you'll have to reload the
program back into the debugger and create a more unique search string by
including more instructions around the patch site in the search string.
One last thing, you cannot include instructions that reference dynamic memory
locations in the search string. These bytes are not contained in the disk
file. So keep this in mind when you are creating your search strings...
And the protection might not be included in the main executable either. If you
cannot find the search string in the main exe file, load the other program
files into the disk editor and search them as well, especially overlay files.
Fortunately for you, I've included a tool to help you do this.
In addtion to UNP, there are several other tools that you can utilize to make
your job easier. These tools were not designed with the cracker in mind, but
they can be adapted to serve our purposes rather than the ones which they were
written for.
UNP and other programs like it were written to remove the compression
envelopes from exectables so you would be able to scan those files with a
virus scanner among other things. If someone were to attach a virus to an exe
file and then compress it, the file for all intents and purposes would be
encrypted. Now when you downloaded that file and ran your virus scanner on it,
it might not find the virus.
But crackers found a different use for these types of programs. We use them to
remove the compression envelope so that we can find the byte strings we want
to search the files for. I'm sure most of the programmers who wrote these
programs never intended them for this purpose. There are some out there though
that were written by crackers with this exact purpose in mind.
Don't just rely on UNP as your only program to do this. No one program will be
able to remove evrything you come across. It's a good idea to start collecting
these types of programs so you have more than one alternative if you come
across a compressed file, and your favorite expander doesn't understand the
routines. Be aware though that some programs are actually encrypted and not
compressed. In this case the expander programs will prove useless.
There is another category of programs you can adapt to your use and they work
in conjunction with the file expanders. These types of programs will scan
entire directories of files and pop up a window that displays which files are
compressed and what they are compressed with. They won't remove the
compression routines from the files themselves, but will only inform you which
files are compressed and which are not. UNP also includes a command line
switch to do this...
Now instead of blindly running UNP on several different program files to see
if they are compressed or not, you can see at a glance if you even need to run
it at all. And if you do, you'll know exactly which files to run it on. This
is another time saving type of program and there are several out there, you
just have to look for them.
Another type of program that you will find useful will scan entire
disks/directories/subdirectories of files for specific hex or ascii byte
patterns contained within those files, and this is the purpose of the second
uuencoded cracking tool contained in this guide.
I usually will have it scan all the programs files and input the string REG.
This will show all files that contain the string unREGistered and REGistered.
If it returns a string that contains REGistered in a file other than the doc
files, I know the program can be made into the registered version. This is
just a quick check I do on programs that have certain features diabled to
determine if the program does contain the code for the registered version.
An added feature of this program is that after you've cracked a program and
have a byte string to search for, you can run this program in hex mode and
input your search string. Now it will search all of the programs files and
return the name of the file that contains your search string, then you can
just load that file into the disk editor and make the patch.
It will also let you know if your search string is contained in more than one
location within the file. Remember, if this is the case you'll have to reload
the program back into the debugger and create a larger search string by
including more instructions around the patch site.
The programs name is SS303 and it's very easy to use, just read the docs for
it...
These are the 'accessory' tools I use in cracking, there are several more out
there, I just don't have any use for them. And if you are dilligent, these are
all you'll really need as well.
As I've stated in the overview chapter, if you want to distribute your patches
you are going to have to write a patcher program. Simply releasing the patched
version of the program file is not desirable. For one thing it's illegal,
another consideration is size. Some files you patch will be 300K or more, and
this is quite a large crack to release. The patcher program included in this
guide is much much smaller, it will assemble to about 600 bytes or so,
depending on the size of your logo.
And what if you want the end user to be able to register the program in their
own name? A patched .exe or .ovr file will not allow this.
When you release a patch that you yourself wrote, you are not breaking any
laws. The program was written by you and is your intellectual property to do
with as you see fit, including making it available for public use. The person
breaking the law is the end user who will use it to illegally modify someone
elses intellectual property contrary to the licencing terms they agreed to
when they installed the program. Remember, it's not illegal to write and
distribute a crack, but it is illegal to apply a crack.
That's why all of the programs I've included in this guide are shareware
programs in the original archives as released by the authors and have not been
tampered with in any way. I'm not about to release a modified version of
someone elses copyrighted property. The only thing I am doing is supplying you
with the original archive and the information on how to modify it if you wish,
this is not illegal. If you decide to take the program and modify it that's
your problem, not mine...
This patcher routine is very simple, I wrote it about 5 years ago and it was
my very first patcher program. It is a brute force patcher in that it will not
do any error checking and blindly patch the program you specify with the byte
pattern you supply. This method has it's advantages and disavantages.
The disadvantage to this method is that seeing how the program does not
perform any error checking it will patch the file specified with the
replacement string even if it's not the correct version of the program. If the
filename is the same, the patch will be applied.
Let's say you crack a program called Ultimate Menu and the version number is
1.0, and the file you patch is called menu.exe. Now let's say a little while
later version 1.5 of the program comes out and someone who has your patch for
version 1.0 decides to run it on version 1.5 of the program.
This byte patcher will not check the new menu.exe for any changes before
making the patch, it will just patch the program in the location you specified
with the string you supplied even if the code you want to change is no longer
there. This could very well be the case if the programmer has significantly
re-written the code between versions, and what will end up happening is the
file will be corrupted and probably crash the system when it is run.
But this is also the advantage of my byte patcher. If the code to be replaced
is still in the same location in the new version, you'll not have to release a
new crack for each version of the program. Bear in mind that when I wrote this
program I was just starting out and didn't consider these possibilities. The
reason I included it in this guide was to give you an idea on how to write
your own patcher or to modify this one to suit your own purposes.
The patcher program that I use now is extremely complex and would just confuse
the hell out of you. Basically what I do is to make a backup of the original
file I am going to patch and then patch the original file. Then I run my
patcher program on the two files, it compares the differences between the
original file and the patched one and saves them to a data file. I then
assemble a patch using the data file.
What I end up with is a patch that will check the file you are running it on
to see if it is indeed the correct version before applying the patch. If it's
not, the patch won't be made. This method also allows me to make multiple
patches at different locations throughout the program. The byte patcher
included in this guide will only allow one string to be patched in one
location. But if you do a clean crack, that's all you'll usually need anyway.
Ok. here is the source code to the patcher program, I've commented as much as
I could throughout the code to make it more understandable. I also wrote it to
be generic enough so that you can re-use it over and over simply by plugging
in certain values and re-assembling it.
NOTE: the patch offsets are not the segment:offset adresses of the code as it
resides in memory, but the offset from the beginning of the disk file.
.model small
.code
ORG 100H
start: JMP begin
;******************************************************************************
; these are all the variables you set to crack a file,
; simply change the values and then assemble the program
;******************************************************************************
handle DW 0
;******************************************************************************
; this procedure opens the file to be cracked
;******************************************************************************
CMP AX,05H
JZ read_only
MOV AH,09H ;else display error message
MOV DX,offset error1 ;and exit
INT 21H
JMP exit
read_only: MOV AH,09H
MOV DX,offset error3
INT 21H
JMP exit
;******************************************************************************
; this procedure sets the file pointer to the patch location
;******************************************************************************
MOV AH,09H
MOV DX,offset error2
INT 21H ;else print error message and
JMP exit ;exit
ok: RET
move_it ENDP
;******************************************************************************
; this procedure writes the crack to the file and closes it
;******************************************************************************
;******************************************************************************
; the main program
;******************************************************************************
END START
CHAPTER 8 CONCLUSION
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Hopefully this guide has been useful in helping you understand the cracking
process. It is by no means an all inclusive guide, the main goal I had in mind
when I wrote it was to give beginners a push without confusing the hell out of
them.
It is not feasable to try and include all of the tricks of the trade that a
beginner might find useful into one single guide, nor would I want to do this.
For one thing, this guide would be ten times the size it is now, and even then
it would not be an encyclopedia of what to do for every situation. If your
serious enough about cracking, you will discover enough tricks and develop
your own methods as you progress. And you have to be creative! What works in
one situation may not work again in a similar one.
Instead, I tried to give you a general idea on how a programs code might
operate and what to look for. A successful cracker is not someone who
memorizes a specific set of actions to perform on a specific piece of code. A
successful cracker is someone who understands the flow of the code, and how to
adapt his methods to successfuly re-write the programs code to behave as he
wishes and not as the programmer intended it to. There are no set rules for
this, the very nature of the PC won't allow it.
If you have any questions about cracking or are stumped by something, drop me
a note at an575063@anon.penet.fi, I'll be glad to give any advice I can. Or if
you simply just wish to discuss cracking techniques or anything of that
nature.
NOTE: Do NOT mail me and ask me to crack programs for you! I'm not interested
in cracking for the masses. If you need something cracked, learn how to crack
it yourself. If you are unwilling to learn how, then register it.
Archea Hacking - Intro to GameHacking
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>
***What is GameHacking?***
--What is Hex?
Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hex: 0 1 2 3 4 5 6 7 8 9 A B C D E F
--What's a *TRAINER*?
--Why do those stupid people say they're 1337 4nD t41K 1iK3
tH1s?
There are some people who make idiots of themselves online,
dont be one of them. ;-)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>
Note from author:
This is just a little something I whipped together as an intro,
if you think there is something more i should include, email
me at archea47@archeahacking.com
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>
-=Archea47=-
Archea Hacking
www.archeahacking.com
== DO NOT EAT ==
FINDING AND USING STRINGS IN PROTECTED EXE's
Tools:
TSearch.
What I am trying to say is that you can not DISASSEMBLE these files using
WinDASM or any other disassembler because the program entry point and
import address tables are changed or corrupted. This is bad because you
can't look through the disassembled code for string references. These can
USUALLY help you locate important game functions.
Start:
I will use the game HelBreath for my example, because it is protected with
ASProtect. One thing to note is that search.dll from HelBreath contains anti-
TSearch code, so please rename TSearch.exe to anything but TSearch.exe,
such as TS.exe. Otherwise the game will exit for you.
So now you are playing the game, and lets say that you put your health
potion in the EXCHANGE window. If you try to use a health potion now, it
will tell you the following: "You can't use a potion while exchanging" in the
bottom left corner of the game screen.
Jump back into TSearch, select HelGame.exe as the process. And now
click on the Hex Editor Button.
You should come to the above. (I did the highlighting in a GFX editor, you will not see it). You can
see that the string is stored at address 4A5230 in memory. (A string consists of a bunch of chars,
terminated with a NULL (0x00)) It starts at 4A5230 and ends at 4A5258 with a 00.
In order to use a string a program must first PUSH it. So if we were able to disassemble the EXE (if
it was unpacked) with WinDasm you would see something similar to the following:
But we do not have the luxury of an unpacked exe. So we cannot just click on the string reference in
WinDasm and find out where that string is PUSHed in game code. We can do the next best thing
though.
The PUSH op code in hex is represented as 0x68. Then follows the address to push in REVERSE
BYTE ORDER. So 0x4A5230 becomes 0x30 0x52 0x4A 0x00. That last 0x00 is there because in
reality it is PUSH 0x004A5230, most disassemblers just do not show it. So our complete PUSH
004A5230 looks like this: 68 30 52 4A 00
Now go and click on the GO TO ADDRESS button in your HVIEW window, and type in 400000 to
get back to the beggining of the game's memory space. Now click on FIND, but this time select HEX
rather then ASCII and type in 68 30 52 4A 00.
You will find two results at 0x446481 and 0x4465E2, so at those two places in game code there is a
PUSH 004A5230.
Click on AUTOHACK. Enable Debugger. Then click on show Autohack window. Now select the
Autohack Window and click on EDIT -> DISASSEMBLE. When the window pops up type in
446481. Now click on the TAB called Disassembler.
You should now be at :446481. Now if you scroll up, by right clicking and hitting JUMP 50 LINES
BACKWARDS. You will see a conditional jump at 44647b. The code compares some value inside
of [ebp+0x4de74] with 1 at :446474. If the value is not 0, then it should jump to some other part of
the code. If the value is 0, then it should continue with the code, and it will push the "You can't use a
potion while exchanging" string onto the STACK and then it will give the user that error. So what we
need to do here, is change that JNZ to a JMP. So change the 75 to an EB.
Looks like its doing the same thing, checking if some value is not 0, and then react accordingly. So
again, change the JNZ to an JMP.
Conclusion:
Now you will be able to use health potions / mana potions while in trade mode. But more
importantly, you will be able to use string references to your advantage even without being able to
take apart the EXE with WinDasm.
^chaos^
December 11th, 2002
3. make your health decrease so you end up at the health decrementing routine.
4. Moving down the code you may notice something interesting after the health decrementing
routine, looks like cmp _____ , 0x0 and a jump after that.
5. force the jump after that to make sure it's the code to determine death.
6. If the condition of 5 is done look at the register for the area of the memory that's being
compared to 0, there's 3 possibilities: Your health pointer, a static identifier register, or
a dynamic identifier register.
7. Make the:
cmp ___, 0
jle deathroutine
portion of the code
to jump to a code cave, what you enter depends on the result of 6.
8a. function:
push register not used in routine
mov register just pushed, identifier value
cmp unused register, identifier
jne _routine1
pop register pushed at beginning
jmp back
_routine1:
pop register pushed at beginning
jmp deathroutine
-----------------------------------------------------------------
Special note: If you can use your health pointer in this routine, use it!!! as
Identifiers are different on different operating systems!
-----------------------------------------------------------------
Shouts to:
Devious: Stonerifik, Tsongkie, Omega, Synbios, Micral, Mini^Me, brzi, Invader, Sn0w
Web sites:
http://devious.tsongkie.com
http://voidofmind.com/eedok
http://www.ghu.as.ro
Feel free to tell me about corrections, or additions I should make to this tutorial.
If you find a copy of this tutorial on a site not listed above, feel free to contact
me about it, I'll take care of the rest.
Defeating DMA - Pointer Searching using Tsearch
by EEDOK
best read in 800x600 resolution, maximized
Mr_eedok@hotmail.com
-------------------------------------------------
--------------------------------------------------
Theory:
In many games that use DMA it is common to see commands like this: mov [esi+0x4],
means is copy eax to an area of memory 4 bytes from a pointer. The pointer it ref
normally stored somewhere in the memory of the program. So to be able to hack pro
this, we would just read the pointer add the offset manually, and we would then h
which we want to hack.
This is beneficial over nopping, or reversing asm commands because:
1. You don't have to modify any of the asm code.
2. You can make the address any value, anytime.
3. A segment of code does not have to be initialized.
4. Allows for one sided hacks where certain functions are shared between the CPU
-----------------------------------------------------
Getting started:
1. Open up Tsearch and the GTM, pause the GTM and find the address for money
2. In Tsearch hit Autohack>enable debugger, Go into the GTM and unpause it until
changes, then go back into Tsearch, and hit Autohack>Autohack Window.
3. In the Autohack Window it should have popped at 4011DB: sub [esi+0x4],eax, wha
is subtract the value of eax, from the area of memory 4 bytes away from the point
to know here is that the current address is +0x4 bytes from the pointer.
4. Open up your hexadecimal calculator and put in your current address(in hex), t
from it(also in hex).
5. Convert the result of the previous step to decimal format and search for it in
done correctly you should have the address 403138.
6. Hit the restart button so the location of the address of money changes, you sh
value of 403138 changes.
7. Read the value of 403138, convert the value to hexadecimal, then add 4 to it,
you the new location of money. This will work even if you restart the program.
8. Make a function in your trainer to read address 403138 and add 4 to it, then w
offset.
------------------------------------------------------------
Possible problem and solution:
I noticed this when I was playing GTA3 and wanted to hack my health, and the prob
when I did a search for pointers I ended up with more than 50 addresses.. So here
A)Had Artmoney to search for the new locations of my health value.
B)Had Tsearch open to find my pointer.
Well first I did the search for the pointer in Tsearch and immediately got 54 add
restarted GTA3. After restarting I used artmoney to refind my health address, and
it I searched for my pointer value again. This resulted in 14 results for a point
restarted the program again, and deleted the possible pointers that turned to 0,
they're definitely not a pointer to what I wanted. I repeated finding my health a
for a new pointer, which resulted in 6 addresses being found. At this time I noti
time I restarted the game, all 6 addresses were the same as each other, no matter
at what time I started the game, so I just used the one closest to the programs e
-----------------------------------------------------------------
Shouts to:
Web sites:
http://devious.tsongkie.com
http://voidofmind.com/eedok
http://www.ghu.as.ro
Feel free to tell me about corrections, or additions I should make to this tutori
If you find a copy of this tutorial on a site not listed above, feel free to cont
me about it, I'll take care of the rest.
*********************************************************************************
ÜÜÜÜÛÛÜÜÜÜÜÜ
Û²ÛÛÛÛÛÛÝ
ßÛ Û²ÛÛÛÛÛÛ Ûßß ß
Û Û²ÛÛÛÛÛÛ Û ÜÜÜÜÜÜ nmls^bafh
ÜÜÜÜÜÜ Û²ÛÛÛÛÛÛÞÜÜÛÛÛÛ²ÛÛ ÜÜÜÜÜÜ ÜÜÜÜÜÜ
ÜÜÜÛßßßßÛÜÜÛßß ÜÜ ßß ÛÛ²ÛÛÛÛÛßßßßßßßßß ÜÜÛßß ÜÜ ßßßÛÜÜÜ ÜÜÛßß ÜÜ ßßßÛÜÜÜ
ÜÜÜÛÛÜÜÜÜÜÜÛÛÛÛÛÛÛÜÜÞßßÛÛÛÛ Ûßßßßßßßß ÜÛßß ÜÜÛÛÛÛÛÛÛÜÜÜ ßß ÜÜÜÛÛÛÛÛÛÛÜÜÜ ßßß
° ÝÛÛÛÛÛÛÛÛÝßßÛÛÛÛ²ÛÛÛÛÛÞßÛÛÛ ÜÜÜÛßßßßßÛÜ ÜÜÛÛÛßßßÛÛÛÛÛÛ²ÛÛÛÞßÛÛßÝßÛÛÛÛÛÛ²ÛÛÜ
° Û²ÛÛÛÛÛÛ ° ÝÛÛÛÛÛÛ²ÛÛÛÞÛÛÛÞÛ ÜÜÜÛÛÛÜÜÜÜÞß²ÛÝ° ÝÝÛÛÛÛÛÛÛ²ÛÛÞÛÝ ° ßÛÛÛÛÛÛ²ÛÛ °
±° Û²ÛÛÛÛÛÛ °°ÝÛÛÛÛÛÛÛ²ÛÛÞÛÛÛ ± ÝÛÛÛÛÛÛ²ÛÛÛÞ²ÛÞ±° ÜÛÛÛÛÛÛÛÛÛßÞÛ °°±ÝÛÛÛÛÛÛÛÛÝ °
±± Û²²ÛÛÛÛÛ ±° ÛÛÛÛÛÛÛ²ÛÛÞÛÛÛ ±² ÛÛÛÛÛÛÛ²ÛÛÝßÛÛÜÜÜÜÜÜÜÜÞßÞ ÝÜÛÛ °±² ÜÜÜÜÜÜÜ ±°
²± ÛÛ²ÛÛÛÛÛÞ²± ÛÛÛÛÛÛÛ²ÛÛÞÛÛÛÞ²²ÞÛÛÛÛÛÛÛ²ÛÛÝÞÝßßßßßÛÛÛÛÛÛÛÛÜÞßÛÞ²² ÞÛÛÛÛÛÛÛÛÜ ±
²²ÞÛÛ²ÛÛÛÛÛÞ²²ÞÛÛÛÛÛÛÛ²ÛÛÞÛÛÛÞ²ÞÜÛÛÛÛÛ²ÛÛÛÛÞ²ÜÞ²² ÞÞÛÛÛÛÛÛ²ÛÛÞ²Þ ²ÞÜÛÛÛÛÛÛ²ÛÛ ²
²²ÞÛÛÛÛÛÛÛÛÞ² ÞÛÛÛÛÛ²ÛÛÛÛÞ²ÛÛÜÜÛÛÛÛÛÛÛÛßßßÞÜÛÛÛÜÜÜÛÛÛÛÛÛÛ²ÛÛß ÛÛÜÞÜÛÛÛÛÛÛ²ÛÛß ²
² ßßßßßÛÛßß Ü ßßßßßßßßßß ÜÜÜÜÜÜÜÜ ßßß ÜÜ ßßßßßßßÛÛÛÛÛßßßßßß Ü ßßßÛÛÛÛÛÛÛßßß ÜÜÜ
ßßßßßÛÜÜÜÜÛß ßßßßßßßßßßßßß ßßßßßßß ßßßßßßÛÜÜÜÜÜÜÜÛßßßßßßßßÛÜÜÜÜÜÜÜÜÜÛßßß
*********************************************************************************
Disclaimer:
-----------
If you request Nuke for People,when they release a Trainer with the same Options
you have,just delete this Tutorial,and kill yourself.It was in Case not written
for kiddie Morons wich make 50% of the todays Internet.
About me..
----------
I am doing Trainers / Reverse Engineering of code since 1986...
C-64,Amiga,SuperNES,GameBoy Advanced and Pc now..
---------------------------------------------------------------------------------
The Search:
-----------
W32Dasm Problems:
-----------------
* Note: Nowadays,for Shareware mangled Section Flags are 90% of 100 done
through Pe-Crypters or Packers like for example Asprotect..
In that Case you will have to find some Depacker for that
Crypter/Packer used on that Program..
Or just dump and rebuild...Can you?..
Alt-Tab Protections:
--------------------
Some Things i found through the Time are:
c) poor Game coding...the Game isnt able to restore the Screen after Task-Switc
At this time,you have only the Chance to use SoftIce-Plugins.
Alt-Tab-Protection-Examples:
----------------------------
---------------------------------------------------------------------------------
GameHack-Tool-Protections:
--------------------------
- lets say you find an Adress at d93200 wich offers the Lifes you have
in an Game.Set a Breakpoint on Region with SoftIce
- use W32Dasm to disassemble the Game (if protected read Section above)
lets say you have 300 Minutes of Time in the Game,just look for an
Assembler Instruction that mov´s the Hexadezimal-Value to an Memory
Adress ( 300 dezimal = 012c hexadezimal)...write down MemoryAdress
were Value is stored,or Adress of Instruction that mov´s the Value.
In most cases you should find only some Instructions/Adresses and
you can check them via Patching in the Code.Adresses outside the
Memory can be checked via an Beta-Ingame-Key Tester.
-----------------------------------------------------------------------
Avoiding the Failure to take DMA as an direct Memory Adress:
------------------------------------------------------------
- DMA Memory is alloctacted by the Game..Its mostly used when the Game has an
Save-Option,or either is big in Size..These Adresses change..That means,
every time you start your Game, it normally has changed Adresses....
If you just access the Dma-Adresses as direct ones,your Trainer prolly
would not work..
Thats it..
No Mythos...Just a bit Experience..
It was an easy Example..there are also Games wich store an Adress over another Ad
you would have to read out both Adress,before you can modify your one..
-------------------------------------------
No valueable DMA-Pointer found,what now?
-------------------------------------------
Lets say,you found an Memory Adress,for Example 1ab3d00.
It holds Money you have in the Game...: $1.000.000
You put a Memory-Breakpoint on it,bpm 1ab3d00.
Buy something,so hopefully SoftIce will pop up,since the Adress will get changed.
SoftIce pops up at: 4432a3: mov [ecx+14],edx
[Ecx+14] = Adress 1ab3d00 , and we have not found a valid Pointer to the DMA-
Adress to read it out in our Trainermenu.
Edx holds the new Value to be inserted ($1.000.000 - what we bought...)
So,we do an Maximum Money Option for it...
How?..We just change the code before that mov [ecx+14],edx.
I guess a Subtract will be done,before the mov [ecx+14],edx.
Change the Subtract to: mov edx,$5f5e100 = maximum Money [$5f5e100 = 100.000.000]
Make sure the Instructions have the same Length,otherwise Nop out the obfuscating
That means now...
Everytime the Game would normally Subtract our Money,
We fill up the Money Adress with maximum Value [$100.000.000]
---------------------------------------------------------------------------------
-------------------------------------------------
Examples of Different-Routines,stolen from Games:
-------------------------------------------------
Ok,the Track will prolly not be enabled now...We need to kill the jmp at adress
00419241 too...I did it by writing EB04 to adress 00419241,this will insert a Jum
419247...but,you can also insert 6 Nops (6 x 90) to clear the instruction..
Main Idea is the same,writing my jump is 2 Bytes,noping is 6 Bytes...Choose
yourself...!
Example from: From Dusk till Dawn *GERMAN* - [Energy] / Code Fake
-----------------------------------------------------------------
:005119CB A804 test al, 04
:005119CD 7409 je 005119D8
:005119CF 5F pop edi
:005119D0 B801000000 mov eax, 00000001
:005119D5 5E pop esi
:005119D6 59 pop ecx
:005119D7 C3 ret
The Test al, 04 at Adress 5119CB checks for any Sprite Collision.
This can be an Enemy or You. We see the sub ecx,edx at Adress 5119de
but if we erase it, we AND our Enemies will also be invincible.
So,CHECK your Register when you enter the Sub-Routine at Adress
5119d8. If an Collision was detected Register ESI sets the Flag to
compare between us,and Enemy.We land at, an Collision that would
decrease our Energy would be Register ESI = 0.
What to do now?
0177:004B11CF 90 NOP
0177:004B11D0 55 PUSH EBP
0177:004B11D1 8BEC MOV EBP,ESP
0177:004B11D3 8B510C MOV EDX,[ECX+0C] <-- Adress Mo
0177:004B11D6 8B4508 MOV EAX,[EBP+08] <-- Adress In
0177:004B11D9 03D0 ADD EDX,EAX
eax can here now be an -,or + Value. That means our add instruction
can add a Value,but if the Value eax is negative it can also sub a Value.
---------------------------------------------------------------------------------
Hints on Values:
----------------
Options search:
---------------
Unlock:
-----------
Gamestart: 0 -------->
1
not equal
Cars/Tracks:
-------------
Gamestart: 0 -------->
1
not equal
Datafields /1/ne
Invincible:
-------------
Gamestart: 0 --------> Flicker Timer
greater than
less than
equal
General Unlocking:
--------------------
Manipulate the Game, for example racing Games to always be first.
Play the Game,until a new Car/Track is unlocked and examine the
Changes.
Invincibility:
**************
- first 0
After a Collision some Timer gets initialized,wich is counted down afterwards.
Level-Skip:
***********
- most Games offer an defined Ammount of Items to get/destroy
(Example: 40 Items to destroy/Zero the Byte,and Level is skipped)
Timers:
*******
- can be stored as 2 Bytes (0801)
Lives:
******
- can be stored -1 (Display says 5 / 4 in Memory)
- can be stored as obfuscating Values 3/3 (use MemChange-Trainertool)
Weapons (Selector):
*******************
- there is mostly an Range of compares to the Adress
0001,0002,0003.....use W32Dasm to find multiple Adress compares
Cheat-Mode enable:
******************
- use W32Dasm to check for CheatMode-Text. If found, a CheatMode
is often made through a Password typed in.Patch the Password-Routine
to always enable/disable Cheat.Use a Memory-Compare-Tool to find the Byte wich
is set to enable/disable CheatMode.
Difficult Values:
-----------------
- Hard to find Timers / Level-Skip-Value Adresses can best be found
with an GameHack-Tool that has an ´Memchange´-Option like ´MTC´
***********************************************************************
Error-Fixing on Trainer-Programming:
-------------------------------------
This is an OpenProcess-Routine wich enables you to read and write to the
specified Game.The Flags are w9x/me + w2k tested.
***********************************************************************
LESSON : 1.
Apart from the beginner stuff im about to introduce ive never seen any of the
information in my tutorials written anywhere else this may be due to people eithe
not wanting to give out advanced information that has taken them a long time to s
OR.. they just cant be bothered to write an extensive essay about this subject..
either way it doesnt matter because u are about to learn ALL!!
LESSON START
------------
WHAT IS DMA?
------------
Im sure u have all heard about DMA by now.. understanding what this is and how
to defeat it are the first steps of a mighty ladder. Ill try and stick to telling
u how DMA affects us (THE GAME HACKER) and not stray into too much technical deta
When a game uses DMA the memory locations it uses are allocated dynamically
whereby the game grabs the next available slot of memory and gives it to
whoever asked for it..
Generally there are so many variations going on while ur computer is running its
unlikely that the memory locations u get on one occasion will be the same next ti
reload the game.. this is why ur trainers only work just after u have collected t
addresses and NOT once u have reloaded.. Once the game is reloaded it will grab a
NEW set of memory locations for itself thus making ur OLD set of memory locations
To defeat DMA and create a trainer that will work 100% of the time u need to come
the realms of the NEWBIE and into the NEW LAND :)
NEW TOOL!
---------
This is where we start adding NEW tools to our cheaters arsenal.. the first tool
to add is called SOFTICE its a software debugger that enables u to manipulate the
code (on the fly) which means while the game is still running..
I wont go into installing softice in this tutorial.. there are plenty of other tu
that do that for u.. so from here on ill assume u already have it installed.
SOFTICE SETUP
-------------
When u press CTRL-D to pop softice u should see the following windows..
REGISTER WINDOW - this window is always at the very top of the softice window
(WR [return]) and displays the contents of all the registers..
DUMP WINDOW - generally situated close to the top of the softice window
(WD [return]) contains a split screen display.. one side is ascii the
other is hex.
CODE WINDOW - this is the main window.. sits just under the DUMP WINDOW
(WC [return]) contains the code of whatever process maybe running when
u pop softice.. the code is represented in ASSEMBLY LANGUAGE
instrutions..
The comments in the brackets are what u need to type to turn the different window
also u need to type CODE ON.. this will bring up the OPCODES which are a set of n
displayed to the left of each ASM instruction and to the right of every memory lo
in the CODE WINDOW..
(if u dont understand any ASM then i suggest u go away now and read up on a basic
DEFEATING DMA
-------------
THEORY
------
At the end of this section i will show u how DMA is defeated IN PRACTICE.. ill us
game ive recently trained showing u code listings so that u can apply the theory
example.. so dont worry if im not going into too much detail about setting breakp
etc.. it will all be covered in the PRACTICAL section....
As we cannot change the memory locations of a DMA game we need to get right to th
and by that i mean the GAME CODE.. once u have found ur memory locations in a NON
game u generally make ur trainer poke numbers into the locations u have found and
makes an affective trainer.. we know that this doesnt work for DMA so what we hav
is STOP the game code from decreasing our locations.. we do this by WATCHING what
happends to our memory locations while the game is running.. thankfully we dont n
sit there and do the WATCHING ourselves.. our new friend SOFTICE does it all for
example...
lets say i have 5 lives and the location of these lives is 490000.
We can all think logically so we know that when we die in the game the GAME CODE
decrease the location 490000 by 1.. We need to stop this from happening..
The way we do this is by setting something called a BREAKPOINT.. there are a few
of breakpoint available to us but the one we need at the moment is a MEMORY BREAK
this breakpoint will WATCH a memory location for us.. if anything should affect o
memory location then softice will then pop at the exact piece of code that affect
this means that when we die inside the game and the GAME CODE decreases our lives
will pop and we will find ourselves looking at the GAME CODE that decreases our l
GOOD STUFF EH? :)
GAME CODE
---------
There is something VERY advantagious about GAME CODE.. IT NEVER CHANGES LOCATION.
right.. on every single game EVEN DMA GAMES.. if we find the GAME CODE that decre
lives at 453000 then u can bet ur life that the next time u load the game the EXA
code is at 453000 and this is the key to defeating DMA.. instead of poking values
DATA memory locations.. we are going to poke values into CODE memory locations..
they are the same thing fundamentally they just behave in different ways..
CODE KILLING
------------
This is just a random code snippet taken from softice.. it has nothing to do with
of any kind i just wanted to show u what was what when it came to the CODE WINDOW
as this is the place u will be spending most of ur time...
now i will show u a section of code taken from a message board.. this is from a R
Ok, the assembly instructions are the only valid thing in the above code the rest
either been filled with 0000 for opcodes or xxxxxxxxx for the addresses.. these a
important at this time anyway....
The above code probably means absolutly nothing to u and dont worry because it sh
NOW!!! let me add a story and some comments to the above code...
We are playing a game... we have got 20 LIVES.. we find the location of these LIV
at 445566 we place a breakpoint on this location inside softice.. so that when so
affects our LIVES softice will pop and we can see the code that is affecting them
BANG!!!!
SOFTICE POPS!!!!!
I hope the picture has become more clear to u now.. the lives are read from our l
then decreased by 1 and then placed back into our location.. im sure the clever o
reading this will already have figured out what we have to do.. but for the slowe
ill continue :)
Ok.. this is the NASTY instruction that is killing our poor little character... a
u can see ive put in the REAL OPCODE for this instruction its 48..
This instruction decreases our lives by 1 each time.. what we need to do is GET R
if we do then there is nothing to kill our little character and he can live forev
Thankfully we can do this within softice.. u need to replace the DEC EAX with som
else.. the all time fave for replacing stuff that isnt needed is an equally small
instruction called NOP which is NO-OPERATION.. thats correct.. when this instruct
executed absolutely nothing is done.. so KEEP this little NOP by ur side at all t
so if we replace
with..
When u are replacing instructions inside a program u have to make sure that if an
instruction has 5 opcodes then u MUST replace it with 5 opcodes..
example...
if i wanted to get rid of the above call.. i couldnt just put 1 NOP.. because NOP
i need to FILL E8-6C-04-EB-10 so instead of just NOP(90) i would need 5 NOPS 90-9
otherwise the program will most definately crash on u... so once u have replaced
it should look like this...
before...
after....
0120:00008121 90 NOP
0120:00008123 90 NOP
0120:00008125 90 NOP
0120:00008127 90 NOP
0120:00008129 90 NOP
A DMA trainer is no differnt in any way to a NORMAL trainer.. all u are doing is
values into the CODE section instead of the DATA section..
eaxmple...
replace..
with..
016F:0000412345 90 NOP <------ NO OPERATION
Same Code but this time ive added the addresses and the correct OPCODES.. if i wa
make a trainer that worked 100% on this DMA game.. all i need to do is poke 90 (N
into location 412345.. this would turn the DEC EAX to a NOP and the game would ha
infinite lives.. no need to worry about DMA locations anymore.. 412345 WILL ALWA
be the place to poke 90 and get infinite lives.. GAME CODE DOES NOT CHANGE LOCATI
As i said at the beginning i havent gone into much detail about how to set breakp
this will all be taken care of in the next part of the tutorial..
As i dont like to do things by half i will now show u a practical approach to def
DMA with code listings and softice commands.. this is just a backup of what is wr
above.. after this u should be able to understand the entire tutorial.. that is i
already :)...
These code listings and commands all come from the game SERIOUS SAM 2.. u dont ne
go and find this game but if u have it then it will make it a lot easier for u to
a go with what we have learnt today...
On this game ive decided to show u BULLETS instead of lives because the life tota
SS2 is worked out slightly differently (something i will be tackling in another t
1. I did a normal EXACT VALUE search to find the address for the bullets ..
i got the address 6AFEF28.
2. I POPPED softice with CTRL-D so that i could set a breakpoint on the bullets l
3. Inside softice i typed BPM 6AFEF28 W (the W means WRITE so when ever something
to our address softice will pop) then i pressed RETURN to set the breakpoint..
5. I scrolled the code window up a bit and this is the code listing...
As u can see even though its not the same code as before its VERY similar.. thats
thing about ASM there are only a couple of instructions that decrease the value o
address so they are easy to spot most of the time.. this time they use SUB.. whic
SUBTRACT.. ok.. to defeat this we need to get rid of that SUB instruction...
6. I typed A 60570C6D then pressed return.. this lets me manipulate the code at l
60570C6D..
7. I typed NOP [return] NOP [return] the returns mean i pressed return :) just to
any confusion.. I used 2 nops as u can see because remember we need to get rid
bytes of OPCODES 29-08 so we need to replace them with 2 bytes of our own OPCO
90-90..
8. I then pressed return a 3rd time without entering anything and softice drops o
assemble mode..
9. Now we are all done and ready to test it.. CTRL-D got me back into the game..
have infinite bullets.. and the dma is defeated..
dont forget.. game code doesnt change location.. to make a 100% working bullet tr
for this game all u need to do is poke 90,90 into location 60570C6D...
WELL!! we have come to the end of this tutorial.. i hope u managed to follow it a
obtain all the knowledge u need to defeat DMA.. keep a look out for other tutoria
in this series..
LESSON : 2 (part 1)
Before we do actually start i warn u that if u dont have certain prior knowledge
before attempting this tutorial then u wont get much out of it..
I suggest u most certainly read my previous tutorial which covers DMA in full det
U also need to know at least the basics of the ASM language...
SOFTICE SETUP
*************
When u press CTRL-D to pop softice u should see the following windows..
REGISTER WINDOW - this window is always at the very top of the softice window
(WR [return]) and displays the contents of all the registers..
DUMP WINDOW - generally situated close to the top of the softice window
(WD [return]) contains a split screen display.. one side is ascii the
other is hex.
CODE WINDOW - this is the main window.. sits just under the DUMP WINDOW
(WC [return]) contains the code of whatever process maybe running when
u pop softice.. the code is represented in ASSEMBLY LANGUAGE
instrutions..
The comments in the brackets are what u need to type to turn the different window
also u need to type CODE ON.. this will bring up the OPCODES which are a set of n
displayed to the left of each ASM instruction and to the right of every memory lo
in the CODE WINDOW..
LESSON START
************
ok.. To achieve the final goal of defeating DMA with CODE INJECTION u will need t
a few new concepts that u may not have come across before.. ive listed the concep
we will be covering below...
Once u have learnt the first 3 concepts u will most certainly be ready to tackle
4th and final one... good luck :))
Code injection is a method used by advanced game hackers to achieve certain tasks
that cannot be achieved with NORMAL game training methods.. The main aim of code
injection is to create a pathway FROM the main GAME loop TO ur own code.. u then
jmp back to the main game loop after ur code has been executed.. what ur code doe
is only limited by ur knowledge of the game and of course ur knowledge of asm :))
Code injection is so flexible u can do pretty much anything u like.. breaking fre
of the restrictions of the normal NOP hacks....
Example...
This is a code snippet i used in my last tutorial.. its just an example so it doe
matter...
if u destroy any valuable instructions while making ur gateway.. u must make sure
re-create them inside the OUR CODE section.. or u will most likely crash the game
Dont forget this is only the theory.. a fully detailed "HOW TO" will follow in th
section lower down..
OFFSET THEORY
*************
We all know that DMA causes the variables of a game to change location every time
either start a new game or reboot completely.. Even though this is true.. DMA var
actually stay in the same place relevant to each other.. WHAT DO I MEAN?? i hear
Now we have restarted the variables have changed location.. BUT!! notice the actu
659345h-659123h = 222h. Even though the variables are allocated different memory
they always stay the same distance apart.. this is the KEY to the whole process..
The reason they stay the same distance apart is because each variable isnt actual
seperate memory locations.. a large chunk of memory containing most if not all ga
would be allocated the memory at run time...
Using offsets we can make a detailed map of every variable we need.. all we would
to do is pick 1 variable as the MASTER and find this address every time.. from th
address u will instantly know where the other variables are located in memory...
Another example....
we can now change that map into REAL addresses.. like this..
So now u can see by making a Variable map using 1 MASTER variable we can find all
other variables with offsets :)) its pretty cool stuff eh? :)))
ok.. its pretty vital that u understand offsets BEFORE u go on.. if u dont unders
it then go back and RE-RE-RE READ....
Once u understand at least the basics of code injecting such as i explained ealie
u should'nt have too much trouble understanding the DMA to STATIC principles..
We find a place in the game code that contains a POINTER to a variable we are usi
i.e LIVES, HEALTH, BULLETS etc..
Once we have found this POINTER we need to make sure that it is a SPECIFIC POINTE
which means it ONLY!! points to 1 location.. if the POINTER is GENERAL it will cy
through many places and manipulate many memory locations this is useless to us...
EBX will contain a DMA base address.. the 208 is an offset added to EBX to form t
POINTER which points to our variable (LIVES)..
Lets say that we know EBX+208 = LIVES.. we now need to find out if this is a SPEC
(points to only 1 address) and not a GENERAL pointer (points and manipulates many
we do this by placing a breakpoint on the MOV EAX,[EBX+00000208] instruction then
F5 to get out of softice.. every time softice pops up again look at the contents
if the number inside EBX doesnt change then we know that we have a SPECIFIC point
number inside EBX changes, even once, then this pointer is no good to us.. to get
if the address in EBX is SPECIFIC u should check the value in EBX at least 10 or
make sure its not changing...
ok, once we have found our SPECIFIC pointer.. we need to store away the DMA base
lies inside EBX (NOTE!! EBX doesnt always contain the DMA base value.. it could b
REGISTER.. u need to look at the pointer and see what REGISTER IS USED.. ie..
just keep all that in mind.. pointers can take on many forms but i think the abov
than likely the type of thing u will encounter in most games...
ok.. so we need to store our DMA base value away into static memory.. we do this
pathway to our own code (code injection).. our code will then place the DMA base
inside EBX into a static address so that our trainer can read that address every
its own pointer by adding offsets to it.. and then poking values into that pointe
Once the above code has been executed u can now read the value from 9000100 and e
when the game changes its memory locations ur code will put the correct value bac
inside 9000100.. so all u need to do is read that value.. add 208 to it and u
have the exact location of LIVES.. remember?? lives = EBX+208...
thats pretty much the whole deal.. apart from the code that reads the value from
ill show u that in the PRACTICAL section below... dont worry if all that was a bi
take in.. keep flipping back to this section to re-read.. with the fully explaine
section u should be able to put them both together and understand it all..
The game ive chosen for this tutorial is called SPACE TRIPPER..(thanks keyboardju
u can dload it from here.. http://www.pompom.org.uk/STpage1.htm
lets start...
lose a life..
softice POPS!!!!
In softice..
Now edit the memory location in the top left hand corner of the DUMP window and u
update properly.. showing u that we have found the REAL LIVES memory location...
Luckily enuff we have found 2 vital things with just 1 breakpoint.. we have found
memory address.. we have also found a potential POINTER to use in our CODE INJECT
if this POINTER is SPECIFIC or GENERAL.. once again we take to softice..
So, now we have found a valid place to inject and save our POINTER into a static
address.. all we need to do now is find a nice place to put OUR CODE!! u can do t
a few ways..
1. Look up and down the code close to where u are injecting and see if there is a
cluster of NOPs.. (this is empty code).. also a large cluster of 0's signals a
OUR CODE location aswell..
3. This is the method i use.. people tell me that they have encountered problems
this method but ive created about 20 to 30 trainers using it and its never giv
me a NON working trainer.. so until it does ill continue to use it..
:map32 spacetripper
Owner Obj Name Obj# Address Size Type
SPACETRIPP.text 0001 017F:00401000 0004BE10 CODE RO
SPACETRIPP.data 0002 0187:0044D000 00006718 IDATA RW
SPACETRIPP.bss 0003 0187:00454000 0035CDB4 UDATA RW
SPACETRIPP.idata 0004 0187:007B1000 000014F0 IDATA RW
SPACETRIPP.rsrc 0005 0187:007B3000 0000095C IDATA RO SHARED
The .data section starts at 44d000 but we need to use the end of the data section
usually a lot of buffered space on the end of the data section so we can happily
messing with any REAL data used by the game) so what we do is look at the next se
which is .bss the start of the .bss section is just after the very end of the .da
Just to be on the safe side we need to scroll the dump window up a bit.. so that
on the end of the data section.. u will notice that when we scroll upwards the te
of the dump window will change.. from
SPACETRIPPER! .bss
to
SPACETRIPPER! .data+<offset>
type EB (return)
then use the PAGE UP / PAGE DOWN keys to move the window up and down :))
ive decided that 453f00 is a good place for use to place our code.. so the first
to do is write that memory address down.. so that u dont forget it...
now we have the address of OUR CODE.. we need to go back to the pointer at (41a73
our gateway.. it should still be inside ur code window but if it isnt then so do
***NOTE!!***
The next steps are all done one after the other .. u cannot break in the middle o
or attempt to come out of softice or u will crash the game....
ORIGINAL CODE...
0041A736 8B8308020000 MOV EAX,[EBX+00000208]
0041A73C D983CC000000 FLD REAL4 PTR [EBX+000000CC]
0041A742 D8B3C8000000 FDIV REAL4 PTR [EBX+000000C8]
0041A748 A3A46C7800 MOV [00786CA4],EAX
to
Now we need to store the POINTER into a static memory address.. all of the addres
around u are static.. so u can pick any one u like.. nothing too close to the cod
section .. i have chosen 453f30....
type jmp 41a73c (return) <-- 41a73c is just after our NOP instruction in the g
ok.. after alllll that... ur code locations should look like this....
GATEWAY SECTION...
0041A736 E9C5970300 JMP 00453F00
0041A73B 90 NOP
0041A73C D983CC000000 FLD REAL4 PTR [EBX+000000CC]
0041A742 D8B3C8000000 FDIV REAL4 PTR [EBX+000000C8]
0041A748 A3A46C7800 MOV [00786CA4],EAX
if ur code does not mirror that of mine then u have done something wrong.. u need
go back and redo it...
NOW!! if u HAVE the same code as me.. which u should have.. u can now press F5 to
exit softice.. and the game should be running fine...
we can now do something pretty cool to demostrate that this is ACTUALLY working..
(if it says something like INVALID ADDRESS) u need to exit softice and then re-en
again...)
if all goes to plan in the top left hand corner of the dump window u will see the
address.. u can modify this and ur lives will change..
start a new game.. (dont reload the game) just start a new game...
if u look at the dump window.. u will notice that the LIVES location has changed.
ITS DMA !! :)))
but.. our code is still doing its job... its still storing away the dma value at
address so all u need to do to find the REAL lives value again.. is type that com
and now in the top left hand corner of the dump window u will see the REAL LIVES
we have defeated DMA .. the DMA base address will ALWAYS!!! be stored at 453f30 a
to do is add 208 to it.. and u get the REAL LIVES address...
FINAL WORDS
***********
im sure the clever ones out there have already worked out how to use this in ur t
for those who are a little slower on the uptake ill explain...
once ur code is injected into the game.. u can then use READPROCESSMEMORY to gath
base address from 453f30.. then u just poke values into DMA_BASE_ADDRESS+208..
its as simple as that...
Once u have done all that u obviously dont wanna go through all those steps every
need to inject ur code.. so u must create a trainer to inject the code for u.. it
simple..infact its the same process as ALL trainers.. except u will be dealing wi
bytes than usual....
For the code injection to work every time.. this is what u would need to poke in
At address 41a736..
At address 5f3f00
and thats it.. u will be able to read the DMA base address from 5f3f30..
basically all u do is poke all the OPCODES of the instructions we just wrote back
correct memory locations...
WORD OF WARNING!! always poke OUR CODE section OPCODES first... then the GATEWAY
FEW!!! another tutorial finished.. man!! its a lot of work..
*********************************************************************************
*********************************************************************************
I would just like to greet some people that support and inspire me....
First of all, if you dont know what code injection is i will explain
it to you. Just two weeks ago i did not know anything about code
injection... Just recently, 2 days ago, i did my first code injection
hack... So technically im a newbie at this, but i hope this will help
me explain this to you better.
Lets say you are playing your game, you found your health address..
ALLRIGHT, you poke it and you have infinite health. Now you pass the
level, and it doesnt work anymore!! WHAT THE HELL?? This is DMA, it
causes your memory addresses to change, so they are different all the
time... This is annoying, you can stop it from decreasing your health
by finding the operation that decreases it , and then by NOPING it,
but what if you want to do more?? What if you want to poke a value
into your changing memory addres? What if you want it to increase
instead of decreasing? Or what if just want some crazy stuff to happen
when u get shot? This can all be done by injecting your own code. All
you basically need is a paper, Softice, and the will to learn. I know
this can be hard, i had problems all the time, but you gotta keep
trying!! When you finnally learn you will be unstopable!
BPM 047C45678 W
THen i cycle weapon so i have gun, softice pops up. Here is what it says:
** I ONLY WROTE THE FIRST ADDRES DOWN BECAUSE THATS ALL I NEED, BUT I
NEED THE NEXT 3 COMMANDS... LIKE MOV EAX,[EDI+14] ....
ADDRES
005DBEO4 MOV [EDI],AX <- this puts a value into my ammo ([edi])
MOV EAX,[EDI+14] <- softice pops here
MOV ECX,[EAX+50]
So write down the first address on a paper on the left side, on the total
right side write down the command it does.... SO i would write this on paper:
ADDRES
005DBEO4 MOV [EDI],AX
MOV EAX,[EDI+14]
MOV ECX,[EAX+50]
Ok now we have the address that checks to see how much ammo we got. The
game at puts our ammo address's 047C45678 *VALUE into [EDI], [edi] is the
value of EDI... SO if EDI=047C45678, [EDI] would equal our amount of ammo...
BTW one bullet in GTA2=10... Ok still with me? Now since we have the line of
code(s) that we want to change we have to look for a place to put our code,
it just cant come out of nowhere. So this is what you do... You type
MAP32 <gamename>
You can find out what to write in <gamename> because it says it in the bottom
right corner of softice... For me it says GTA2 so i would write : MAP32 GTA2
**Some games have longer names like unrealtournament, and in softice itll only
show the first 8 letters i believe, so just write the name of the .exe you are
running. So if your playing a game and you are running the file game.exe,
you would type MAP32 GAME.
Ok, we have that. But what good does that do? See where it says .rsrc? Its at
0070500 right? Above rsrc 9/10 times there is no code. It is safe to put your
code there... So in softice type:
U 00705000
This will show you 00705000 in the main window. Now press ctrl+up or shift+up
to scroll up... **TYPE: CODE ON
Now you can scroll up, see all those 0000 above the address 00705000? ITs safe
to put your code here. Pick a address that you wanna put your code, pick
something easy to write down like 00704900, once your picked one, write down
the address. Ok we have ourselves a place to put our code. Now lets put our
own code in :)
type :
A <yournewcodelocation>
So if you picked 00704900 you would type A 00704900, it ask you to write a
instruction. Now remember those instruction we wrote down before, the
MOV [EDI],AX
MOV EAX,[EDI+14]
MOV ECX,[EAX+50]
we will place that first instruction into our first line of code. So when it
asks your to write the instruction write : MOV [EDI],AX
now it asks you to write the instruction for next address, it asks to write
it for 00704906, so write the second instruction and press enter. then put
in the third. Ok we put those instructions into our code. Just to make sure
the game is running or it didnt freeze because u made a mistake, pop out of
softice, and check if the game is still runing. If it is, pop back into
softice and type U 005DBEO4. Remember 005dbe04? THats the one addy we wrote
that we were gonna replace. Now we can see 005DBE04 in the main window
(code window). Now lets make the first line of code, the former MOV [EDI],AX
into a JMP so it jumps to our code... So type
A 005dbe04 <enter>
type : JMP 00704900 <enter>
As soon as you did that look what happens to our code:
BEFORE AFTER
We only change one line of code, but everything else changed... WHAT THE HELL??
If we poped out of softice now into our game, i bet it would crash... SO lets
not make it crash.
*** IT MIGHT NOT LOOK LIKE THIS BUT IM JUST GIVING U AN EXAMPLE
BEFORE AFTER
LOOK AT 005DBE1C AFTER WE NOP!! THE COMMAND IS THE SAME AS IT USE TO BE BEFORE
WE EVEN ADDED OUR JMP!! SUCCES!! OK NOW LOOK BELOW 005dbe1c, the addy right
after it is the addy we will return to from OUR code. We cant just have the
game go to our code and nothing, it needs to return! IN OUR CODE THE LAST
LINE OF CODE WE PUT WAS MOV ECX,[EAX+50]. Now the next line of code after
that needs to be something that was in the original code, so the game thinks
its running normally, or else it could crash... So write down the next address
after 005dbe1c, it might be 005dbe1F...
Now type in
U 00704900 <enter> <-- so we can see our code in the main window
now the last line of code we put in was at lets say 0070491C, and the next
addy after that is 0070491F, we need to change taht 0070491f so it jumps
back to the original game code. So type
A 0070491f <enter>
INSTRUCTION: JMP 005dbe1F <enter>
<esc>
Now it should jump back to the original game code. Now this new code we put
in doesnt do anything special, we just put it in to see if the game would
still run if we put our new code in. This is the best way to check if u did
it right. By putting in the original code into the new code and jumping back
to original. Now pop out of softice, if your in the game playing normally
CONGRATULATIONS! You did code injection, if you were succesfull you probably
already know what you wanna change and how you can do it.. If the game got
frozen, or quit you did something wrong on the way. I know how upsetting it
can be, i was yelling at my computer just 1 week ago. Keep trying, look
carefully what your doing, make sure u dont mispell an address or something.
KEEP TRYING!!! YOU DONT KNOW HOW WORTH IT IT REALLY IS, ONCE YOU CAN DO THIS
YOUR UNSTOPPABLE!!!! I HACKED SO MANY GAMES THAT I COULDNT HAVE HACKED USING
THE NORMAL GAMEHACKING TECHNIQUES... ITS GREAT, YOU WILL BE UNSTOPPABLE, SKY
IS THE LIMIT WITH CODE INJECTION.
**** IF YOU HAVE ANY QUESTIONS ABOUT THIS TUTORIAL, OR JUST WANNA CHAT, MY
MSN IS STRYKER1080@HOTMAIL.COM. ID BE GLAD TO HELP YOU OUT.... *************
ALL THIS POSSIBLE BECAUSE OF SHEEP, THANKS FOR STICKING WITH ME AND TEACHING
ME.... SHEEP RULES!
- stryker
Simple In-game Trainer Menus
----------------------------
Author: Orr
NOTE!
This tutorial is _Definetly_ NOT for newbies. Best read with NOTEPAD.
Introduction
------------
Say you made a trainer with 10 or more options. The game you trained uses routine
protect against Alt+Tabbing outside the game. Say that the gamer using your train
forgot what are the trainers options, or he forgot what keys to use. He can do tw
things now. Quit the game, or try to press all the keys and see how it affects hi
Is there a solution for this kind of situation? Well, There is!
The method I will suggest in this tutorial was not invented by me. As far as I kn
it was already done in the old DOS days. That method is called Ingame Trainer Men
The purpose, is to show the trainer option menu, inside the game, when the user h
a hotkey.
What I will show in the tutorial, is how to make a trainer with one hotkey, that
pressed, will pop up a Message Box from inside my favorite target game: (pam pam
"The House of the Dead 2".
The tools I will be using are SoftICE, IDA, HIEW, and Visual C++ (not a must).
Theory
------
Basically the idea I will suggest works like that:
In case you don't know how to perform in-mem code injections, I suggest you go re
alittle about it in [SHEEP]'s tutorial, or keep reading on, as I will explain som
fundumentals of injections.
If we find a place that is getting executed ALL the time (like, in a huge loop :)
could locate a good place to patch there, and inject our code to am empty space.
question is, how do we find a place, a loop that runs all the time?
Basically, what I did was, whiile playing that game alittle, I poped SoftICE for
times, until I saw I am in the correct process (look in the bottom-right corner o
for the CLSID), in my case it is HOD2. I poped SoftICE in times that I wasn't doi
so I would see what code is executed even when I am IDLE.
After poping up in a place that looked OK, I began tracing alot. Some cases I did
manually, and some cases I did it using the T command (T 100 will trace 100 instr
After a while, I saw that some loop is being executed alot of times, so I wanted
it out. I disassembled the file with IDA, and got to that location. I am terribly
to tell you I really forgot what location it was... What I did though, was seeing
function that location was, and then seeing who calls it... for example:
This function is called from the location sub_4A41C0. So I went there. and there
I found a cool place that executed many API's. Anyway, I chose this location:
Why? Because GetMessage is a Windows API that gets executed all the time. I check
for my suspicion by simply setting a breakpoint at that location, and I saw that
I couldn't even play for one sec, because SoftICE kept popping after I pressed F1
OK, So we found a place to overwrite with our jump... now we actually need a plac
to jump to!
To summarize:
You can do 2 things in order to find a place that is getting executed all the tim
- Find a place that loops alot manually, by simply stopping the game in an IDLE
point, and trace from there. Tracing can be done manually, or it can be done
using the T command in SoftICE.
- Breakpoint on known API's that are likely to get executed all the time:
GetMessage, GetTickCount.
Windows EXE's are based on the PE (Portable Executable) file format. The PE forma
supports sectioning of the file. Every section of the file has a different job.
There are Code/Data/Resource/Import/Export/etc sections. Most sections are differ
in size, so they all must be aligned. Because of that nice feature compilers leav
us, there are often alot of 'dead' NULL bytes, that are simply wasted just to ali
the section size. There is a difference between those code caves, because these a
mapped to memory, while there may be cases you will see empty places, but they wo
be mapped into memory, thus you cannot jump to them.
1. You simply scroll through the entire EXE looking for those alignments. Once yo
see empty spaces, you check if they are indeed code caves (later on how to check)
2. In a hex editor, look for a binary string that contains nothing but 00's. It w
you to many odd places, but eventually to a cave.
3. You do the "proffesional" way. In IDA (or any other PE editor), we get some in
about the sections. We go to the beginning of the code (generally on top), and we
You see that the Virtual Address is 1000, and that the Virtual Size is C1940?
You add those up together, and you get C2940. You go to that OFFSET in the file,
will see a nice and clean code cave. :)
In order to check if this is indeed a CODE cave, and not just a dead cave, in HIE
notice if there is a dot (.) before the address of not. The address will be 4C294
see this: .004C2940, then this is code... if you see just 004C2940 then it won't
Trust me on this one, I spent a lot of hours figuring why it didn't work on some
I was working on a while ago.
What to Inject?
---------------
OK, So we know where to jump from, and where to jump to. But all of this is usele
we inject something! In this tutorial, I will show how to inject a simple Message
push Style
push Caption
push Text
push WindowHandle
call MessageBoxA
But remember, that we have overwritten an API... so we need to execute it again,
to the location we came from (actually we jump to the instruction after the API c
call GetMessage
jmp 4A596E
After that, we need to actually inject the text for MessageBox caption and text.
location 4C2970 for the caption, and 4C2980 for the actual text. The style will b
So we have this code now:
push 0
push 4C2970
push 4C2980
push 0
call MessageBoxA
call GetMessage
jmp 4A596E
But this code won't work... because we push 0 as the window handle. If we use 0 a
handle, then the MessageBox will be shown OUTSIDE the game, and sometimes cause i
crash. So how do we solve this? We need to find the window handle, and push it. B
the Window Handle is saved in a variable after the window was created. So we go b
IDA, and we track down the CreateWindowExA function. We see where it is reference
and we find this location:
So we see that the hWnd is saved in a global variable which is located inside the
memory address 7DC8AC. So now, we have to get that value, and push it, instead of
push 0
push 4C2970
push 4C2980
mov eax, [7DC8AC]
push eax
call MessageBoxA
call GetMessage
jmp 4A596E
Make a copy of hod2.exe, and name if hod2_.exe or whatever. We will be doing all
changes to this one. Open up HIEW, select HOD2_.exe, and then press F4 and go to
mode. Press F5, and type ".4A5968" (Without quotes ofcourse). Now you are in this
Press F3 (to be in EDIT mode), and then press F2 (to be in ASSEMBLE mode), and ty
jmp 4C2949 [Enter]
nop [Enter]
[Escape]
Press F9 to update.
now go to the cave (.4C2949), and assemble the code block we wanted to add (see a
For API's you cannot assemble, so you will have to leave 6 nop's for each API. ho
add an API? Simply. Do you remember that I told you that it can be executed from
in the program, and also with the same opcodes all the time? Simply go to a locat
that calls GetMessage (4A5968), and a location that calls MessageBoxA (49E148), a
the opcodes (FF 15 xx xx xx xx).
After that go to add the strings (F3 and then TAB), and simply write them. Rememb
In order to separate strings there has to be a 00 between them:
The Trainer
-----------
#include <windows.h>
#include "resource.h"
hInst = hInstance;
DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), 0, (DLGPROC)main);
return(0);
}
// My WRITE engine
HWND hwnd;
HANDLE phandle;
DWORD pid,bytesw;
quit:
return(0);
}
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
// This is the actual thing!
{
if (GetKeyPress(VK_F4)) { // If F4 was pressed
Write(wname, 0x4C2949, opt2, OPT2); // Write The injection
Write(wname, 0x4A5968, opt1, OPT1); // Patch the call
Sleep(2000); // Wait a little (2 seconds)
Write(wname, 0x4A5968, opt1_off, OPT1); // Change back the call
}
}
LRESULT CALLBACK main(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
case WM_COMMAND:
if (wParam == ID_QUIT) ExitProcess(0x31337);
break;
default : return(FALSE);
}
return(TRUE);
}
Explanation:
What I did, was writing all the injected bytes into memory. First I wrote the inj
then I Patched the place to jump from, then waited for 2 seconds, and then patche
back again. I didn't bother to Zero out all the injection, because it won't get e
anyway.
Ending
------
Phew! That was a lot to write! I have been working 2 days on this menu + another
actually WRITING this. Looking back, it wasn't very tough, I just had to reboot a
due to blue screens and other sorts of page faults and weird exceptions.
What you have to keep in mind while doing an ingame menu, is:
There can be many problems and diffuculties that can occur. For example, what hap
if you don't find a global variable that contains the Window Handle? For that cas
can simply use FindWindow(0,"Window Name"). But what happens if you don't have Fi
imported in the EXE? You can import it like this:
Finally, my little advice, BE CREATIVE. Think of more ideas, like adding DIALOG B
many more options, or perhaps even injecting the ENTIRE trainer to the game, so y
even have to use an external program besides a memory patcher.
Attached to this package is the trainer source, and a nice pic hehe :)
Thanks:
[SHEEP]: Encouragement, and for telling me the Window Handle thing
Duelist: For telling me where to find that Window Handle thing :)
Greets:
iCARUS, Have_No_Mercy, calligula, jmp_fce4, Keyboard Junky, ddh, MacDeath, Dang,
and all the other dudes in #gamehacking which I forgot to add. Please bitch
me if I forgot :)
/\
____/__\____
\ / \ /
\/ \/
/\ /\
/__\____/__\
\ /
\/
OpenGL Hack Methods
by Phar Lap (JeSelected@Hotmail.com)
This How-To is for experienced programmers who need to know how they can implemen
glGetFloatv(GL_CURRENT_COLOR, &curcol)
We now have the color as float-values with single precision which equals 32 bits
curcolor[0] = red portion
curcolor[1] = green portion
curcolor[2] = blue portion
glDisable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
I used this combination in my OpenGL Hack because I think this looks best. You ca
GL_ZERO
GL_ONE
GL_SRC_COLOR
GL_ONE_MINUS_SRC_COLOR
GL_SRC_ALPHA
GL_ONE_MINUS_SRC_ALPHA
GL_DST_ALPHA
GL_ONE_MINUS_DST_ALPHA
GL_DST_COLOR
GL_ONE_MINUS_DST_COLOR
GL_SRC_ALPHA_SATURATE
Finally, we can choose how transparent we want the walls (also called alpha-value
Basically, we have transparent walls now. But we won't have much fun with it as l
You have to hook glClear and check if the given parameter is GL_DEPTH_BUFFER_BIT.
That's it!
To see what the different OpenGL-modes mean, take a look > here <
?Feature #2: White walls
That will remove any texture from every wall, making it bright white.
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glLineWidth(1.0)
Now we can set the lines to a nice green color like that:
After that, we're finished and can call the original glBegin.
Last thing to do: If the mode is not GL_POLYGON :
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
This will turn off wireframe for everything which is not drawn in GL_POLYGON, lik
Remember that this wireframe mode also requires the buffer being cleared between
The feature called "Lambert" will prevent models from being shaded, so you will s
This one is actually very easy and I can't understand why some people use the HL-
glGetFloatv(GL_CURRENT_COLOR, &curcol)
Now we can easily determine if HL wants to draw smoke by checking for a grey colo
Now in glVertex3fv, we check for bSmoke to be true and if so, we return to the ca
Et voil?
?Feature #6: Flashbang removal
In glBegin, we check mode for GL_QUADS. If so, we fetch the current color:
glGetFloatv(GL_CURRENT_COLOR, &curcol)
Now we look for pure white, which means red = 1.0, blue = 1.0 and green = 1.0 ...
In order to communicate between glBegin and glVertex2f, we have to use a flag (bo
The next step is to retrieve the current screen dimensions since we need them to
glGetFloatv(GL_VIEWPORT, &coords)
Last thing to do in glBegin is: in case the quad is not white we have to set bFla
Now in our hooked glVertex2f, we firstly look for bFlash being 1 ... if not, we c
This feature is only useful when used together with transparent walls or wirefram
So the first step is to hook those functions. Next step is to define another bool
In glVertex3fv, just check for bSky to be true and if so, return to the caller wi
Please remember that "smoke removal" also uses glVertex3f so make sure that those
glDisable(GL_DEPTH_TEST)
... which is telling OpenGL to skip the testing whether you can see an object bas
glEnable(GL_DEPTH_TEST)
So far so good ... now in glEnable check for bDrawn to be FALSE (0) and if not, j
glPushMatrix()
glLoadIdentity()
glDisable(GL_TEXTURE_2D)
glEnable(GL_TEXTURE_2D)
glPopMatrix()
This ensures that you don't touch the current matrix with all the information of
The code of my crosshair used since v1.7 of the OpenGL Hack is the following:
glGetIntegerv(GL_VIEWPORT, &iDim)
glColor4f(1.0f, 0.0f, 1.0f, 1.0f)
glLineWidth(3.0f)
glBegin(GL_LINES)
?glVertex2i(iDim[2]/2, (iDim[3]/2)-12)
?glVertex2i(iDim[2]/2, (iDim[3]/2)-5)
?glVertex2i(iDim[2]/2, (iDim[3]/2)+5)
?glVertex2i(iDim[2]/2, (iDim[3]/2)+12)
?glVertex2i((iDim[2]/2)-12, iDim[3]/2)
?glVertex2i((iDim[2]/2)-5, iDim[3]/2)
?glVertex2i((iDim[2]/2)+5, iDim[3]/2)
?glVertex2i((iDim[2]/2)+12, iDim[3]/2)
glEnd()
glBegin(GL_POINTS)
?glVertex2i((iDim[2]/2)-3, iDim[3]/2)
?glVertex2i((iDim[2]/2)+3, iDim[3]/2)
?glVertex2i(iDim[2]/2, (iDim[3]/2)-3)
?glVertex2i(iDim[2]/2, (iDim[3]/2)+3)
glEnd()
What lambert does to models does fullbright to the walls: ignores shadows so you
Shadows are drawn with black textures which are blended over the walls and which
glDisable(GL_TEXTURE_2D)
Mission accomplished!
The Ancient Art Of Training Or What The Mega
Trainer Gods Stuff Is All About Not Assigned
04 June
1999 by A Nameless Stranger
slightly edited
Courtesy of Reverser's page of reverse engineering
by reverser+
I feel some sadness and disappointment in this contribution (see the
drink/imposing bit :-)
Yet it is indeed a valid contribution. The Author wrote to me the
following:
lately my students requested a little excursion to the
mystified world of trainers.
This little essay is the result of the lesson I held
about this topic.
My students most happily refer to your site and
teachings.
So it might be fair to give your students the
possibility to refer to my work.
Yours sincerely,
fra_00xx
980604 a nameless stranger
anamstra and the author of this essay is right: the strainer world is a very
1100 interesting reversing world, and I invite all readers to have a (deep) look
NA at it. There are sites on the web that have perfectioned the softice
PC techniques we use everyday ONLY with the purpose of modifying games.
Make a search for +softice +doom (or quake, or whatever) and you'll see
what I mean.
Yeah, of course "pure" crackers and reversers are not alone: there are
all kinds of reversers out there in the great great Web. Some of these
'revkinds' are quite alien for us, some are very near, some touch 'our
interests' only marginally, but many others have (quite) something to
teach us, like the demomakers, for instance, and also the trainers'
experts like "A nameless stranger", here and now.
"This is the MINIMUM trainer (i.e. a hotkey and memory patching)! Just a
starting point."
Indeed! Awaiting much MORE! :-)
Outside they call them gods
Magicians with mighty rods
Inside it's just little work
Can be done by every jerk.
Rating ( )Beginner (x)Intermediate ( )Advanced ( )Expert
All in all this is something every beginner should be able to understand and reproduce. It's rated
intermediate 'cause it's assumed that the reader knows basic data types, a bit assembly, a bit C and
basic reversing techniques. A little knowledge of programming with Win32 API should be helpful.
Introduction
This essay covers the concept of trainers in Windows9x environments in FAQ style.
If the reader needs a ready made trainer 'skeleton' this is definitely the wrong essay,
but the author covers all topics the reader needs to know for coding his/her own trainer.
This way the reader will have the possibility to be proud of his/her own work and he/she won't have
to lie about the credits.
Tools required
SoftIce
GameHack
C compiler
The reader doesn't need any special drink and/or music. The author won't impose his/her preferences
on the reader.
Target's URL/FTP
Trainer targets are usually games which can be found at any game store or any major distro site.
The reader might have already one or two games at home. The author mostly used Expendable in the
examples.
Program History
A very brief history of trainers:
Once upon a time cracker groups didn't only crack. They coded their own intros, demos, trainers...
As long as there were such cracker groups trainers were coded.
Later the cracker groups stopped coding and specialized in changing jne/je to nop.
A few individuals conquered the free space and tried to build something like a trainer scene.
Today the warez groups try to revive the glory of the old days by producing intros, demos and trainers
again.
Essay
What's a trainer?
A trainer is a program that allows to manipulate certain values of games such as life points,
experience points, ammo, credits, tiberium, gold, armor, .... at run time. In short words - A trainer lets
the player cheat.
'Freezing' is the effect a player experiences when a trainer stops values from changing.
This can be accomplished by modifying the game's code in a way that the value won't be accessed
anymore or by updating the value in short intervals. Another way to 'freeze' values is to change the
code which accesses the value.
Example:
If the code that drains your life points looks like this:
'sub [esi+1C6FCF6],ax' change it to 'mov [esi+1C6FCF6],64'
and you'll always have 100 LP.
In most cases a trainer reacts upon defined key strokes (hotkeys). If the right key is pressed the
trainer's 'engine' attemps to patch the memory of the target's process at the address where the desired
value/code is located.
This is no secret. A lot of material can be found on this topic in various books, magazines, journals...
The main idea is to utilize the Win32 API function WriteProcessMemory().
The Win32 API reference sates:
BOOL WriteProcessMemory(
HANDLE hProcess, // handle to process whose memory is written
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // pointer to buffer to write data from
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
If you're unsure about the target's window name use any of those nice little utilities which list the
windows' names.
Remark:
If you're using OpenProcess() you should use CloseHandle() too else you will produce a nice little
memory leak. Closing a process' handle does NOT cause closing of the associated process!
For a detailed description of the above functions consult the 'Appendix - Win32 functions used'.
To find the address where you have to patch the target's memory is the trickiest part of it all.
But there's help. The easiest way to find the right address is to use GameHack 2.0
(www.gamehack.com).
This little program allows the user to scan a traget's memory for specified values and shows the
associated addresses. When the desired value changes the user lets GameHack scan the found
addresses for the new value. This way GameHack sorts out the wrong addresses until there are only a
few left.
Get it. Take a look at it. For composing trainers it's a very valuable tool. Of course you can write
such a memory scanner on your own and add some advanced pattern scan methods. It's not very
difficult if you've coded your own trainer you're already half the way down. Creating the UI is the
worst of it all.
Anyway, use GameHack to find the address where your target stores the desired value.
Sounds easy, doesn't it? Well, it is, but you may experience some problems relying only on
GameHack's addresses. The problem is that you can't take for granted that the desired values are
always stored at the same addresses.
Example:
You can use addresses found with GameHack to train e.g. Heroes of Might & Magic 3 which works
fine in a single scenario or in the first campain but later, in the next campain or in multi player mode
the memory layout changes i.e. the addresses of the values change and become useless.
You see it's necessary to check if your addresses work all the time not only the first five minutes.
If the address(es) change it's a good idea not to patch the value but the code that accesses the value.
The address of the code can be easily located by putting a memory breakpoint on the value's address.
(i.e. 'bpm address w' or 'bpr addr1 addr2 w' in SoftIce).
Example:
You've found with GameHack that your target stores life points in a WORD at address 0x1C6FCF6.
Start your target.
Set a breakpoint 'bpmw 1C6FCF6 w' in softice.
Resume your target.
When your life points change SoftIce pops up at a location like this:
This line of code changes the value of your life points. To stop the program killing you simply nop it
out by writing 7 times 90 (nop) to address 4657FA. If you want to disable your trainer restore the
original bytes at address 4657FA.
Of course there some other ways to locate the right address - scanning for specifc patterns or even
dead listing - but I think you got the idea, didn't you?
BYTE bNewData[]={0x90,0x90,0x90,0x90,0x90,0x90,0x90};
Yes, that's really all. Simply create an array holding the bytes you want to write. Pay attention to the
Intel byte order!
Count your bytes or let the function sizeof() count them for you:
BYTE bNewData[]={0x90,0x90,0x90,0x90,0x90,0x90,0x90};
DWORD dwNewDataSize = sizeof(bNewData);
HANDLE hWndTarget = FindWindow( NULL, "Expendable");
DWORD dwProcessId;
GetWindowThreadProcessId(hWndTarget, &dwProcessId);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
WriteProcessMemory(hProcess, 0x4657FA, &bNewData, dwNewDataSize, NULL);
CloseHandle(hProcess);
Yes, it's that simple. You've already trained Expendable's life points.
See 'Appendix - a live record' for a brief description of the whole process.
Using the Win32 API you can realize hotkeys in various ways.
The GetAsyncKeyState function determines whether a key is up or down at the time the function is
called, and whether the key was pressed after a previous call to GetAsyncKeyState.
SHORT GetAsyncKeyState(
int vKey // virtual-key code
);
Parameters:
If the function succeeds, the return value specifies whether the key was pressed since the last call to
GetAsyncKeyState, and whether the key is currently up or down....
To use this function for hotkeys the only thing you have to do is polling. Polling means to let it run in a
loop.
If you call it in a loop like:
while(1)
{
if (GetAsyncKeyState(VK_F12)) // if F12 is down or was down since the las
{
train(); // call the trainer engine
}
};
it will consume too much if not all of the cpu time. So it is important to time the 'loop' carefully.
A timed loop is nothing else than a timer callback function. You can realize it like this:
Parameters:
Generally it's a good idea to check the game's key layout before choosing your hotkey i.e. don't use F5
if the game uses this for e.g. quicksave.
Remark:
The timer callback for the hotkeys consumes cpu time everytime it's called. You shouldn't set the
timer interval to very short periods (<75 ms) to avoid slow downs of the running target. Usually a
~1000 ms interval is an acceptable choice.
See the 'Appendix - Win32 functions used' for detailed information.
That's all?
Yes! This is all you need to know for coding trainers. You know how find the right addresses, how to
patch memory and how to realize hotkeys. You may need to work out the address finding part a bit but
with GameHack on your side you'll soon discover how easy things really are.
All what's left to do is assemble what you've learned to a working Win32 program and ready is your
trainer. You've mastered your way to the olympus of the 'trainer gods'.
Remark:
The author tried to make this as short and simple as possible. This is the MINIMUM trainer (i.e. a
hotkey and memory patching)! Just a starting point. If you think your trainer won't work this way
'cause you need an in built memory scanner or the use of the debug interface or whatever, good, very
good: CODE IT YOURSELF!
This is just an EXAMPLE for illustration purposes. If you think that some code locations should be
patched another way, good, do so. You should of course add some sanity checking i.e. error handling
to your trainer code!
- Used 'bpmw 04A0134 w' in Softice to track down the code that modifies
the time value.
- Used 'bpmw 1C6FCF6 w' in Softice to track down the code that modifies
the life points.
- Used bpmw .... to track down the grenade count down code.
void TrainTime()
{
WriteProcessMemory(hProcess, 41C63E, &bTimeDataNew, 1, NULL); // patch the me
WriteProcessMemory
BOOL WriteProcessMemory(
HANDLE hProcess, // handle to process whose memory is written to
LPVOID lpBaseAddress, // address to start writing to
LPVOID lpBuffer, // pointer to buffer to write data to
DWORD nSize, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
Parameters
hProcess
lpBaseAddress
lpBuffer
Points to the buffer that supplies data to be written into the address space of t
specified process.
nSize
Specifies the requested number of bytes to write into the specified process.
lpNumberOfBytesWritten
Points to the actual number of bytes transferred into the specified process.
This parameter is optional. If lpNumberOfBytesWritten is NULL, the parameter is i
Return Values
Remarks
WriteProcessMemory copies the data from the specified buffer in the current proce
address range of the specified process. Any process that has a handle with PROCES
and PROCESS_VM_OPERATION access to the process to be written to can call the func
The process whose address space is being written to is typically, but not necessa
debugged. The entire area to be written to must be accessible. If it is not, the
fails as noted previously.
FindWindow
The FindWindow function retrieves the handle to the top-level window whose class
window name match the specified strings. This function does not search child wind
HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);
Parameters
lpClassName
lpWindowName
Points to a null-terminated string that specifies the window name (the window's t
If this parameter is NULL, all window names match.
Return Values
If the function succeeds, the return value is the handle to the window that has t
specified class name and window name. If the function fails, the return value is
To get extended error information, call GetLastError.
GetWindowThreadProcessId
DWORD GetWindowThreadProcessId(
HWND hWnd, // handle of window
LPDWORD lpdwProcessId // address of variable for process identifier
);
Parameters
hWnd
lpdwProcessId
Points to a 32-bit value that receives the process identifier. If this parameter
GetWindowThreadProcessId copies the identifier of the process to the 32-bit value
it does not.
Return Values
The return value is the identifier of the thread that created the window.
OpenProcess
HANDLE OpenProcess(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle, // handle inheritance flag
DWORD dwProcessId // process identifier
);
Parameters
dwDesiredAccess
Specifies the access to the process object. For operating systems that support se
checking, this access is checked against any security descriptor for the target p
Any combination of the following access flags can be specified in addition to the
STANDARD_RIGHTS_REQUIRED access flags:
Access Description
PROCESS_ALL_ACCESS Specifies all possible access flags for the process ob
PROCESS_CREATE_PROCESS Used internally.
PROCESS_CREATE_THREAD Enables using the process handle in the CreateRemoteTh
to create a thread in the process.
PROCESS_DUP_HANDLE Enables using the process handle as either the source
in the DuplicateHandle function to duplicate a handle.
PROCESS_QUERY_INFORMATION Enables using the process handle in the GetExitCodePro
GetPriorityClass functions to read information from the process
object.
PROCESS_SET_INFORMATION Enables using the process handle in the SetPriorityCla
to set the priority class of the process.
PROCESS_TERMINATE Enables using the process handle in the TerminateProce
to terminate the process.
PROCESS_VM_OPERATION Enables using the process handle in the VirtualProtect
WriteProcessMemory functions to modify the virtual memory of the
process.
PROCESS_VM_READ Enables using the process handle in the ReadProcessMem
to read from the virtual memory of the process.
PROCESS_VM_WRITE Enables using the process handle in the WriteProcessMe
to write to the virtual memory of the process.
SYNCHRONIZEWindows NT only: Enables using the process handle in any of the
wait functions to wait for the process to terminate.
bInheritHandle
Specifies whether the returned handle can be inherited by a new process created b
current process. If TRUE, the handle is inheritable.
dwProcessId
Return Values
If the function succeeds, the return value is an open handle of the specified pro
If the function fails, the return value is NULL. To get extended error informatio
call GetLastError.
Remarks
The handle returned by the OpenProcess function can be used in any function that
handle to a process, such as the wait functions, provided the appropriate access
requested. When you are finished with the handle, be sure to close it using the C
function.
GetAsyncKeystate
SHORT GetAsyncKeyState(
int vKey // virtual-key code
);
Parameters
vKey
Windows NT: You can use left- and right-distinguishing constants to specify certa
See the Remarks section for further information.
Windows 95: Windows 95 does not support the left- and right-distinguishing consta
on Windows NT.
Return Values
If the function succeeds, the return value specifies whether the key was pressed
last call to GetAsyncKeyState, and whether the key is currently up or down.
If the most significant bit is set, the key is down, and if the least significant
the key was pressed after the previous call to GetAsyncKeyState. The return value
a window in another thread or process currently has the keyboard focus.
Windows 95: Windows 95 does not support the left- and right-distinguishing consta
If you call GetAsyncKeyState on the Windows 95 platform with these constants, the
is zero.
Remarks
You can use the virtual-key code constants VK_SHIFT, VK_CONTROL, and VK_MENU as v
vKey parameter. This gives the state of the SHIFT, CTRL, or ALT keys without dist
between left and right.
SetTimer
The SetTimer function creates a timer with the specified time-out value.
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
Parameters
hWnd
Identifies the window to be associated with the timer. This window must be owned
calling thread. If this parameter is NULL, no window is associated with the timer
nIDEvent parameter is ignored.
nIDEvent
Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this paramet
uElapse
lpTimerFunc
Points to the function to be notified when the time-out value elapses. For more i
about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application qu
The hwnd member of the message's MSG structure contains the value of the hWnd par
Return Values
If the function succeeds, the return value is an integer identifying the new time
An application can pass this value, or the string identifier, if it exists, to th
function to destroy the timer. If the function fails to create a timer, the retur
is zero.
Remarks
The wParam parameter of the WM_TIMER message contains the value of the nIDEvent p
TimerProc
Parameters
hwnd
uMsg
idEvent
dwTime
Specifies the number of milliseconds that have elapsed since Windows was started.
This is the value returned by the GetTickCount function.
Return Values
Remarks
/*
* Virtual Keys, Standard Set
*/
VK_LBUTTON 0x01
VK_RBUTTON 0x02
VK_CANCEL 0x03
VK_MBUTTON 0x04 /* NOT contiguous with L & RBUTTON */
VK_BACK 0x08
VK_TAB 0x09
VK_CLEAR 0x0C
VK_RETURN 0x0D
VK_SHIFT 0x10
VK_CONTROL 0x11
VK_MENU 0x12
VK_PAUSE 0x13
VK_CAPITAL 0x14
VK_ESCAPE 0x1B
VK_SPACE 0x20
VK_PRIOR 0x21
VK_NEXT 0x22
VK_END 0x23
VK_HOME 0x24
VK_LEFT 0x25
VK_UP 0x26
VK_RIGHT 0x27
VK_DOWN 0x28
VK_SELECT 0x29
VK_PRINT 0x2A
VK_EXECUTE 0x2B
VK_SNAPSHOT 0x2C
VK_INSERT 0x2D
VK_DELETE 0x2E
VK_HELP 0x2F
/* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
/* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
VK_LWIN 0x5B
VK_RWIN 0x5C
VK_APPS 0x5D
VK_NUMPAD0 0x60
VK_NUMPAD1 0x61
VK_NUMPAD2 0x62
VK_NUMPAD3 0x63
VK_NUMPAD4 0x64
VK_NUMPAD5 0x65
VK_NUMPAD6 0x66
VK_NUMPAD7 0x67
VK_NUMPAD8 0x68
VK_NUMPAD9 0x69
VK_MULTIPLY 0x6A
VK_ADD 0x6B
VK_SEPARATOR 0x6C
VK_SUBTRACT 0x6D
VK_DECIMAL 0x6E
VK_DIVIDE 0x6F
VK_F1 0x70
VK_F2 0x71
VK_F3 0x72
VK_F4 0x73
VK_F5 0x74
VK_F6 0x75
VK_F7 0x76
VK_F8 0x77
VK_F9 0x78
VK_F10 0x79
VK_F11 0x7A
VK_F12 0x7B
VK_F13 0x7C
VK_F14 0x7D
VK_F15 0x7E
VK_F16 0x7F
VK_F17 0x80
VK_F18 0x81
VK_F19 0x82
VK_F20 0x83
VK_F21 0x84
VK_F22 0x85
VK_F23 0x86
VK_F24 0x87
VK_NUMLOCK 0x90
VK_SCROLL 0x91
/*
* VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
* Used only as parameters to GetAsyncKeyState() and GetKeyState().
* No other API or message will distinguish left and right keys in this way.
*/
VK_LSHIFT 0xA0
VK_RSHIFT 0xA1
VK_LCONTROL 0xA2
VK_RCONTROL 0xA3
VK_LMENU 0xA4
VK_RMENU 0xA5
VK_ATTN 0xF6
VK_CRSEL 0xF7
VK_EXSEL 0xF8
VK_EREOF 0xF9
VK_PLAY 0xFA
VK_ZOOM 0xFB
VK_NONAME 0xFC
VK_PA1 0xFD
VK_OEM_CLEAR 0xFE
Ob Duh,
does not apply here!
You are deep inside reverser's page of reverse engineering, choose your way out:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
REVERSING, FUNCTIONS ADDITION,MODIFICATION OF THE EXISTING CODE
A TYPICAL TARGET FROM MICRO$FOT:NOTEPAD.EXE
PART 1
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
INTRODUCTION
************
TOOLS NEEDED/USED
*****************
MISSION
*******
As first tutorial of this kind we will add only a menu item in notepad's Help
inform us about who made to patch.
Every win95 executable file consists of 2 parts : the PE header and the sectio
header contains all kind of information for the os about how to threat this file.
are grouped by their functionality. For example there is one section for the prog
one for its data, one with its resources, one with the table of imported function
First an environment is created for the program where it gets its own virtual a
Then win95 has to decide where in this virtual address-space it should place the
information is available in the PE header. The PE header contains the desired ima
of the program, this is the address the program wants to be loaded at.
Then windows takes all the sections and places them in memory beginning at the
(default imagebase is 400000h). Where exactly it places the sections is also stat
header. Every section has its own so called RVA (Relative Virtual Address). This
just an offset relative to the imagebase.
Once the sections are in memory, windows has to know how to threat those sectio
know which section contains a stucture with the resources, which one has the scru
import table etc.That is also stated in the PE header with RVA's to the beginning
various so called data directories.
Then finally windows has to jump to the programs code. This entrypoint is in th
the entrypoint RVA.
The above words about the PE header is not meant as a replacement for the PE do
mentioned at the beginning of this tutorial. I would recommend u to study the PE
It will give you a much better understanding of win95 programs.
LESSON START
************
So we have the menu ID in esi and then a check to see if esi>20h (20h = 32 dec) s
value greater then 32 will be processed by a variable jump. So we'll better give
value > 32 so that we will be able to process it folowing the jg at 0040119E whic
and so on .. So we found a good point to insert a jmp to our code which will proc
ID value relative to the new menu, but we need to create this menu don't u think
So run BRW (Borland Resource Workshop) and open notepad.exe (create a backup firs
menu section and under Help menu add a new item called "Patch Info". Now give it
Remember any ID value > than 33 is good. Now save and run notepad. U'll see a new
Help menu. But when u click it nothing happens. Well we are going to inject a Mes
"Patch Info" is selected it will show u a nice little msgbox.
So now we have to add the code to the file. How can we do this??? =:[ CODE INJECT
OK now we will jump from 00401BA to our CODE CAVE - 00404959. Here we GO....
was:
becomes:
---------------------------
our code:
:00404989 cmp eax,23 <- eax holds current item ID's. 23h -> ID of our new menu
jz 00404999 <- if u clicked our menu, process it
cmp eax,300 <- these are the 2 code lines that we replaced with the jmp
jl 004011E2 ; we restore them
So when the "Patch Info" is selected the code above will be executed and a msgbox
will be displayed saying "wINDOWS nOTEPAD pATCH v1.0 by [brzi] of DEViOUS"
Here's the final TSearch script:
cmp eax,300
jl 004011E2
jmp 004011C1
ok, maybe this was not very explained but it's very easy to understand (unless u
Now in TSearch in the EasyWrite Script press the Tmk button and the press the Che
give u the opcodes that u need when u will patch the file - by this i mean not wh
running but patch notepad so it will contain this code forever.
Well that's all for this tutorial.. Watch for others...
GREETS
******
-> Greets in no special order ^_^
[sheep] +=+ Omega +=+ Stoner +=+ EEDOK +=+ PCP +=+ VBTrainer +=+ Bie +=+ Synbios
Rat +=+ everybody on CES and DEViOUS forums and everything that belongs here...
And thanks to [sheep] for the ascii logo...
To begin, we will assume that you want to hack the reload time for a gun in one of your favorite
games. Let’s also assume that this gun by default takes 6 seconds to reload after one shot has been
fired (gun reloads automatically.) If and when we’re successful at hacking the reload timer for our
gun, the gun will be capable of firing like a machine gun (this depends on the game.)
Using the info above, we will now attempt to find the address of the reload timer. To do this we must
follow these steps:
Step #1:
Open memory searcher and do an advance search by searching for an unknown value (1 byte.) <-- 1
byte because timer values are usually less than 255 in value.
Step #2:
Fire your gun one time and freeze the game immediately after firing the shot (once the shot is fired the
reload timer becomes active,) now go back to the memory searcher and search next: advanced search
- decreased (1 byte.) <-- we search decreased because in most cases the timer goes something like
this: default – 6.0 | shot fired (1 second wait before pause) – 5.0 <-- the timer decreases the longer
you wait, but once it hits 0 the gun is fully loaded. Take note that if this way fails, you may reread this
guide and replace decrease with increase.
Step #3:
Once again fire one shot from your gun, but this time wait just a tad longer until you freeze the game,
then go to the memory searcher and search next: advanced search - decreased (1 byte.)
Step #4:
Now allow the gun to fully reload, then pause the game and go to the memory searcher; search next:
advanced search - decreased (1 byte.)
Step #5:
Go to the memory searcher and search next: advanced search - unchanged (1 byte.) <-- we now
search unchanged because the value has not change as we didn’t fire any shots this time.
Step #6:
After going through all the steps, your memory searcher should now contain the appropriate addy(s)
for the reload timer, if not try altering a few of the values/search types contained here…Good luck
hacking timers!
- Phoenix -
Resolving Dynamic Memories at Runtime
by Tsongkie
I. Introduction
In this guide, I would try and explain to you a certain advance technique in game training that is
lacking in most game trainers. I will not provide a source code for every coder has his own way of
developing his trainer, so if you are looking for that, dont waste your time reading this tutorial. I will
explain in pseudocode and theory on how it is done. May I remind you that this is only a way, not
THE WAY.
In a certain game, I found the following addies, although the values are dynamically allocated by
runtime to different addies.
Notice that they are separated by 8 bytes. I restarted the game, found 3 different addies but also are
separated by 8 bytes.
Also, when I scroll up and look at the bytes before our addies, i found a 909090EB08909090 exactly
16 bytes before the first addie (Gold). I then restarted the game and find the same bytes over and over
again at exactly 16 bytes before our addies.
We want to write a trainer that resolves these addies at runtime. So how do we do that? Lets see what
we know....
1. Our addies, wherever they may be located are always 8 bytes apart.
2. At exactly 16 bytes before our addies we could find the hex bytes 909090EB08909090
Since we already know the facts, we can use it in our trainer to resolve the game addies at runtime.
What we need to do is search for the "signature bytes" and when we find it at 16bytes to that address,
read a dword (gold), add 8 bytes to that addie, read a dword(silver), add another 8 bytes to that addie
and read the final dword (bronze).
V. Final Words
Well, I hope you learned something from it. If there is something vague in the tutorial, pls contoct me
via e-mail : root@tsongkie.com or go to team extalia's homepage. www.extalia.com
Tsongkie
http:/www.tsongkie.com
Extalia
Learn from Trainers WITHOUT Trainer Spy
by Orr
OrrAghion@hotmail.com
*NOTE!*
The reason I am writing this paper is not of teaching the lamers out there another method
stealing other people's hard work, but I want to let the Game Hacking community know a
this finding (though a lame finding, but still something good to keep in mind and be aware
Please Don't be a lamer, and honor other people's hard work.
Target Audience
This tutorial is aimed for the more experienced hackers out there, as I assume that you ha
the slightest knowledge of SoftICE or any other debugger, and that you know how to use
disassembler (such as IDA).
Preface
Today, most of the trainers that are actually CODED and not created using a trainer make
program, contain a certain protection against the notorious program "Trainer Spy" created
by Olivier. Trainer Spy is an amazing program which uses a kernel-mode Virtual Device Dr
(VxD) in order to "Hook" the most common functions used by Trainers: WriteProcessMemo
uhm, ReadProcessMemory (which is not used very frequently).
When I say hooking, I mean that whenever one of those API functions occur, TS intercept
the call, and watches for all the parameters passed to it. Those parameters include
the address and the value the trainer is writing to.
By adding Anti-TS code to the trainer, the coder thinks that he eliminates the option of
viewing his hard work. One must keep in mind that a successful Reverse-Engineering
attack can be accomplished in two ways:
1. Dynamic Analysis; Tools used are Trainer Spy and a Debugger.
2. Static Analysis; Tool used is a good disassembler such as IDA or W32Dasm.
In this short essay I will try to review some of the "attacks" used by a more advanced
hacker, should he try to learn from a trainer.
Essay
Recently, when I tried to cheat in a game, for some strange reason the address I found
wasn't correct and I couldn't train it. I decided to download an exisiting trainer from
the Internet, and check out the address it writes to, so I can find out where I was wrong.
Most trainers use the WriteProcessMemory API function in order to write to memory addre
Here is the function's prototype:
BOOL WriteProcessMemory(
HANDLE hProcess , // handle of process whose memory is written to
LPVOID lpBaseAddress , // address to start writing to
PVOID lpBuffer, // address of buffer to write data to
DWORD cbWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten // actual number of bytes written
);
A normal call in a high level programming language would have been written like this (Pse
push lpNumberOfBytesWritten
push cbWrite
push lpBuffer
push lpBaseAddress
push hProcess
call WriteProcessMemory
Did you notice that the data is pushed backwards? That's because of the stack concecpt;
Last In First Out or LIFO.
Static Analysis
By disassembling the file, one can learn alot about the target trainer. By Tracking a certai
call to WriteProcessMemory, one can view its parameters, and later analyze and decide th
memory address the trainer is writing to.
I will use an example trainer from CES (www.gamehacking.com). It would be MI2's DII
Trainer. It is a mega trainer, and I must say that it is one of the best trainers
I have ever seen! I hope MI2 doesn't care that I use his trainer as an example..
MI2's trainer contains an Anti-TS protection. Although the trainer uses a protection that
can be bypassed really easily (just by changing the caption of TrainerSpy's Window),
I will demonstrate how to apply my method.
Let's say that I want to know which address is needed for the Dexterity. After I
click the "Dexterity" Hack, I get this message: "Your dexterity is higher!"
So disassemble the file with IDA, and after it is finished, go to the Names window
and look for that string (should be "aYourDexterityI").
Follow the call to that location and soon enough you should end-up here:
So you see that the address the trainer is writing to is D188F4, easy isn't it?
Dynamic Analysis
By using a system-level debugger(Such as our lovely SoftICE), the attacker can monitor
any call to the WriteProcessMemory API function, and view its parameters.
Sometimes, the address parameters will not be shown in such a visible way as in the
previous example. Sometimes the address will be hidden and shown inside a register,
or inside another memory address. A common way of seeing it is (TMK1.4a compiles its
trainers this way):
You see that the address is not shown in a clear way, but inside the EAX register.
In this case the attacker would simply apply the '? eax' command inside SoftICE,
and the address would get crystal clear to him.
There are quite alot of methods of protection when it comes to static analysis:
1. You can encrypt the file using a PE-Packer (I like UPX and PETITE), and
by this hiding the code and protecting it. This method can be easily bypassed with
the use of an UnPacker such as ProcDump.
2. You can "encrypt" the address you are writing to. By XOR'ing a value twice
with the same number you get the same result you had before. Here is a little
Visual Basic code snippet to help you visualize my thoughts:
Ending
I hope you enjoyed reading this essay as much as I did writing it. I hope I
shed some light on this somewhat 'dark' subject, and brought an important issue
to the attention of some people.
You must remember that the really determined reverse-engineer cannot be stopped
from viewing your addresses, and that the above methods are only here to keep
lamers away. Know that if anyone can read your addresses after applying some of
the methods suggested above, he is also capable of finding those addresses himself :)
For Comments (I like comments :), Suggestions, "Bug Fixes", Flames, Love Letters,
Anthrax Envelopes or Moeny, Mail to OrrAghion@hotmail.com
/\
____/__\____
\ / \ /
\/ \/
/\ /\
/__\____/__\
\ /
\/
Game Hacking
by Sorin
An Overview
Intro:
In the following, I'll show you what GameHacking is, an how you
can work it out :)
1. What is GameHacking ?
All of you must played even for one time a game that you couldn't finished,
or couldn't pass X level, or something like that. The solution was :
a) make use of the game's cheat_codes (if any). But with this you are
treated by the game like an ordinary cheater : NO HIGHSCORE !
b) put yourself together, download some useful tools from the web and
try to make yourself the law for the game (i.e. : make your pistol
bullets be unlimited without using any game's cheat_code)
NOTE: If you like very much the game, then have the patience to finish it
without any game_hacking. After that, hack it until your eyes will be stic
on the PC's monitor !!
a) a good Debugger (Soft Ice, of course) - we'll use the debugger in advanced
techniques of game_hacking, when you need to trace the game's code.
c) a Hex-Editor (HexWorkshop, Hackers View) - we'll use the hex editor when
hacking the saved_game files, or when we modify the game's .exe/.dll ...
- http://www.protools.cjb.net/
- http://www.gamehacking.com/
- http://www.ghu.as.ro/
- and at many more sites...
I. Memory Hacking
a) Value poking (when changing the amount of grenades, for example)
Ecx holds our energy. We have found the instruction that decrease it.
To avoid decreasing, we patch like this:
By changing "dec ecx" with "nop" (49 with 90), we prevent our energy for
beeing decreased. Preety kool, huh ? This method is EXTREMELY EFFECTIV
when we have to deal with DMA.
Here's why we need Hex-Editors: If the game you want to hack has a
"save curent game" option, you can hack that .saved file...
What did we deduce ? The game changes the locations of your data EVERY TIME !
BUT, let's take a closer look... In all 3 cases, the difference between the add
is THE SAME !
This means our DMA problem ('till now) reduces to : FIND THE PATERN ADDRESS whi
By knowing the PATERN ADDRESS, we can easily add the difference to get the othe
addresses !
Well, we clarified what is DMA... But how can we bypass that ? SIMPLE ! Code
Injection ! (or kill the instructions that makes your day miserable)
Code Injection is, like the name says, Injection of Code :) hehehe...
Here's an example:
This is DMA... We found that "PARENT ADDRESS(POINTER)" is ecx. But since is DMA
ecx also changes. So we need to keep this ecx stored in a place from where
we can mess with it all time, knowing it's value...
How to do that ? SIMPLE ! Find somewhere in the game's code a place full of 0's
There we will inject our code. The injection routine is very simple:
- find some empty space in game's memory a.k.a the 0's (or FFh)
- overwrite an instruction with a "jump" or "call" instruction that jumps to th
place full of 0's
- reconstruct the overwritten instruction
- overwrite some of 0's with our code (to catch the parent address)
- jump back (or "ret" if we used a "call") to the initial place (game's code)
ORIGINAL MODIFIED
mov eax,[ecx] | jmp 4455 (place full of 0's)
dec byte ptr [eax] | dec byte ptr [eax] <-------<---------<----<-
mov eax,[ecx+20] | > mov eax,[ecx+20]
dec word ptr [eax] | dec word ptr [eax]
mov eax,[ecx+50] | mov eax,[ecx+50]
dec dword ptr [eax] | dec dword ptr [eax]
...................
offset 4455: (where we found the 0's)
mov eax,[ecx] - we reconstruct overwritten instr.
mov dword ptr[5555],ecx - save parent to a STATIC addr
jump back to "dec byte ptr [eax]" ----->--->--->------
With this, we defeated DMA by saving the PARENT pointer to a STATIC memory loca
And in our trainer we just read the PARENT pointer from address 5555 (stati
then add the difference to obtain the pointers for other addresses (for
life, money, etc).
Also NOTE : that 5555 address is where there are lots of 0's, too ! If u find 0'
1234, then don't use 5555, use 1234 !
!! A BIG THANKS GOES TO SHEEP FOR HIS DMA TUTS. THEY WORTH READING !!
Now, that we have finished DMA & CODE INJECTION, let's have a look on the differe
hack methods...
Let's take first the .SAVE file patching... What can we do here ? Well, search th
saved_file and replace the wanted value with the new value...
Let's take for example WarCraft II. Play a single player game. After a while, sa
game under XXX (for example). And remember your gold amount !!! Now, load
XXX file in HexWorkshop and do some searching... But the search type must
under "32 Bit Unsigned long". That's because u search for a base 10 number
this number can be greater than 65535 (biggest word value). Got the idea ?
Now you type in the "Value" edit_box the amount of money, and click OK...
Simple, heh ?
But there are also A LOT of games that save their data ENCRYPTED (like StarCraft
Here we need the memory_searcher ! So, fire it up (TSearch, ArtMoney, etc) selec
process the game you want to cheat in, and search for the wanted value. The
memory_searcher will find many addresses containg your value. To bypass this
go back in the game and CHANGE that value. Pause the game, go back in mem_se
and search for the new value ! Repeat these steps until you will find only a
addresses. Then all you have to do is to try changing the value in those add
and see (in the game) how affects you and what is the one you need...
YES ! This is awesome ! And sticks very_well with DMA & CODE INJECTION !
But to master this technique, you must have (some) asm knowledge...
Here's an example :
You find your bullets at addr. 100. Open SoftIce (^D), and put a bpm on that ad
< bpm 500 >. BUT YOU MUST BE IN THE GAME PROCESS !!! (Check SoftIce's lower
corner. If it says the name of the game, then you're IN !)
.............
xx: mov eax, [44]
yy: dec eax -> you land here in SoftIce
zz: mov dword ptr [44], eax
............
What do we see ? The game moves in eax your bullets number stored in memory at
[44]. Then it comes that UGLY instruction "dec eax", then update your decre
bullets back in [44]. So, to prevent bullets for decreasing, we just "nop"
operation) that "dec eax". You can do it in SoftIce by typing:
asm yy [ENTER]
nop [ENTER]
[ENTER]
Yeah, this is a GOOD method, but we don't want to do this SI thing all the time..
OK ! There are 2 solution :
a) make a trainer
b)
This is almost like above, except we change the instructions permanently ...
We'll use Hiew. Fire it up and load in it the game's .exe. Press F4, select "De
then press F5 (goto address) and type that yy number you had from SoftIce.
press F3 (edit), then F2 (asm), then write your "nop" instruction. Then pre
[ENTER], then [ESC], then F9 (save) and you're done !
REMEMBER : Sometimes, the instructions that dec your life, money etc are not in
.exe file, but in some game's .DLL. You can easily find this out wi
SI by looking at the offset of the respective instruction. If it sa
something like 1XXXXXXX or so, then your in some DLL ! You can also
at the lower right corner of SI.
In the following there will be presented some techniques on hacking different thi
in a game...
BULLETS, LIFE, MANA, GRENADES etc (when you know their real amount) :
ENERGY BARS, BULLETS, LIFE, MANA, GRENADES etc (when you don't know real amount)
*** The value of a full energy-bar is usualy around 250 !!! ***
representing the screen. When your unit is moved on a[5,6] (for example), then t
puts in that place in matrix the coded_byte for place_without_fog. When you m
your unit from that place, the game puts back at that place in matrix the cod
for place_with_fog.
My personal opinion...
PS: Don't bitch me if u find a game that has diff. ways to store the map...
- Groza (BEST publisher :) - I'm still & still waiting that tut on C&C map_hack :
when you'll have time, of course... )
- Snaky (toate cele bune ! )
- T-RaiNeR (n-am mai vorbit de mult... nasol e cu bac'u asta :((( )
- ParaBytes (my cracking teacher - a BIG THANKS)
- Some in GameHacking's forum ( some of u are great, but some are made of cocoa :
- All GHU members (Cei mai buni ! - Biciuila esti si tu inclus, cacaciosule !)
- JUVENTUS (I love JUVE)
- YOU
romanian:
*******************************
* Salutari celor din Romania! *
*******************************
Special Greet Goes To Synbios -> he knows why and I hope he'll forgive me someday
Advertising:
Sorin ( Splinter@email.ro ).
2003
eof
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
We'll start with cheating only in this tutorial and maybe later you will learn ho
a trainer. Here I will only give you an impression of what is possible.
I assume you are on a windows computer and you have Minesweeper on it.
You will need an easy program called the "Cheat 'O Matic" by Nick Shaffner.
Start up minesweeper and AFTER that the Cheat 'O Matic (CM from now on).
When you are in minesweeper and you click on one of the boxes the time begins to
Now minimize minesweeper, wait 5 seconds and then maximize it again.
You notice that the time is the same as when you minimized it. That is helpful fo
From the drop-down box select Minesweeper. Go back to Minesweeper and start a new
Then click once so the time begins to run. Now look at the time and minimize it.
Now press the SEARCH button.CM will now search 7 in the memory (DMA) in your comp
After a while it will stop and say: (Change the value in the program, then enter
We will do exactly that. So go back to Minesweeper and wait a few seconds until t
has become a little bigger. Say for example that it is 14 now.
Go back to CM, fill in 14 and press SEARCH.Again it will search for the value you
Change the time again and search again until you get a message like this.Cha-chin
Now what we shall do is freeze the time.On the down left you will see LOCK. Check
Now in Minesweeper press the smiley and start playing. You will see that you have
Congratulations !!!
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Greetings go out to all of Computer knightS (EFNET, #computerknights) especially
Greetings go out to all of Extalia members especially SnokGreetings to [Sheep] fo
Greetings to #cracking4newbies.
Greetings to #gamehacking.
Greetings for all the others. You know who you are ;-)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
BliZZard, blizzard_1337@hotmail.com
1.Tutorial about using trainers
by Reaper
e_nesovski@yahoo.com or
reaper@extalia.com
www.extalia.com
################################################################################
Intro:
In this tutorial I will tech you how to use and to learn
how a trainer works, I know these is very easy, but there
are some people that don't even now what a trainer is.
################################################################################
Needed things:
1.A trainer
2.The game that the trainer is made for
################################################################################
How does the trainer work?
The trainer is used to poke memory addresses of a game.
Poking means changing or freezing the values of some addresses.
The trainer only works with the game that is made for, which means you
can't use a trainer for all the games, only for 1 and only with the
version of the game that the trainer is made for (ex. counter-strike 1.1, 1.3...)
A trainer doesn't always have the options the you want, if some game
has lives, ammo, shield, that doesn't mean that in the trainer you can
change all of that.
When the trainer pokes in some game, it can make you have unlimited
life's, money, wood, gold, ammo, reveal map...to do this the trainer writes, adds
or freezes the value of a memory address. As the trainer must work while the game
most of the trainers will require you to minimize the game (With ALT + TAB) so yo
use the trainer, but some of them have hotkeys which you can use while playing
the game. Sometimes if you use a trainer, it could happen the game to crash or
the anti-virus program to think that the trainer is a virus, but the trainer
isn't a virus in anyway and if the game crashes while using the trainer that
means the game has some protections and it may be unstable while using a
trainer, therefore you can continue playing the game with the trainer or find
cheats for it. Also note that trainers are legal only if they work with single pl
games, while using a trainer in multi player games can sometimes be illegal and m
lose its fun for you and the other players that are playing with you.
################################################################################
How to use a trainer?
1.You must have a game, example Age of Empires 2.
2.Now go to some cheating site that has trainers and download the trainer for thi
(some cheating sites with trainers are: www.extalia.com www.gamehacking.com www.x
www.megagames.com www.dlh.net ...)
3.Almost always the trainer comes in zip or rar files, so you will have to extrac
some folder.
4.Now go to that folder and start the trainer
5.Now start the game (the trainer must be working)
6.Start playing the game, and press ALT + TAB
7.Now your back to the trainer (the game is still running) and click on a button
the trainer to start poking (ex. chose to have 1000000 wood, gold, rock, food or
8.Go back to the game, and you will see that you have 1000000 wood, gold, rock, f
There are also some trainers that have hotkeys, if you know the hotkey for some f
trainer (ex. life's, ammo) you don't have to ALT + TAB to go back to the trainer,
hotkey and trainer will start poking (ex. if the hotkey for ammo is SHIFT + R, in
playing press SHIFT + R and you will have get ammo without having to minimize the
################################################################################
Now that you know how to use a trainer, maybe you want to find out more about gam
and learn how to make a trainer. To learn this read my tutorial on how to make a
and Part 2.
THE END
- What Is "Gamehacking" - By Elissaios.
The illegal stuff are starting to flow when a personal/computer system security i
2 :: Gamehacking process.
When we hack a game we do not actually hack its contents within, but its stambed
The only case gamehacking can turn illegal, is to hack online multiplayer games.
- Game Server Hacking. You dont have the right to hack memory table of company's
- Various of complains to game companies by gamers saying "I had full health and
- Luck of online gaming fun! Its the first reason why u shouldn't hack multiplaye
- Its not fair! Be an online gamer, not an online lamer!
I hope you've learned some things you were questioning before. Thanks for reading
-Elissaios.
Tutorial Written By x-UnDeaD " undead@extalia.com "
Take a fast visit at www.extalia.com :D
___________________
A trainer can be alot of things,a Trainer(Cheat) that helps you in a game, where
Where they add an help function like AutoKnife,so it makes you'r knife ,knife fas
Or it could also be speedso you can run from a guy that is hunting you or move WW
But a SP(Single Player) trainer doesn't hit any server or host,it only hits the g
Which is NOT illegal,cause it is Legal :-)..
That's why WE only and are only going to provide SP trainers.....
By x-UnDeaD
What is hotkey(s) used for and what can they do?
----------------------------------
By x-UnDeaD
__________________________________
Hotkeys can be a hotkey in the game or a trainer, most used hotkeys is in a train
I use the hotkey function in vb GetAsyncKeyState , someother's use SendMessage.
To get an example of this read the text below :
__________________________________
You are in a game the ALT+TAB function has been disabled by the people that made
You think,darn this sucks,how am I now going to use the new cheat I downloaded?..
That is why hotkeys exsist, so u can press them instead of ALT+Tabbing Out if it
-Just a small simple tutorial about hotkeys..
By x-UnDeaD
Contact Me At : undead@extalia.com or register at the Extalia forums and send me
UnDeaD..
BY x-UnDeaD
Contact Me At undead@extalia.com Or Visit The Extalia EXP site At: www.extalia.co
Back to Delta Force.I played that A long time ago,when it first was released, the
n00b's asked guys that got cheats if they could tell them where they got it or ho
..................................
Later / x-UnDeaD
:::::::::::::::::::::::::::::::::::::::::::::
:: GAMEHACKING TUTORIAL PART 2 ::
:: BY BLIZZARD ::
:::::::::::::::::::::::::::::::::::::::::::::
I assume you have also read part 1 of my tutorial. In the first tutorial you saw
Okey let's do that.In this tutorial I will teach you how to make a trainer. You w
Okey let's start. You have to download a program called TSearch. It is available
So I start a skirmish game and look around. Let me build a Marketplace. Mmmm mone
Then I press the small button of a magnifying glass just under the OPEN PROCESS b
I fill in 2000 and I get 97 results. Back to the game. I will buy some iron so my
Fill in 1775 and press OK. I get 1 result. For me the address is D5E168. For you
Click on your (DMA) value 1 time and press the green + symbol a little above it.
Okey let's make a trainer. Remove the blue smiley by clicking on your line and pr
Now go back into Stronghold:Crusader and buy something 1 time! Then ALT+TAB back
* 40FF98: add [eax], ecx* 40FFBF: mov [ebp+0xD5A774], edx* 464FA2: mov [edi+0xD5A
Now we are going to use what they call the TRIAL AND ERROR way of which one is th
As you will see your money will not be decreased anymore! NOTE: In the autohack w
Okey so we know now that the line:* 464FA2: mov [edi+0xD5A774], ecx is the line t
But what do we do with it now? Select the * 464FA2: mov [edi+0xD5A774], ecx line
:::::::::::::::::::::::::::::::::::::::::::::::
Tmk button script
Copy and Past into tmk using ctrl+V
Ex: Patched script for a ON button and Unpatched script for a OFF button
Patched script:
Poke 464FA2 90 90 90 90 90 90
UnPatched script:
Poke 464FA2 89 8F 74 A7 D5 00
:::::::::::::::::::::::::::::::::::::::::::::::
Copy this into a text file because we will use it to build our final trainer!
But that in the next tutorial ;-)
:::::::::::::::::::::::::::::::::::::::::::::::
Greetings go out to all of Computer knightS (EFNET, #computerknights) especially
Greetings go out to all of Extalias members especially Snok
Greetings to [Sheep] for helping me out.
Greetings to #cracking4newbies.
Greetings to #gamehacking.
Greetings for all the others. You know who you are ;-):::::::::::::::::::::::::::
BliZZard, blizzard_1337@hotmail.com
Welcome To A Tutorial I Know Alot Of People Will Have A Use Of.
FINDING AMMO
______________________________________________________________
Go back into your game,select the gun you want ammo for(knife cannot be used.)
Go back in the game,and waste one clip so it should show that you have 1 clip lef
ALT+TAB out of the game again,and search for 1 ,and now you should have one addre
there it is,you have now found the ammo code.U can freeze it so it doesnt increas
Contact :
undead@extalia.com
REMEMBER : EXTALIA EXP DOES NOT PROVIDE ANY MULTI PLAYER HACKING OR TUTORIALS.
WARNING: always make a backup copy of files before you start dissecting them, I am not
taking responsibility if you accidentally disassemble your Main Battle Flagship or manage to
edit a file so that it corrupts your entire game - (some games just don't like to be messed
with....[e.g. Age Of Empires].
*****************************************************************************************
The Registered Version of this program can be purchased and
received immediately on the Internet at Albert's Ambry.
http://www.alberts.com/
Search on: hextool.zip and then Click on the "Buy It" Hotlink to register this software.
*****************************************************************************************
Hands On Experience
Basically, a hex editor lets you view the hexadecimal code in which most save games are
compiled/saved. When you're trying to cheat by adding money, attributes, ships, gold,
lumber, ammo etc., you'll be looking for a string of hex characters that will look something
like this:
08 49 FA 9B 58 09 DA
and replacing it with an altered string that the cheat file/hex editor tells you to. All you're
doing is the same as changing "credits=1000" to "credits=1000000". So, load the hex
editor, (its easier if you place the hex editor files in your Utils directory so if you have a
DOS path set to include \Utils, you can use the program anywhere on your drive) by typing
'hex ' and the filename you need to edit in order to get your credit bonus - e.g. C:>hex
save1.sav. When it opens, it'll look something like below:
The column on the right is the ASCII code generated by the characters to the left. So, in
this example, the amount of credits I have in the game is 14847889 (I already cheated!!!!).
So we are looking for the string "14847889" but we don't know the hex equivalent, you can
use the converter (ALT B) and type in your decimal figure. Hexadecimal is what we call a
base-16 system, which just means that instead of counting 0-10 for each decimal place,
you count 0-16, using A-F instead of 10-15, so, if 11=0B, then 15=0F and 16=10 and so
forth. It takes a little practice, but it's really not too hard, especially if you keep a pad and
pencil handy for notes, but again being kind old Mogsy, the editor I use can convert
decimal, hexadecimal and 2 others (told you it was good), so as I said, you can convert
back and fore from hex/decimal at your leisure!
Back to the editing, so as per the picture, to convert '148478889' to hex in order to find its
location its hex address), use ALT B and type in the decimal figure, this then tells us the
HEX equivalent which is 'E2 8F 91', but here is the twist so READ carefully - any hex figure
that uses more than 1 byte i.e. over FF (255) must be reversed before editing it to your
hex file. So it now becomes '91 8F E2' and we do a search using F5 and type in the string.
It tells us that it is located at offset 2D (shown in green text on far right of screen). The
offset is used so you know where to return to the next time (use ALT G and type Offset
number). Phew!!!!
Some cheats lists will tell you to replace a complete string, others just say the first
occurrence and so on. If you've backed up your files, you should be free to experiment with
whatever variables you can find, and believe me they sometimes are hard to find! Then,
rename your original file (save1.sav -----> save1.bak), save your edited file under the
original file name (save1.sav), load the game and load your save game, now you should
have enough credits to buy an army/armada/fleet. Be aware, that some games will crash,
should you insert some weird values, Alien v Predator and most MS based game are bad
for this.
That's all for now, I will do an update soon, for all the new types of games.
Any comments or queries, just email 'em to me with Header/Subject : Hex Edit Query
You use a tool like Hex Workshop. Basically you need two tools to hex edit successfully.
A hex editor:
http://www.bpsoft.com/
That is the one I use, I use AXE (Advanced HeX Editor) too but Hex Workshop pretty much suits my needs.
A disassembler:
ftp://underhalls.ftphost.net/pub/st...es/w32dasm7.zip
I use Windasm, which I linked above. I also use IDA Pro, but that program does not even have a trial
download (at least I think) so I can't give you a dl link.
The last thing you need takes a bit more time, and that is knowledge of assembly. Now don't think this is
the only thing you will use it for; I promise you if you ever want to be a really good game hacker you are
going to have to learn it.
What you do is use the disassembler to disassemble your target program into its assembly equivalent.
Please do not confuse this with a decompiler, which interprets the program and displays its contents in the
language it was programmed in.
You use your knowledge of assembly and follow the disassembled code around to find the code you need
to alter to accomplish whatever goal you may have. The disassembled code will look something like this:
Code Location
004010F8
Opcodes
740B
Assembly Instructions
je 00401887
je = a conditional jump. Two values were compared and it jumps to the code location 401887 if the values
are equal (that code location would be a tag in the original code, like say maybe this is for a cheat detector
and it jumps to NoCheat: if the values are equal (maybe it did a checksum and is making sure its value
matches up with the hardcoded value) when the program is assembled it gets turned into that address). As
you may see je stands for Jump Equal (jump if equal).
Ok know I am sure you want to know how this stuff is useful? You use the assembly intructions (and the
code location) to follow the code around and find what you need to alter to make the program do what
you want. I will tell you know that in game hacking you will almost always be playing with a jump.
Say I discovered what I need to do to make my game allow me to play with cheats (remember in this
example we are defeating some sort of cheat protection albeit very simple protection) is force this jump. In
other words make it jump to NoCheats: even if the checksums do not match because a cheat was found.
What I would need to do is go to that code location and change the opcodes to make it jump no matter
what (an unconditional jump). There is a problem though, the code location is not the same address as it
will be in the hex. The code location is a Relative Virtual Address (RVA). What I need to do is use my
disassembler and have it tell me what the RVA is as the hex address. In Windasm you do this by highlighting
the line and reading the status bar.
Now you need to convert the assembly instructions (mnemonics) into their hex equivalent. Je = 74 as you
see in the opcode, and we want to change it to EB (jmp = EB). So what I do is open the program in my
hex editor and go to the hex address I obtained and change the line 740B to EB00. Since I replaced a
conditional jump with an unconditional jump, I did what is called "forcing" the jump. Now it will go to
NoCheat: even if a cheat was found.
Wow this ended up being a long post. I didn't really mean to write a tutorial, but it looks like I did. I hope
you followed it. I decided to write a general overview of how to do it because I didn't know of any good
text and pretty much taught myself all this
How To Hack Games So You Can Skip Levels
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Tools Needed :
-Game Hack 2.0(Free And Good)
-Game With Levels
Step One > Go Back Into The Game And Pass The Mission.Then Alt+Tab Into Game Hack
Menu,Select Increase And Search.You Should Still Get Too Many Addresses For Game
Step Two > Go Back Into The Game And Load The Save Game That You Just Saved,Alt+T
Out Into Game Hack,Make A Next Search But Select Decrease This Time.
Step Three > Repeat The Two Steps Above Until You Have The Least As Possible Addr
Step Four > Now Reload The Game And You Will See All Your Address Values Turn To
Game.Now Try To Finish The Mission.Just As You Are About To Win,Alt+Tab Out Of Th
Step Five > Now,WATCH CAREFULLY!!! See The Values That Turn From 0 To 1 ? Delete
Ok The Easiest Part Is Here. Just Quit The Game And Reload It Again.Load Your Sav
Trial And Error Method To Change The Values Of The Address You Have One By One Fr
In The Game By Turning Up Your Sound And Listening The Victory Sound.
Step Six > Create Your Trainer With The Address And Poking It To 1 And You Will h
=-=-=-=-=-=-=-=-=-=
By SubZero
C.E.S
-------------------------------------------------------
Introduction:
_____________
I am going to keep this short and sweet so don't blink. This does not include an
Tutorial:
_____________
A hex editor:
http://www.bpsoft.com/
That is the one I use, I use AXE (Advanced HeX Editor) too but Hex Workshop prett
A disassembler:
ftp://underhalls.ftphost.net/pub/st...es/w32dasm7.zip
I use Windasm, which I linked above. I also use IDA Pro, but that program does no
The last thing you need takes a bit more time, and that is knowledge of assembly.
What you do is use the disassembler to disassemble your target program into its a
You use your knowledge of assembly and follow the disassembled code around to fin
Code Location
004010F8
Opcodes
740B
Assembly Instructions
je 00401887
je = a conditional jump. Two values were compared and it jumps to the code locati
Ok know I am sure you want to know how this stuff is useful? You use the assembly
Say I discovered what I need to do to make my game allow me to play with cheats (
Now you need to convert the assembly instructions (mnemonics) into their hex equi
by Tsongkie
www.tsongkie.com
www.gamehacking.com
A little Intro
--------------
I've read tutorials by [sheep] and eedok and somehow I have learned
to fuse the two great tutorials in 1 unique way that can help most
gamehackers in training games. I have seen several vague tutorials
on this also that may not be to the specific point on what readers
want to learn. I would try to be as clear as we go on...
Needed Files
------------
Pointers
--------
Let's define what a pointer is. Get Falcon's Beertender from my website
and run it. Play around with it for a while. As you would notice, you have
4 lives, but in the screen when you have all the lives it shows III. Thats
because when you get killed it turns to II - I - NIL respectively. You
get the idea, right?
Ok, play again and search for 4 in tsearch. It will help if you pause the game
using the File Menu of the game. Click spel - spelegrer. That should have shown
an about box and the game paused. =p Die and sieve again to 3.
I get the address 9304C4 (4bytes). Enable autohack and show autohack window. Righ
click on the address and choose autohack. Get back to the game and loose another
Pause the game.
what this means is the value at eax is being moved to [ecx+0x4] which is our life
address. Try NOPping It and get back to the game. Lose a life... great! our life
isn't decreasing but our points are not increasing either. Not only that, you don
advance after you win the game...
Thats because the code mov [ecx+0x4],eax is also being used by some other parts o
the game like our points. Restore the original code by unNOPing it.
The easiest way on defeating this is to find a pointer to our life address. This
how to do it:
Ok lets get what ecx is. Using Tsearch's calculator, subtract 4 from 9304C4 which
should then give you 9304C0 (lol we dont even need a calculator for that :) ). An
convert 9304C0 to decimal by clicking the "D" beside 0. I got 9635008. Then searc
9635008 in Tsearch. The result is the pointer.
We should all have the same pointer which is the address 417CC4. Whatever is in t
address and it by 4 is your life address!!! Alright, let's test this. Restart a n
game. Read the value at 417CC4. Type it in the calculator, convert it to hex and
You got the new life address!!! hooray!!!
What you can do with this is have your trainer read 417CC4 and add 4. You should
the right address to your life. Congratulations, you resolved a dynamic memory in
runtime.
Code Injection
--------------
I'm a lazy ass and i want to resolve all this by just injecting my code. This is
very useful when it comes to games that uses the same code to a computers life ro
and your life routine.
Ok we have:
mov [ecx+0x4],eax
mov eax,[esp+0x4]
mov [ecx+0x4],eax
Alright, we already found out our pointer address which is 417CC4. What we need t
is compute if ecx is equal to the value in 417CC4. Remember that the value in [41
plus four is equal to the life address and ecx plus 4 is also equal to the life a
therefore we conclude that ecx = [417CC4]
Note:
[417CC4] - means the value IN 417CC4 not 417CC4 itself.
Enable code:
offset 0x403240
jmp 0x400000 //jump to our code cave
NOP
DISABLE CODE:
Enable this easywrite hack while playing the game. We have hacked Falcon's Beerte
The score is now also increased and the stages loads normally. *sigh*
Final Words
-----------
Some game trainers modify (increase/decrease) values, such as your health, or lives. Others prevent
those values form changing. So you never take damage.
If you just want to know about the protection methods you can just go on further but if you want to see
these protections at work, I recommend having this software before you continue.
Before I begin let me explain what a trainer is. A Trainer is a seperate program that has the ability to
access the Primary memory used by another program in an
attempt to change valuable data ( in this case ammunition, health, Lives etc.)
In short Trainers are like external cheat codes. They seem to be fun if you are the gamer but if you end
up being a developer it's a lot frustrating as the whole action and difficulty of the game is lost.
Even though trainer protection is not very critical it still is a good way to ensure that the game is
played the way it is meant to be played. Some game developers are now trying to stop creating cheat
codes in their games since the whole point of the game is lost.
An example is the game Uplink Hacker Elite by Introversion in which the patch for version 1.3
onwards disables cheats. CD-Protection schemes do not prevent cheats from being used, CD-
Protection schemes are used to prevent piracy. Trainers turn out as substitutes for cheats. This Article
will help game developers to make trainer creation difficult if not impossible.
(i).Some people think that displaying a value such as health in a graph stops beginners from making
trainers.But this is not so.Assuming you are playing a game in which your health is displayed in the
form of a graph. Now you start the trainer maker program which can search for values within an
application.Nowadays these Apps have become so intelligent that they can even monitor changing
values. So in this case we would set the search mask for "a decreasing value" and do our best in the
game to keep losing health. Eventually the address is found. Overcoming this is explained later.
(ii)Another frequent method used is to use floating point numbers to store data. But Again Trainers
allow mere users to search for float and double values.So this wont work either.
(iii)Adding/Subtracting/Multiplying/Dividing Numbers and using the result as the actual data has also
lost importance. Because all you have to do is to find the value when your health(or whatever) is
FULL and then "Freeze" the memory location as your health decreases. This way people can even
overcome this protection without even knowing the calculation mechanism.
(iv) Using two or more variables even of different data types isn't of much help the reasons of which
are the same as the one described above.
These are the basic protection mechanisms used to fight trainers but dont work. Now we shall see
what really can be done to stop trainer creation.
MORE POWERFUL PROTECTION MECHANISMS
1) THE PLAIN CONDITIONAL
If you tell a software developer that you check the value of a variable just after you assign a value to
it he might think that you are the dumbest programmer but it is not so. Look at this example that stops
the game when a trainer is detected.
While Executing the code below make sure TSearch is Started and the EXE is included as a process.
Then keep searching for 100/90/80 as the output is shown.
When you find the memory address freeze it or modify it and see the MessageBox Popping Up!!
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
void trainer()
{
MessageBox(0,"TRAINER DETECTED!","WARNING",MB_OK);
exit(0);
}
void main()
{
int health=100;
cout<<"HEALTH="<<health><<endl;
getch();
health-=10;
if((health+10)!=100)
{
trainer();
}
cout<<"HEALTH="<<health><<endl;
getch();
health-=10;
if((health+20)!=100)
{
trainer();
}
cout<<"HEALTH="<<health><<endl;
getch();
health-=5;
if((health+25!=100))
{
trainer();
}
cout<<"HEALTH="<<health><<endl;
getch();
health-=5;
if((health+30)!=100)
{
trainer();
}
cout<<"HEALTH="<<health><<endl;
getch();
}
So checking whether the value has been actually assigned is a very simple yet effective measure.A
Similar type of protection is used in "Prince of Persia: Sands of Time".Try making a trainer on this
game and you will see an ERROR Message and the Game will Quit.
void main()
{
int health;
char *fname="E:\\aaa.txt";
ofstream out(fname);
out<<100;
out.close();
ifstream in(fname);
in>>health;
in.close();
cout<<"HEALTH="<<health<<endl;
getch();
out.open(fname);
out<<90;
out.close();
in.open(fname);
in>>health;
cout<<"HEALTH="<<health<<endl;
getch();
in.close();
out.open(fname);
out<<80;
out.close();
in.open(fname);
in>>health;
cout<<"HEALTH="<<health<<endl;
getch();
in.close();
out.open(fname);
out<<70;
out.close();
in.open(fname);
in>>health;
cout<<"HEALTH="<<health<<endl;
getch();
in.close();
}
The most interesting part of this type of protection is that even if we find the memory address and
modify it or freeze it, the correct value still appears on the screen.However,then the file which stores
the data has to be either encrypted or stored in Binary Format. With Binary Format you can only view
the file correctly if you have the correct contents of the file structure.
3) MORE METHODS......
The previous two are some of the primary protection methods but the right one to choose depends on
the type of the game. If the game requires speed and the FILE STORAGE protection wouldn't be
perfect.If the game size is important the conditional may not be suitable. But the whole idea of setting
up a Anti-Trainer protection is to surprise the people who make trainers. Using a DLL File or the
Registry to store data while Running the game is very frustrating for the game-hackers as no one
would expect keeping such data in DLL Files or in the Registry.
No developer is as of now interested in putting a trainer protection since game development takes a
lot of time and effort. But a Neat Game is a game which only allows people to play the game the way
it is supposed to be played.
Author Information:
Sanchit Karve
http://
born2c0de@hotmail.com
How to Hurt the Hackers: The Scoop on Internet
Cheating and How You Can Combat ItBy Matt Pritchard
Gamasutra
July 24, 2000
URL: http://www.gamasutra.com/features/20000724/pritchard_01.htm
I had planned to begin this article by sharing my own true experiences with online cheating as it pertained to
a particular game. But I think the long version of my story would cast an unnecessarily negative light on the
game and the company that made it. And since the developers are good friends of ours, I'll stick to the
short version that goes like this.
Last year I became hooked on a certain first-person shooter (FPS) game. After a couple months of
addictive online gaming, I became convinced that some players were cheating and things suddenly changed
that day. I was ready to walk away from the game in disgust and tell everyone else to do the same.
Instead, I decided it was time to learn what I could about the alleged cheaters, their motivations, and most
importantly their methods. In my case, I discovered at least three distinctly different methods of cheating
that could explain what I experienced -- though as just a player I could not prove conclusively which
methods, if any, were being used against me.
The aim of this article is to bring the subject of online/multiplayer cheating out of the shadows and talk
about it in terms of real problems with real games and to help build a framework for classifying and
understanding the various details. I will cover some of the ways that players are able to cheat at various
games; at times I will go into the working details, ways to prevent those cheats, and limitations of various
game architectures as they relate to multiplayer cheating. This is by no means a comprehensive and
exhaustive tome on the issue, but it is a start. There is a serious lack of information on this subject, and
paranoia among developers that talking about it will reveal secrets that will only make the problem
significantly worse. Several individuals at various companies declined to talk to me about cheating and their
games for this and other similar reasons. I respect that, but I think developers have everything to gain by
sharing our knowledge about cheaters and how to combat them.
Just how seriously should you as a developer take the possibility of online cheating? If your game is single-
player only, then you have nothing to worry about. But if your game is multiplayer only, the success of
your entire product is at stake. If your game does both, you're somewhere in the middle. As more games
are released with online play as an integral component, drawing ever-larger audiences (and the corollary
development of online communities and sites based around the game), it becomes ever more important to
insure that each online game player experiences what they believe to be a fair and honest experience. I'm
reminded of a quote from Greg Costikyan's excellent report, "The Future of Online Gaming"
(http://www.costik.com/): "An online game's success or failure is largely determined by how the players
are treated. In other words, the customer experience -- in this case, the player experience -- is the key
driver of online success." Our short version is, "Cheating undermines success."
Consider the well-known case of Blizzard's Diablo -- deservedly a runaway best-seller and great game that
acquired a significant reputation for a horrible multiplayer experience because of cheaters. Many people I
know either refused to play it online, or would only play over a LAN with trusted friends. Blizzard did their
best to respond, patching it multiple times, but they were fighting an uphill battle.
Cheating hit closer to home for me while I was working on the final stages of Age of Empires II: The Age of
Kings. Cheating online became a widespread problem with the original Age of Empires. Tournaments had to
be cancelled due to a lack of credibility, the number of online players fell, and the reputation of my company
took a direct hit from frustrated users. Unable to spare the resources to fix the game properly until after
Age of Kings was done, we just had to endure our users turning their anger upon us -- probably the most
personally painful thing I've experienced as a developer.
What about your next game? This is a good time to introduce my first two rules about online cheating:
Rule #1: If you build it, they will come -- to hack and cheat.
Rule #2: hacking attempts increase with the success of your game.
Need more reasons to take online cheating seriously? Go onto eBay and type in the name of your favorite
massively multiplayer game. Now look at the real money changing hands for virtual characters and items.
What if those items being sold were obtained via some sort of cheat or hack? Let's not overlook the
growth of tournaments and contests for online games. Consider the public relations nightmare that would
ensue if the winner of a cash prize in a tournament had cheated. Enough to give you a headache, eh?
The sad truth is that the Internet is full of people that love to ruin the online experiences of others. They get
off on it. A great many cheaters use hacks, trainers, bots, and whatnot in order to win games. But while
some openly try to wreak havoc, many really want to dominate and crush opponents, trying to make
other players think they are gods at the game -- not the cheaters they are. The only thing that seems to
bother them is getting caught. Beyond that, no ethical dilemmas seem to concern them. The anonymity
and artificiality of the Internet seems to encourage a moral vacuum where otherwise nice people often
behave in the worst possible way. A big factor in this is a lack of consequences. If a player is caught, so
what? Are they fined or punished? No. Are they rejected by the people they played against? Usually, but it's
so easy to establish another identity and return to play that discovery and banishment are no barrier to
those with ill intent.
Another interesting aspect of online cheating is the rise of clans and how cheats get propagated. If a
member of a clan hacks a game or obtains a not-readily-available program for cheating, it will often be
given to other members of the clan with the understanding that it's for clan use only and to be kept secret.
The purpose being, of course, to raise the standing and prestige of the clan. If the cheater is not a clan
member, odds are he will keep the secret to himself for a while and not advertise his advantage. The logic
here is simple: If anyone goes public with a cheat, a) he will lose his advantage, b) he will probably be
identified by his opponents as a cheater, and c) the developer can then patch the game, invalidating the
cheat. As a result of this secretive behavior we get to rule number three.
Rule #3: Cheaters actively try to keep developers from learning their cheats.
So how do they discover the hacks and create the programs to cheat at your game? Consider rule number
four:
Rule #4: Your game, along with everything on the cheater's computer, is not secure. The files are not
secure. Memory is not secure. Services and drivers are not secure.
That's right, you gave them a copy of your game when they purchased it. The hackers have access to the
same tools that you had while making the game. They have the compilers, dissemblers, debuggers, and
utilities that you have, and a few that you don't. And they are smart people - they are probably more
familiar with the Assembly output of an optimized C++ file than you are. The most popular tool among the
hackers I surveyed was NuMega's excellent debugger, SoftIce - definitely not a tool for the wimpy. On
another day, you just might be trying to hire these people. Many of them possess a true hacker ethic,
doing it just to prove it can be done, but more do it specifically to cheat. Either way we get the same
result: a compromised game and an advantage to the cheater.
Hacking games is nothing new, it's been going on as long there have been computer games. For single-
player games, it has never been an issue, since no matter what a player does with a game, he's only doing
it to himself (and therefore must be happy about it). What's new is bringing the results of the hacking to
other players, who never wanted or asked for it.
I've lost count of the number of developers I've encountered who thought that because something they
designed was complicated and nobody else had the documentation, it was secure from prying eyes and
hands. This is not true, as I learned the hard way. If you are skeptical, I invite you to look at the custom
graphics file format used in Age of Empires. Last year, I received a demanding e-mail from a kid who
wanted the file format for a utility he was writing. I told him to go away. Three days later he sent me the
file format documentation that he reverse-engineered, and asked if he missed anything. He hadn't. Thus,
this is a perfect example of rule number five. Yes, I've borrowed it from cryptography, but it applies equally
well here.
Sometimes we do things, such as leaving debug information in the game's executable, that make the
hacker's job easier. In the end, we cannot prevent most cheating. But we can make it tough. We don't
want effective cheating to be a matter of just patching six bytes in a file. Ideally we want hacking a game to
be so much work that it approaches the level of having to completely rewrite the game -- something that
goes outside the realm of any reasonableness on the hacker's part.
One of biggest things we often do that makes it easier for a hacker, and thus harder on us, is include Easter
eggs and cheat codes in the single-player portion of our games. Considered to be practically a requirement,
they expose extralegal capabilities of our game engines and make it much easier for the hackers to locate
the data and code that controls that functionality.
Most online games use one of two communication models: client-server and peer-to-peer. For our
discussion, the deciding factor is where game event decisions are made. If only one player's (or a separate)
computer makes game event decisions or has the game simulation data, it is client-server. If all players'
computers make some or all of the game event decisions, or have the full game simulation, then it's peer-
to-peer. Many of the cheating methods described here are applicable to both models. I've organized the
various cheats, trainers, exploits, and hacks that I've learned about into the categories listed in Table 1.
When aiming proxies for Quake first appeared a couple of years ago, their targeting wasn't too
sophisticated and didn't take into account things such as the player's field-of-view (FOV) or lag. Giveaways,
such as players shooting weapons out of their backs, tipped people off that something foul was afoot. One
of the first countermeasures to be developed was a server add-on that statistically identified players whose
aim was too good to be true, then kicked out and banned the perpetrators. This naturally proved
controversial, since some people really are "railgun gods," and the issue of possibly falsely identifying a
person as a cheater was raised (and has yet to go away). And of course, the aiming proxies evolved with
time. Later versions were improved to consider only the player's current FOV and compensate for lag, and
added just enough randomness in their aim to stay below a server's "too good to be legit" identification
threshold.
This big vulnerability is summed up in rule number six. Since the proxy is not running on the same computer
as the game client, definitive detection can be next to impossible. Making the development of the proxy
extremely difficult then becomes a priority.
Rule #6: Any communication over an open line is vulnerable to interception, analysis, and modification.
One way to inhibit this form of cheating is to encrypt the command packets so that the proxies can't
decode them. But there are limits to the extent that encryption can be used on communications. Most FPS
games can send and receive a couple of kilobytes of data or more per player per second, and have to allow
for lost and out-of-order packets. The encryption therefore has to be fast enough not to impact frame
rate, and a given packet's encryption can not be dependent on any other packet unless guaranteed delivery
is used. And once the encryption is cracked, the game is vulnerable until the encryption is revised, which
usually involves issuing a patch. Then the hacking starts over.
Another way to make life more difficult for the proxy creator is to make the command syntax dynamic.
Using something as simple as a seed number that's given to the game when it connects and a custom
random number function, the actual opcodes used in the communication packets can be changed from
game to game, or even more often. The seed itself doesn't have to be transmitted; it could be derived
from some aspect of the current game itself. The idea here is that since a proxy sees all the
communications, but only the communications, the random seed is derived from something not explicitly
communicated. Foolproof? No. But it's far more difficult to hack, forcing the hackers to start from scratch.
If guaranteed delivery is used, another communications protection technique is to serialize each packet.
Taking it a bit further, you could make a portion of the next serial number dependent on a checksum of the
last packet. While there are speed issues with the delivery, it's an excellent way to make it difficult to insert
or modify packets.
Though reflex augmentation seems to be exclusive to FPS games, the vulnerability extends to any game
where quick reflexes can make a difference and game communications can be sniffed.
The next major class of cheats is exploiting authoritative clients. This is when one player's modified copy of
an online game tells all the other players that a definitive game event has occurred. Examples of the
communications would be "player 1 hit player 2 with the death-look spell for 200 points of damage,"
"player 2 has 10,000 hit points," and so on. The other players' games accept these as fact without
challenging them and update their copy of the game simulation accordingly.
In this case, a hacked client can be created in many ways: The executables can be patched to behave
differently, the game data files can be modified to change the game properties on the hacked client, or the
network communication packets can be compromised. In any case, the result is the same - the game
sends modified commands to the other players who blindly accept them. Games are especially vulnerable
to this type of exploit when they are based on a single-player game engine that has been extended to
support online multiplay in the most direct (read: quickest to develop) manner.
Fortunately there are several steps that a game developer can take to eliminate most problems with
authoritative clients. A first step is to install a mechanism in the game that verifies that each player is using
the same program and data files. This means going out and computing a CRC or similar identifier for all the
data in question, not just relying on a value stored in the file or the file size. A nice side benefit is that this
method also detects out-of-date files during the development process.
For peer-to-peer games, cheating can be made difficult by changing from a game engine that issues
commands to one that issues command requests. It's a subtle distinction but one that requires engineering
changes throughout the game. It also requires that each player's machine run a full copy of the game
simulation, operating in lockstep with the other players.
Command processing in a single-player game typically works in the manner shown in Figure 1. The player
issues some sort of command via the game's user interface. The game then performs a validation check on
the command to see if the player has the resource, the move is legal, and so on. The game then performs
the command and updates its internal game simulation. Figure 2 shows game engine command processing
extended to support multiple players in the most direct way possible. The process stays the same except
for the addition of a communications packet that's sent out to inform the other players of what has taken
place. The receiving players integrate the data directly into their world simulation.
With the shift to command requests, the order of events changes a bit, which is shown in Figure 3. After
determining that the command is a legal one, a command request describing the command is sent out to
other players and is also placed into the player's own internal command queue, which contains command
requests from other players as well as his own requests. Then the game engine pulls command requests
from the queue and performs another validation check, rejecting the request if it fails. The fundamental
difference is that every player has a chance to reject every action in the game based solely on the
information on that player's machine. No other machine provides the information to make the
determination on what is right and wrong. A hacked game cannot reach out and alter what's on an honest
player's machine with this approach. Note that such an architecture works equally well for a single-player
game.
Preventing a dishonest command from being accepted on an honest player's machine is only half the task.
The game also has to be able to determine whether someone is playing the same game and if not, it must
do something about it. For instance, when a received command request is rejected for reasons that should
have prevented it from being issued in the first place (remember, the issuer is supposed to have checked it
for validity before passing it to the other players), all other players should assume that a cheater is in their
midst, and take some sort of action.
Often though, due to design issues (such as posting command requests to a future turn), it is not possible
to thoroughly ensure that all command requests passed to other players won't be rejected if a player is
being honest. A good way to deal with this is to add synchronization checking to the game. At various
points during the game, each player's machine creates a status summary of the entire game simulation on
that computer. The status, in the form of a series of flags, CRCs, and checksums, is then sent to all the
other players for comparison. All the status summaries should be the same, provided the game program
and data files are the same for each machine. If it turns out that one player has a different status from all
the rest, the game can take action (like drop the player from the game). The idea is that a hacked game
should cause that player's game simulation to produce different results.
Alternatively, you can make life even more difficult for the hacker by easing up on the received command
request evaluations. By allowing command requests to bypass the verification check only on the machine
that issued it, you're deliberately allowing the game to go out of synch if the initial verification check or data
has been hacked. Combine this with a synchronization check that occurs somewhat infrequently and you've
presented the hacker with something of a mystery -- on his machine the cheat worked, but then a while
later the other players booted him out of the game.
This status synchronization has a huge benefit for the development process as well. Getting a complicated
game engine to produce the same game simulations results while having different player views, inputs, and
settings is a very difficult task. It's difficult to keep the simulation-independent code from accidentally
impacting the simulation. For example, a compare against the current player number variable in the
simulation code, or randomly playing a background sound based on an object in the player's view using the
same random function used by the simulation, could cause future executions to produce different results on
different machines. Judicious use of status synchronization allows a developer to quickly narrow down the
portion of the game that isn't executing the same for all players.
Client-server games unfortunately can't benefit as much from these techniques, as they lack full game
information and by design must rely on the authority of the server. We will look at this more a bit later.
The next major class of cheats is what I've dubbed "information exposure." The principle is simple: On a
compromised client, the player is given access or visibility to hidden information. The fundamental difference
between this and authoritative clients is that information exposure does not alter communications with the
other players. Any commands sent by the cheater are normal game commands - the difference is that the
cheater acts upon superior information.
The first-person-shooter cheats of modified maps and models arguably fall under this classification, as they
let cheating players see things that they normally wouldn't be able to (in the case of modified maps), or see
them more easily (in the case of a modified player model that glows in the dark). Any game whose game
play relies on some information being hidden from a player has a lot to lose to these types of cheats.
The real-time strategy (RTS) genre suffers severely from this. The most obvious being hacks that remove
the "fog of war" and "unexplored map" areas from the display. With a fully visible map, the cheating player
can watch what other players are planning and head them off at the pass, so to speak.
There are a couple of ways the hacker accomplishes this. The hacker may go after the variables that
control the display characteristics of the map. With the help of a good debugger and single-player cheat
codes to reveal the whole map, finding the locations in memory that control the map display is fairly simple.
Then either the game .EXE file is modified to initialize those map control values differently, or a program is
made that attaches to the game's memory space and modifies the variable values while the game is
running. To combat this, the values of those variables should be regularly reported to other players in the
form of a checksum or CRC code. Unfortunately, that only raises the stakes; the hackers then just attack
the code that reads those control values (easy enough to find quickly), inverting or NOP'ing out the
instructions that act upon them.
Additional techniques are needed to detect the hacked game view. There are a couple of ways to take
advantage of the fact that the full game simulation is run on all clients. One way is to borrow a technique
from the "authoritative client" section and check each command request for the side effects of a hacked
map on one of the players. We specifically ask the game simulation, which is separate from the screen
display, the question, "Can that player see the object he just clicked on?" In doing this we are assuming
ahead of time that such hacks will be attempted, making sure we consider the side effects by which they
might be detected. Once again, easing up on checks of the player's own machine is very useful. The next
time the game performs a synchronization check, all the other players will agree that the cheating client is
"out of synch" with the rest of the game and can deal with him accordingly.
Another technique that avoids looking at the display control variables is to compile abstract statistics on
what gets drawn to the screen. The statistics are derived from the game simulation data and just filed
away. This doesn't immediately prevent the hacker from cheating; instead, you send the statistics around
as part of the status synchronization and see what the other players think of them.
In the RTS map-hack case, it is necessary for some change to be made to the game; either the code or
some data is in a modified state while the game is running. And if something has been modified, you can
attempt to detect that.
But information exposure cheats can be totally passive. Consider a scenario where a program gains access
to the memory space of an RTS game that is running. It then reads key values for each player in the game
out of memory and sends them to an adjacent networked computer. An industrious hacker once raised
that scenario with me regarding one of the Age of Empires games, saying he had figured out how to read
out of memory the resource amounts for every player. At first we thought that this wasn't very serious. He
then explained that if he polled the values a couple hundred times a second, he could identify nearly every
discrete transaction. A simple Visual Basic program could then display a log window for each player, with
messages for events such as the training of various units (to the extent they could be distinguished from
others on the basis of cost), and messages for events such as building construction, tribute, and
advancement to the next age. Basically, this cheating method was the next best thing to looking over the
shoulders of his opponents.
Rule #7: There is no such thing as a harmless cheat or exploit. Cheaters are incredibly inventive at figuring
out how to get the most out of any loophole or exploit.
Intrigued, I asked him how he could be sure he had found the correct memory locations each time, as they
changed each game since they were stored in dynamically allocated classes. His answer was most
interesting. He first scanned the memory space of a paused game looking for known values for things such
as population, wood, gold, and other very significant game values that he knew about and believed were
unique. He had a simple custom program that looked for the values in basic formats such as long ints and
floats. After his program identified all the possible addresses with those values, he ran the game a bit more
until the values had changed. He then reran the program, checking the prior list of locations for the new
values, reducing the list of possible addresses until he was sure he had found the correct locations. He then
put a read-access breakpoint on the value and looked at how it was accessed from various points in the
code. At one of the breakpoints, the C++ code for accessing the wood amount looked something like this:
This is a pointer to a pointer to an object containing an array of integers, one of which contains the value of
the player's current stockpile of wood, and all the objects are dynamically allocated. The hacker's point was
that if you trace back through all the dynamic pointers, you eventually find a static variable or base pointer.
The different spots where his breakpoints were triggered were from member functions at different levels in
the class hierarchy, and even from outside the class hierarchy containing the data. And it was finding an
instance of that latter access condition that was the jackpot. There it was in his debugger's disassembly
window: a base address and the Assembly code to traverse through the classes and handle player and
resource index numbers.
Considering all this, I found a couple of strategies that can greatly reduce the likelihood of this sort of
passive attack. Again, these tips cannot guarantee 100 percent security, but they make the hacker's job
much harder.
The first strategy is to encrypt very significant values in memory at all times. Upon consideration, most
game variables are not significant enough to warrant such protection - the hit points of a particular object
don't tell anyone much, while a drop of 1,000 food and 800 gold from a player's resources does indicate
that the player is advancing to the Imperial Age, which is an event of large strategic importance in our
game. Simple encryption is relatively easy when all access to the variables goes through assessor functions.
A communicative function such as XOR is your friend here, as it alters values upon storing, restores them
upon reading, and is extremely fast. The whole point is to make it very hard for the hacker to find the
variables he is searching for in the first place. Values the hacker would know to look for are not left around
so that a simple scan can find them. In C++, our encrypted assessor functions for game resources look
something like what's shown in Listing 1.
The second strategy for slowing down passive attacks is to never access very significant values from
outside the class hierarchy. Assuming the values are located while using the debugger, try not to access
them in a way that starts with a reliably fixed memory address. Combining this with small, randomly sized
spacing buffer allocations during the main game setup ensures that the memory addresses for vital
information will never be the same from one game to the next. A piece of C++ code you won't see in our
next RTS game would be the following:
Information access isn't limited to games as complex as RTS games, it can extend to something as simple
as a card game. Consider an online card game such as poker. All it would take to ruin the game is for a
player to see the values of the face-down cards in another player's hand. If the information is on the
machine, hackers can go digging for it. This goes back to rule number four.
In client-server games, because so much is controlled by the server, the game is only as good as the trust
placed in the server and those who run it.
An issue here is brought up because some client-server games can be customized by the user running the
server. Access and configurability are great for many games, as they allow the player community to extend
and evolve a game. But some individuals will test the server to see what can be exploited in the name of
cheating. This in itself is not the problem -- rather it's when honest but unaware players find their way to
the server and don't know that they are not on a level playing field.
You really need to consider your audience here. A successful game will sell hundreds of thousands of copies,
if not millions. You as a developer will be most in tune with the hard-core players -- those that know the
game inside and out. But it's easy to forget about the more casual players, who probably will be the
majority of purchasers of your game once you pass a certain level of success. These are the people who
don't know to check the status of the Cheats_Allowed flag before joining a server, or that game rule
changes are transparently downloaded when they connect. All they probably know is the default game
configuration, and when they see their ReallyBFG27K gun doing only 0.5 points of damage, they're going to
cry foul. It doesn't matter that it was technically legal for the server operator to make the change, you still
wind up with a user that is soured on the game and not likely to recommend it to his buddies anymore.
Naturally, people get a whole lot more unhappy with a game when they encounter modifications with
malicious intent. What if a clan decided to add a tiny server mod to their FPS server that looked something
like this snippet of C code:
Or what if the remote console was hacked to allow normal cheats to be toggled? Dishonest players in with
the server could make a key-bind that resembled this:
Access_password on; set Cheats_Allowed true; Give Big_Ass_Weapon; Give Big_Ass_Ammo; Set
Cheats_Allowed false; Access_Password off;
The important point here is that with user-run servers and powerfully configurable game engines, these
kinds of shenanigans will happen. While we as developers can't protect our more casual users from joining
any game server they wish, we can do a better job of letting them know when they are encountering
something that could be different from what they expect. Quake 3: Arena set a great example when it
introduced the concept of a "pure" server. It's a simple idea that casual users can quickly grasp and set
their gaming expectations by.
But why stop there? If we download data that includes a new set of weapon properties, why not put a
message on the screen saying, "Weapon properties modified"? If single-player cheat commands are issued
in the middle of a game, maybe we should send a message to every client notifying them of that fact, so
even players who aren't near the issuer can be made aware. Empower players to easily determine whether
the games are fair or not.
Rule #9: Honest players would love for a game to tip them off to possible cheating. Cheaters want the
opposite.
Technically, this category of cheats is one that we bring upon ourselves: bugs in our games can be
discovered by users and used to disrupt game play. Most bugs don't enable cheating, but a few do.
A good example is the farm-stopping bug in the unpatched version of Age of Empires. When a user had
both a villager and a farm selected, he could issue the Stop command. Because the command was valid for
a villager, it was allowed to go through, but listed both objects as the target of the command. The villager
would stop working as expected and reset its state. The farm would also reset itself, something it never did
normally, and replenish its food supply. Once this was discovered by players, it drastically changed the
game for them, giving them a huge advantage over those who didn't know about it.
I encountered another bug when playing Half-Life. I would get into a firefight with another player, both of us
using the same weapon, but when it came time to reload our weapons, my opponent was able to reload
much more quickly than I could. Sure enough, when the next patch came out, I saw in the release notes
that a bug allowing fast reloads was fixed. There's really not much we can do about these types of bugs,
other than fix them with a patch.
Environmental Weaknesses
My last category of cheats is something of a catchall for exploitable problems a game may have on
particular hardware or operating conditions. A good example is the "construction-cancelled" bug that was
found amazingly in both Age of Empires and Starcraft at about the same time. The element needed to
make it work was extreme lag in network communications, to the point of a momentary disconnection.
When this happened, the game engines stopped advancing to the next game turn while they waited for
communications to resume. During this time, the user interface still functioned, so the player didn't think the
game had locked up. While the game was in this state, a player could issue a command to cancel
construction of a building, returning its resources to the player's inventory - only the player would issue the
command over and over as many times as possible. Normally, a player could only issue one Cancel
command per turn, but because the game simulation was in a holding state, multiple command requests
went into the queue. Because of some necessities of RTS engine design, when an object is destroyed during
a turn by something such as a Cancel command, the destruction is postponed until after all the commands
for that turn have been processed. The result was the command executed multiple times during one game
update.
Once discovered, this had a horrible impact on online games. People deliberately caused massive lags to
take advantage of the cheat. To fix it in Age of Empires, we had to update the validation checks to see if a
similar request was already pending on the current turn and reject duplicates.
Another bug of this type involved the game Firestorm and its interaction with the Windows clipboard. It
seems a clever user found out that if he pasted text from the clipboard into his chats and that text
contained a certain character not normally used, the game would crash when it attempted to print it to the
screen -- on all player's machines. He then treated this knowledge as a personal nuclear bomb that he
could spring on people when he found himself losing.
Yet another example taken from Age of Empires is what happens when a player's network connection is
overloaded or ping-flooded by another player. When such an attack renders a game unable to
communicate with its peers, the other players decide that something is wrong with that player and drop
him from the game- - a totally necessary capability, but one that can be exploited in a modern twist on
scattering all the pieces on a game board when you are losing. This was one the major reasons we added
Multiplayer Save and Restore capabilities to Age of Empires II.
I hope these examples got you thinking about some of the problems and issues at stake when developers
address the problem of online cheating. We certainly have a lot more ground to cover, from massively
multiplayer games, open source, and consoles, to enabling the online communities to better police the
situation. But we're out of space and time for now.
Listing 1. Hiding the variables that tip off hackers to possible cheats.
Matt Pritchard is busy trying to be a modern renaissance man. When not working hard on his
latest game, he can be found spending time with his family or collecting antique videogames. Send
e-mail to mpritchard@ensemblestudios.com.
Basics
Debuggers
Debuggers allow crackers to trace an
application, instruction by instruction,
and to stop it at any point and trace its
important sections. It is true that
applications written in higher level
languages (like C++, Visual Basic, or
Delphi) may be traced only in
Assembler, but crackers understand
what is happening in the application
code amazingly well – probably better
than most people can imagine. The
truth is, the higher the level the
programming language is, the more
difficult it is to trace, but on the other
hand they offer fewer possibilities for
creating really good protection.
Everything has its bright and dark
sides.
Disassemblers
Disassemblers or decompilers can
translate an application code back into
Assembler, no matter in which
language the application was originally
written. Decompilers translate only
applications written in those languages
for which the particular decompiler
was created. There are, for example,
decompilers for Delphi, Visual Basic
and Java. If the decompiler is really
good it can translate the application
very well. Once an application is
translated it’s easy for the cracker (if
he knows the particular language) to
find sections of interest to him and to
determine how they work. One
advantage that disassemblers offer
over decompilers is that they always
translate into Assembler so the cracker
has to know only that one language.
The resulting translated code depends
on the quality of the disassembler or
decompiler. The best decompilers
even comment on the translated code,
which makes the code that much easier
to understand. For example, if the
cracker finds a ”Wrong serial number”
string and locates its place in the code,
he will be able to find the part of the
code that protects the application. At
t ha t point, nothing can prevent him
from studying the protection and
breaking it.
Cracking Tools
Anti-Debugging, Anti-Disassembling
and Other Tricks To Improve
Protection
Detect tracer
here
old times
Enabling the overflow bit in eflags and check it by "into". This causes overflow
exception (interrupt 4 redirected to own handler).
Ring0 here
Small routine for detection the type of Windows (useful for anti-debugg tricks).
StopIce here
CRC32 here
CD-Check here
Example of CD-Check.
© 2001 AntiCracking. All Rights Reserved.
Protecting your programs from piracy
INTRODUCTION
At one Web site I’ve seen a curious discourse, whether your programs should be furnished with anti-pirate devices. It went
like this: No one has a right to enter your house without your consent. The inviolability of your house is protected by law.
Nevertheless, you prefer to have a lock in your front door. Further proceeding with this comparison, we’d have to admit
that after putting a lock on the door many software authors leave their keys at the front door or they lock a wrong door at
all.
This article is intended for those software developers who do not professionally engage in issues of protection from
any unauthorized usage. It’s aimed at pointing out the most typical mistakes and helping to create more
impregnable software.
Discussed here are the issues of creation of shareware and trial versions for Windows’95 (and Windows NT, if stated
so). Leaving specific examples aside we can say that everything that is mentioned below is true for other platforms,
too.
This article does not claim to cover the problem in its entirety.
You can contact the author at vitas@ webdon.com. Even if you don’t have any specific suggestions or notices just
send in your opinions about this article. This article may be continued in future, so please give us your opinion about
this, too.
There exists an opinion that hackers are unique specialists and they can be fought only by specialists like them, yet an
ordinary software developer is unable to do it and he shouldn’t even try to. Therefore you shouldn’t try to protect a
program from a break-in, because it wouldn’t save from a hacker and you should only create a simple fool-proof
protection. Meanwhile, as unexpected as it may sound, a typical hacker is not in any way an able specialist; he cracks
programs because he is unable to do anything else (a proverb «It’s easier to break than to build?is true to life!). If you
weren’t seriously into illegal copy protection (don’t waste your time if you were – in this case, this article is not intended for
you) then you are going to discover a number a number of simple, logical and very efficient ways of increasing your
programs’ reliability upon reading this article (at least, I hope so). Well, of course, there are skilled professionals among
hackers, and they could do a lot. The methods which are described here would not stop them. Nevertheless, if reading this
article helps you to improve your program in a few hours well enough to repel a lot of pitiful hackers – it is not so bad, is it?
SHAREWARE programs.
There are two big problems concerning unauthorized copy protection of shareware programs. The first one is how to
prevent a hacker from turning a shareware version into a complete registered one. The second one is a copy protection of
a registered program, that is how to arrange that only the legal owner could use a registered copy. This second problem is
going to be touched upon in the end of this article as it requires a greater separate discussion.
When offering a shareware version of his program an author pursues two goals. On one hand, he wants to get a
potential user interested therefore a program should demonstrate all of its options and be as convenient as possible.
On the other hand he wants to make a user pay for the program. The folowing methods are the most popular ones
for creating shareware programs.
A demo program.
A potential user is receiving an «inferior?program with some options completely missing, Having tried it, he’s buying a normal
version in a usual way. The determining fact here is that there is no way even in theory to turn a demo version into a complete
program. I’m mentioning this choice here, yet I’m not going to discuss it. Sometimes demo versions are made via introduction of
some limitations in a complete version whereas a theoretical possibility to do away with these limitations remains. Let’s
have a look at two examples. A phone directory demo version contains phone numbers from just one phone station.
No hacker can ever turn this demo program to a full-scale phone directory. Another example is a demo version of a
graphics editor, which won’t allow you to open images greater than any predefined size. It is very probable that a
hacker may quickly remove this limitation. The difference between these two examples is that a phone directory has
a part which is totally missing from it. On the contrary, in the second example there is a removable «extra part?
Incomplete functionality
A shareware version does not include some useful functions which only appear after the registration. It’s very
important to determine what functions are going to be inaccessible during the trial period. At the present time the
software market is extremely satiated. For most of the programs there exists an alternative by a competitor. So, if
you deprive a user of many useful functions he may not want to try your program any further and buy it. It is well
known that, when meeting a new person, one’s attitude to him (or her) is formed during the very first seconds of
the acquaintance. The same thing happens to items and programs – it is very important that your program
impresses a user as much as possible. Therefore, the missing functions must be useful but not essential for the first
acquaintance with the program. Moreover, these functions must be evident and intuitive, that is, a user should
clearly see what exactly is going to be at his disposal after the registration and how convenient his work is going to
be. During the trial period a user should get used to your program, get familiar with it and want to use its at its full
power and at any time. Therefore a choice of options to be removed for the trial period is very important.
3. Annoying behavior.
During the trial period a program does something to annoy a user but not to prevent the usage of all options of the
program. Usually it is a reminder about a necessity of the registration. A good example is a popular WinZip program which
recommends to register itself after every launch. This variant differs from the first one by the necessity to «add?
something in case #1 and the necessity to «remove?something in case #3. It is evident that the third method is
outperformed from the point of view of reliability.
4. Registration info.
This option is intended for honest people – a program would just inform them that it is not registered yet or who it is
registered for (on-screen, in a demo or in an About box). This way of protection is present almost in any program, but
usually it is not the only one.
5. Upgrade.
A new version of a program should allow using itself only if a previous version of this program is already installed.
Program registration.
How a program is being registered? Of course there exists an option that, upon paying for the program, a user will receive
a new (or complete) version in a glossy box bundled with complete documentation, possibly delivered by a parcel service.
In this case we’ll have to speak about a demo program which is followed by a purchase of a complete version, yet we
have decided not to discuss this case. Another drawback of this method is that a user does not receive a result
immediately following a money transaction (for example, paying on-line with a credit card), having to wait for it several
days (at best). Moreover, an Internet program distribution without traditional boxes, floppies and manuals allows to cut
expenses down and to increase efficiency, which is so important for various utilities and other inexpensive programs. Upon
a registration a user is naturally supposed to receive something that can turn a program into a registered one from a
program manufacturer. Ususally this something is a registration number, but let us understand it widely – it does not have
to be a number, it is a piece of information given to a user by a program distributor. Given a chance, you should make this
number readable and not too long. Consider, for example, entering such a registration code:
04846718351B3E6B3D717E240A200A29556B7C18347A1162526F5CThis real-life example (well, maybe almost real-life :-) ) is a
registration number from a program named GoldEd. You should make it more readable, that is, use only digits and
separate groups of digits with optional separators, like this: 214-527-822-655-121. If a program is registered on-line then a
problem sorts itself out because a registration process can be automated.
In case of limitations that are imposed on period of program usage or times a program had been launched some specific
cracking methods become available not only for hacker, but for smart users, too. One of the ways to cheat a protection
goes like this: before installing the program it is necessary to set a date several years ahead, for example, at 12.31.2017.
Let’s say your program only works during two weeks after having been installed. Then it’s protection system would decide
the program is supposed to work till 01.14.2018. Having installed the program, a user reverts to a correct date and uses
your program till the end of the world. How could one counter such a method?
The first palliative is to check a current date and, if it is too big (say, more than six months since program release),
suggest to use a newer version. A more radical way is to check a current date every time a program is being launched. If,
suddenly, it turns out that a current date is lesser than the installation date, then… At this point you may be tempted to
display a message which accuses the user of cheating and maybe even to uninstall a program. DON’T DO IT! The user’s
system might just have a time failure. Alas, if a time failure did happen, your program will stop working short of its time.
This is a rule of thumb – increasing protection reliability leads to increasing your program’s discrimination. A program can be
made to behave a bit smarter – if system time is lesser than the program release time then the system clock has really
failed, because when a failure occurs a date is often set to 1.1.1980. In this case you can suggest a user to correct the
system clock.
The second way of cracking lies in setting a wrong date at the runtime and restoring a correct date afterwards. Of course,
this way is a bit awkward, but, unfortunately, there are programs which help to automate this process. It is extremely hard
to counter this method. You can try the following ways to do it.
It is a radical way which can be afforded only by developers of Internet-based programs. Since a user is supposed
to work online, your program can get a current date and time from a server that provides with exact time and date;
there is quite a lot of them now. At the same time your program can do a good service by synchronizing the
system’s time and date if they are set incorrectly.
Unfortunately, this way is acceptable for very few programs. It can be slightly modified; if a computer works in a
local network, a date can be obtained from a server or from other computers.
If this way is unacceptable, either, we have to admit that without leaving the bounds of a computer, there is no way
your program can find out what date it is. Yet, a fact of altering a date still can be detected. Many programs, for
example, record their relevant information into the Registry. For this reason, the registry modification date usually
matches the current date. When Windows is started, the system creates backup copies for the files
c:\windows\system.da0 and c:\windows\user.da0 (these files are marked as the hidden ones).
You can check the date of their last modification and, if it turns out to be greater than the current one, then a user must
have set the clock to an earlier date. It is important to check the backup Registry files because the current registry files
may already have been modified and therefore their modification date may match the current wrong date. Evidently you
can not only check the Registry files like this, you can also verify your own data files. Here’s how a real current date may
be obtained: as you may or may not know, Windows’ 95 not only stores the creation date/time for each file, it also stores
the time and date of its last access. As a true current date you can consider the last access time of a file which is always
launched or opened once when Windows start up. Autoexec.bat or windows\system\vmm32.vxd may serve as examples of
such files.
The third and the last way of protection that we are going to consider consists of installation and uninstallation of a
program. Modern programs usually have convenient setup utilities which install and deinstall programs. As a result, it may
be not burdensome at all to perform a simple installation procedure once a month. There are different methods to fight
this method. If, for example, your program requires a great deal of setting its options, you can arrange it in such way that
uninstalling a program would cause all options to be lost and a program would have to be set up again after the repetitive
installations. A more radical solution would be to leave a mark in a computer (in a Registry, for example) which would state
that a program had already been used on this computer and to refuse to install a program if such a mark exists. Indeed,
your program would have to be a true perfection so that a user would want to reinstall Windows just to be able to use it.
Should I mention that this mark must not be removed by an uninstaller, it should not be located close to other settings of
your program and the last, but not the least: use your imagination! If your program is named CoolApp.exe, do not name
the register key for its mark as CoolAppWasHere! An alternative of using the Registry may be a small DLL in the Windows
directory which an uninstaller does not remove.
If there is a limitation of a launch count, then a counter must be decremented after each launch. (It may be incremented
– this is totally irrelevant for us. Let’s suppose it is decremented, just to be certain.) It is very probable that this counter is
located in the Registry or in an ini.-file. At times, it’s just amazing to see how clever people who are able to create brilliant
programs show miraculous narrow-mindedness and name this counter, for example, iTimeSpan, like it is named in the
FineReader program. Name this key variable, for instance, RAS32stub and make its value equal to the remaining launches
count with a checksum, encrypted in any code, even a trite XOR. Although this may not help you a great deal – if a
hacker finds the counter, he can just restore its original value every time. A radical remedy which is acceptable for
Internet-based applications is keeping your counter on a server instead of a local computer.
It is possible to store into a parameter a checksum of the remaining parameters, including the counter itself. In this case
all the settings of the program can only be restored together.
You can try and hide the counter outside the Registry, because this location is too evident. You can come up with an
impressive name for an .INI file (which, by the way, may have an extension other than «INI.?, stuff this file with a load of
settings with intimidatingly complex names (the counter is to be one of them), place it in the Windows directory, and, more
importantly, every time you decrement the counter, you should forcefully set the same date for this file, 08.24.95, for
instance. I hope you have been already influenced by the anti-hacker spirit and understand, why I’m suggesting you to
use this date.
Comparing the time-of-usage and launch-count limitations we’ll have to admit that the second option is less reliable because
of the necessity to keep a constantly changing counter which can be found with relative ease.
Suppose a registration process involves sending a registration number as a response to a user name. All too often, just
after a program is released a key generating program appears. Such a program is able to generate a registration number
for any given user name. Meanwhile, it is not hard to arrange everything in such way that creation of key-generating
programs would be completely impossible. To accomplish this, it would be sufficient for you to use a simple asymmetrical
encryption algorithm. You can find a lot of information about asymmetrical encryption algorithms, often dubbed as open-
key systems, for example, at www.rsa.com. To put it in a nutshell, asymmetrical encryption algorithm is a way of coding
information which requires one key for the encryption and another one for the decryption, yet it is impossible to obtain both
of the keys, knowing just one of them. As a rule one of the keys is made as an «open?one (which one of them it is
depends on the purpose of their usage), that is, a commonly known key, the other one is kept as a secret. Now consider
this: a registration number is a user name which is encrypted with an asymmetrical encryption algorithm, and the
encryption password (a key, that is) is known only by you. A program would perform the verification by decrypting the
registration number (the decryption key is built into the program) and comparing the result with the user name. If such an
algorithm is used correctly, it is totally impossible to create a key generating program. It has to be noticed, however, that
the aforementioned way of protection will not prevent from using someone else’s key and from cracking by modification of
program code. This method is essentially an electronic signature with a registered user name by the program’s author.
Most of modern commercial (non-shareware) programs require entering a serial number during the registration. This would
pose no problem for a legal user – the number can be found in the program package, and could pose a problem for an
illegal one (if we aren’t talking about a pirated CD, that is, because thoughtful pirates often place a file with a required serial
number on the same disk). A serial number has to satisfy several criterias therefore a random number will not work. Yet all
too often an implementation of checking the number validity cannot stand any criticism. For example, most of Microsoft
products can be satisfied with a number which consists only of 1’s. Here’s a method of verification which can be advised
(actually, there can be quite a lot of options): the first part of the serial number is encrypted (even in the most primitive
way), the result checksum is calculated and then a remainder of division of checksum by some number X is calculated.
The resulting remainder should match the second part of the checksum. No matter what kind of verification you use, at
least it should not miss banal numbers like all zeros or all 1’s. It would be a good idea to provide a link between a serial
number and a program name and/or version to make it impossible to use serial numbers from one of your programs with
another one. One quite successful brand of this method of protection is a method which requires entering word # N from
page # M from printed manual which should be provided with the program in this case.
Here’s a bit about upgrades. A newer version of a program which allows to be used only if there is a previous version of
this program already installed on the computer must have some mechanics that scans for the previous version. In a likely
way Windows-95’ upgrade requires presence of Windows 3.1 during the installation. Yet, alas, all of the verification consists
of checking for presence of a file windows\system\win386.exe. It is enough to create a file with this name (you can even
make it 0 bytes long) and Windows ’95 can be installed on a computer where there is no and has never been Windows 3.1
present. Hence the verification should be a bit more complex. For example, an upgrade version of a program may
purposefully omit setting several options in the Registry, provided they match those in the previous version. It is possible to
come up with a lot more of highly reliable methods.
Very often hackers turn a shareware program into a full-scale working one, having changed just one byte in its code and
having spent just a few minutes. How do they do it? How do they manage to find a right place in a multi-megabyte
program and spend less than a minute on this search (this is genuine time it takes, not an exaggeration)? The matter of a
fact is that authors of programs seem to do their best to help hackers in their work. Let us discuss one very typical
example. Suppose your program goes something like this:
BOOL isRegistered() {
...
return TRUE or FALSE; /* this function may determine if this program is registered or not, basing on
some probably very complex and perfect criteria
*/
....
if(!isRegistered())
// here’s a verification of being registered when performing some useful functions if(isRegistered())
doSomethingVeryUseful();
else
MessageBox(“Unregistered copy! This function is available for registered users only!”);
....
//there’s a lot of such tests, and they are stuffed all over the program in various modules
The most funny thing about this is that many authors actually find this kind of protection very reliable. Well indeed, the
isRegistered() function is very complex and the verifications are scattered all over the program in abundance.
What is a hacker going to do to such a program? That’s right – he will just find a string, for example, «Register please!?
and get its address. Now it’s not hard to find a piece of code like this one:
or eax, eax
jnz yyyyy ; *
...
....
Now he is going to alter the only byte in the code, the one marked by an asterisk and there will be no demand of
registration any more. Sometimes it’s enough to put a period here. In this case the time of hacking can be measured in
seconds. Yet we are examining a more complex sort of protection – this testing is performed repeatedly. Get rid of an
illusion that a hacker will try to find all of its occurrences (although it is not that difficult). He is merely going to alter a few
starting bytes of a function IsRegistered in such way that it is always going to return a TRUE value. This function may
implement the most brilliant and the most reliable algorithm – but who needs it now?
Pondering over this given example we can reach two conclusions. First, the hackers’ task would get much more difficult,
had he not found this place in the program so easily. Secondly, we cannot live with the fact that there is a theoretical
chance to break a program by replacing just a few bytes. The right place was found only because the right string was
found. Of course, this is a specific case. Instead of text there could be a resource id, if a message is stored as a text
resource or a dialog box. There could be some distinctive number. Suppose an unregistered modification of your program
limits some of its setting by 20. In this case a hacker might be looking for the code
cmp <something>, 20
To hamper the search of the necessary place for a hacker you should diguise such critical segments. Text strings (such as
messages, filenames, Register key names etc.) should be encrypted for storage (in any, maybe even the most primitive
way). The telltale constant numbers should be disguised like this:
...
Besides, the verification is not to be carried out in the very beginning of a program. It is preferable to have several testing
procedures and perform them repeatedly. You can create a separate thread which performs such necessary check-ups
periodically.
Let us take a more global look at the problem. How to achieve that your program theoretically cannot be broken by
altering just a few bytes? Yes, it is possible. Consider an example:
struct VeryImportant {
/*
Collect all the constants you use in functions which are not available for unregistered users into this
structure. Accordingly, in the functions themselves use the constants upon retrieving them from this
structure. For example, instead of a = b + 2;
write a = b + myconst.two;
Let there be just a few of your constants. They are going to be important and non-ordinary, if possible. A
pointer to a function can be used as a constant and, if necessary, this constant can be used to call this
function by this very pointer.
*/
} myconst = { xxxx };
/*
Here is the most cunning part. xxxx are the constants we need, encrypted in some algorithm. Do not re-create anything
that is well-known, use a professional algorithm, for example, rc2 or rc4 – they are not complicated at all. The necessary
values may be read from a file, a resource or extracted out of a Registry (where they are put by an installer). The last
option is the most attractive one.
*/
....
BOOL IsRegistered()
{
}
....
//this is where the registration number or zeros, if the program is unregistered, are stored.
.....
void initProtection()
{
// now we decipher our constants with the registration number (or, rather, with its part)
decrypt(&myConst, regNum);
// The following part may be just like the one in the previous example.
Even now a hacker may find the function IsRegistered(). Now modifying it will only make your program stop working,
because the constants which are located in the structure and are necessary for the work cannot be deciphered without the
registration number. In other words, you should follow a simple rule – a value being verified should be used instead of
being compared to a constant. So, we do not check for a presence of a registration number, we use it. Nowhere in a
program a hacker may find what value this number should have. Let’s view one more example of this concept’s usage.
Suppose an unregistered modification of your program allows not more than 40 records in some database. To simplify the
matter we suggest that each user is described by a structure named CUser, and the database is just an array of the
CUser structures. Usually there is something like
...
cmp <???-??>, 40
Having learned the aforementioned, you can make his life a bit more complex in this way, for example:
CUser *array;
void initUserArray()
{
int x = -83, y = 3;
array = new array[(x+y)/-2];
...
In this case, even if a hacker finds the verification (marked by an asterisk), he is going to get himself some very
unpleasant and hard-to-find range check errors when the quantity of records exceeds forty.
It is harder to implement a protection if an unregistered program is supposed to display reminders. This variant is different
in that a hacker is supposed to remove an «extra?to get a full-scale working version, not to add a missing function. To
break is easier than to build, and this applies to this case, too. You can protect your program from cracking to some
extent, if your program does something minute but necessary for your work when displaying a reminder. For instance, a
reminder is implemented as a dialog box. When the WM_INIT message handler (dialog initializer) is executed, a timer can
be set to one second. And when the WM_TIME timer handler is executed, you can initialize some necessary variables or
perform another action which is necessary for the further work. If a hacker finds and suppresses the window output,
simultaneously he renders the program inoperable.
Another evident way to protect your program from cracking is to check its integrity. For example, your program can count
its checksum upon loading (the checksum of a file, not in memory). Although this cannot boost the speed of operation in
any way, it can also help you to locate a virus infection or a violation of a program’s integrity which can occur during the
program’s transfer via communication channels. It has to be kept in mind that, generally speaking, the integrity verification
cannot guarantee the integrity itself, because a hacker may remove the verification subroutine itself. This is where the
«chase?begins, whoever succeeds first. The integrity verification can be logically tied to a digital signature of a program
(a.k.a. its certificate). There has been written a lot about it, so we won’t talk about it here.
Copy protection.
Let’s address another problem now – how to prevent a distribution of the registered program? Generally, its a problem of a
«traditional?copy protection. There is a lot written about it. Listed below are the most popular ways of protection.
Key disk.
This way of protection is practically not used any more. Firstly, it is very inconvenient for a user, secondly, it is unreliable
because of unreliability of disk as an information medium. By the way, a common belief that this method is unreliable
because any disk can be copied with a special program, is not true.
Electronic key.
Aside from some apparent benefits, this method also has its disadvantages. Usage of two programs protected this way on
one computer may turn out to be problematic. Because of a sensible cost, this method may be inappropriate for
inexpensive programs. Besides, this method is only potentially reliable. In practice, however, we may encounter some very
clumsy implementations (here’s a specific example: a verification function is located in a separate DLL and returns a
true/false value «key present/ key not present?
Hardware binding.
Binding a program to equipment seriously limits a user, because a computer upgrade becomes impossible.
Software binding.
This binding may not be evident because program which has a complicated installer that carries out a large preparation
work (entering settings into the Registry, installing common DLLs into the system directory, registering ActiveX controls)
essentially binds a program to a specific copy of software installed on your computer.
Conclusion.
If your program is distributed on CDs and its volume is not too big (that is, a program does not take up a whole CD), than
you may consider filling the free space with the information which is needed for the installation. If you do it skillfully enough,
than pirates would have a question arisen – is it worthwhile to issue a CD which is completely dedicated to your small
program?
Well, pirates strive to place as much of different programs on a CD as possible, in order to increase the quantity of
potential buyers. Your program may be small, yet have a bonus pack of useful, yet non-essential programs included with
it. Pirates can easily «crop?your distribution package, therefore your installer should check for the presence of this extra
information. You can also check if some files or directories previously absent from an original package have appeared on a
CD.
And, just a little notice in conclusion. You can dramatically increase your program’s fortitude, yet it is going to take greater carefulness
and attention than common programming takes. Here’s a small example: when proposing a method of protection by means of setting a
counter of program launches, this article suggested to put this counter into a .ini file with a name that sounds intimidatingly scientific, and
the most important thing was to forcibly set the same old date of modification for this file after each decrement of the counter. I
hope that, upon reading this article, you will not store the name of this file as an open text. To manipulate this .ini-file you
will probably use a WIN API function WritePrivateProfileString. Do you remember that Windows caches .ini-files to increase
the operation speed? Here’s where such a situation may occur: you use the WritePrivateProfileString function, yet saving an
.ini-file is delayed. You then set a date you need for the file. And then the cache is being dumped onto disk with a correct,
yet undesirable date of modification specified. How to counter this problem is mentioned in the description of the mentioned
function – I used this example to show, just how accurate a programming should be.
[MIRRORS/www.litespeed.org/Tutorials/a7.htm]
[MIRRORS/www.litespeed.org/Tutorials/a8.htm]
[MIRRORS/www.litespeed.org/Tutorials/footnote.htm] bot="Include" endspan i-
checksum="7085"
Anti Cracking FAQ
How to make cracking your programs a little harder
Contents
1. How to make cracking your app a little bit harder...
2. More tips you might take into consideration...
3. Advanced tips given by Assembler freaks...
4. Special on Delphi VCL cracking...
5. Some notes on registration numbers...
6. How to find cracks for your apps...
7. What to do if you found a crack for your app...
8. Facts and Myths about Software pirating...
9. Thoughts and letters from crackers
10. Links of interest...
Finding out that the program on which you worked for months or years has been cracked can really hurt
and demotivate.
For me as a Shareware programmer, the reason has never been that I've lost a few cents (I don't want to
do propability calculations here, it might hurt even more..), no, it was simply that I've always tried to hold
my programs as cheap as possible to make them affordable for everyone, even for students or freeware
programmers.
Somehow I can understand the fascination of cracking programs (if you are absolutely intolerant about
software crackers and hackers, please excuse, but one of my educations is Psychotherapy, and I'm always
searching for reasons...) - cracking a restricted software program must be like solving a (sometimes very
tricky) riddle, and you might get addicted to the feeling of solving them (I've found that when I saw my
grandmother doing crossword puzzles all over the time for some months). The problem is (but at the
latest, now we come to the undoubtedly illegal part of the "game"): it doesn't really satisfy the cracker if
he is the the only one who knows about his "genius"...thus, he has to spread the news. He has to publish
his "crack" (just see most crack packages: in most cases they just consist of: 1. the cracking utility 2. a
short description 3. a big file containing claims that the producers are nothing less than the greatest ones
on Earth and that the cracked program is another one which could not stop them with "its lame protection
scheme".)
But now the fun is completely over: by giving out this (let's try to be fair: "study of feasibility") to other
people, by spreading it via Websites, newsgroups, mailing lists, anonymous FTP, CDROM "abonnements"
and whatever, they clearly damage the business of everyone who puts time and energy in their software
product. Even if we assume that typical crackers wouldn't have bought your product under normal
circumstances: spreading the "crack" IS criminal and no one could claim that none of the receivers or
downloaders would never have bought it. It's just like if someone hands out copies of the key to your car
on the marketplace - and it doesn't really matter if he does that for money or not.
In earlier days, I have never put real energy in protecting my programs against cracking, but after finding
several cracks for them around, I thought to myself: why make it too easy? As a programmer, of course I
know that no - really: NO! - program can ever be crack-safe, and I know that of every interesting program
sooner or later cracks (or at least pirated or illegally copied versions) will be around, but at least I could try
to avoid the worst mistakes. Crackers are not super-geniuses .. they are simple programmers who have
learned some techniques to counteract common protection schemes - and if you know where and how
crackers are searching, you can make them lose *much* time! And that's what it is about: there is no
bullet-proof way to protect your programs, but you can dance on the nerves of those people until they
decide for an easier target to "get the feeling"... or even go outside to enjoy the nature instead of sitting in
front of the monitor the whole day. ;-)
Most of the typical 'high language' programmers don't know Assembler anymore, so the 'protection ideas'
they use are in most cases quite weak.
I don't know much about Assembler myself, so I decided to open my eyes and started to collect anti-crack
protection tips wherever I found them. Also I did my best to "learn from the other side" .. many of the tips
you can find here I've found by studying the typical cracking techniques, the various "cracking guides"
around the web and by reading protection tips given even by professional crackers themselves (some of
them generously give us tips to increase their challenge). Well, I hope I've learned my lessons well enough,
but also want to share my experiences with you on this page.
Some rules given here were already stated in various essays on other sites, but are listed here for
completeness. Many of these apply especially to windoze, but can be "ported" to other OS'es or anywhere
else.
PLEASE:
This FAQ is just as good as the experiences that are webbed into it. If you think that I've missed some
points or useful tips a typical Delphi programmer could easily add to his/her programs to improve
protection, please let me know. If you allow it, I'll add it here, otherwise I'll inform you about my
experiences with it.
Don't ask me questions - might be that I'm simply too overburden to answer.
1) As mentioned, I don't have much knowledge of the low-level stuff.
2) I can't send you demo sources, since I don't have anything ready for a publication. If I have
something, you will read it here.
3) Finally, I will not provide anyone with any of the URLs where I've found (or found out) some of
these tips. Please understand, but this is a site dedicated to programming, but not to provide "step-
in's" to available cracks or even to "Cracker hunting".
How intelligent and complex your code inside this function might ever be - an experienced cracker will
just take about 10-20 seconds to remove it. Believe it or not.
Alternatively, place some required code for your program in such a function. If the cracker disables the
function, your program would produce incorrect results, for example.
Avoid nagscreens or "Gotcha!" messages - this is what crackers are searching first. They will
never dig through the 300K ASM instructions of your program - instead, they are first searching the
location of nagscreens or your "Your evaluation time has expired!" message and start cracking there
(see below for more tips about that). In some cases, it's even enough to remove the form resource
from the EXE and it will show no nagscreen anymore - without any bug showing up! If you really need
such a nagscren, you should build it dynamically at runtime, and generally, the only method to show
the user that he is unregistered should be in the "about" dialog (some programmers also have the
philosophy that nagscreens might cause your users to hate your app which would then also be very
stupid).
Never use meaningful file names such as License.Dat. Why, you say? Please start reading here.
:)
Play with asymetric encryption. Just using unusual filenames is often not enough. Good encryption,
of course, could keep the cracker busy for months (if he likes).
Add long delays. Don't warn the user right after a violation is made. Wait later, maybe until the next
day or two (crackers hate that).
Add short delays. Pause a second or two after a password entry or to your other checking routines
to make brute force cracking unfeasible. Simple to do, but rarely done.
Use checksums in DLL's and in the EXE. Have them check each other. Far away from "safe", but it
just makes it harder to crack.
Self-heal your software. You know, things like the error correction modems and hard drives use.
The technology has been around for years, and no one uses it on their software? The best thing about
this is that if the cracker used a decompiler, they may be looking at a listing that is no longer valid.
Patch your own software! Change your code to call different validation routines each time. Beat
them at their own game.
Store serial numbers in unlikely places like as a property of a database field. Often heard and read:
"..give it a DLL file name and store it in the System directory." Too often heard, don't use it. ;-)
Don't rely on the system date. Get the date of several files, like SYSTEM.DAT, SYSTEM,DA0 and
BOOTLOG.TXT and compare them to the system date. Require that the time be greater than the last
run (but keep in mind that many users might do Y2K-checks these days).
Don't use literal strings that tell the user: "Sorry, but... (whatever)." These are the first things to
look for. Build strings dynamically or encrypt them.
Flood the cracker with bogus calls and hard-coded strings. Decoys are fun.
Have fun with Spaghetti-Code simply eats his time and nerves..
Don't use a validation functions. Every time you validate the user, write your validation code inline
with the current process. That just makes more cracking for the cracker and bewares of just NUL'ing
out your routine.
Use "reserved" names. When using hard-coded keys or passwords, make them look like program
code or function calls (i.e., "73AF" or "GetWindowText"). This actually works very well and confuses
some decompilers.
No "disabled" features. If your program doesn't save data in "crapware" edition, don't include a
"grayed" menu item. No saving means no saving - the code should not be included in the EXE - that's
it. Most programming languages offer you a really easy way to maintain several versions of your code
by simply doing the following:
{$IFDEF trial}
... no action here ...
{$ELSE}
... advanced functionality for registered user ...
{$ENDIF}
Say "Goodbye" to startup/time-limits! This belongs close to the tip above - especially, since there
is simply no way to protect a time-limited demo. You won't believe it - there even exist patched
versions of Windows DLL's (!) which will make your demo think it has never run before on this
computer. At one point or another, you will have to save your date or program start information on
the computer: in a file, in the registry, somewhere - and Windows provides GREAT ways to spy on
any changes made to these devices. "This is a war that can never be won." (D.Filion)
Update often. Frequent updates mean: frequently changing code, so the typical (simple) crack which
is just patching hard-coded byte positions, will possibly already be outdated when published. Also
prevent uploading them to public servers, so that you have better control about where your app sits
around and people don't find older versions the cracks can still use. Yes, this doesn't prevent pirates
from including the version to the crack package, but IF they do so, you can at least contribute to filling
up their harddisks.
Use strong encryption. Just XORing is not really strong - use something with an algorithm that isn't
easily reverse-engineered, and don't put both encryption and decryption code in your app.
Finally, take some time to think about protecting your software. Is it really worth the
protection? Wouldn't it be better to improve your software, rather than improving protections? The
problem of protecting software vanishes if no one will use your software. Don't overestimate your
work's "importance to the world".
Caution with the Runtime libary! Use it fully when writing the beta versions, in the final release
rewrite some functions at least to make crackers life harder.
Traps. A method I'm not sure about, but I have heard some apps are using it: do a CRC check on
your EXE. If it is modified then don't show the typical error message, but wait a day and then notify
the user using some cryptic error code. When they contact you with the error code, you know that it
is due to the crack. Be aware: such traps could also be activated due to virus infection or incorrect
downloads. Imagine the possible aftereffects if you are blaming your potential customer for software
piracy.
Don't rely on "EXE-packers". For almost any tool which compresses EXE files (Shrinker,
WWPack32, NeoLite - to list the most popular ones) there's an uncompressor around, so
compressors capable for software-protection should at least support configurable encryption.
Unpackers for the above (and other) tools are not very wide-spreaded, however, don't rely on them
as your program's (one and only) "protection" - organized crackers usually have their harddisks full of
such "tools".
Recompile and re-release often! Especially if you are modifying your "anti-cracking" routines often,
even more advanced cracks with code-searching capabilities will be useless.
Control your own distribution! Avoid putting your apps on compilation CDs. If a crack is developed
for a version that is on 30,000 CDs, that version is likely to be pirated. [by Ch.Losinger]
Advanced tips ..given by assembler freaks.
"Let's learn something about the innards of new Borland's programming tools. This knowledge will allow us
to speed up cracking sessions, as will teach shareware programmers who use Delphi to be more careful
and not to happily expose their 'secrets' to curious eyes B) [..]
VCL stands for "visual component library", a library used by recent Borland visual languages as Delphi and
BC++ Builder.
These environments use a proprietary resource format, that appear as 'RCDATA' when listed by Resource
Workshop. These resources contain 'forms'. In Delphi jargon, forms are the windows of the program. All
the info about their design is stored there. When a typical Delphi app is starting, the initialisation code
creates the forms, loading the required information from the resources. Sometimes this loading is deferred
- forms that aren't used very often are created and destroyed as needed.
This system is the best and the worst of Delphi. It allows a very fast way of programming but, for full-
length apps, it can slow down the loading.
The really interesting part of this information is that the address of the routines - called in response to user
interactions with the elements of the form - are bound at run time by name. So knowing these names we
can find the appropriate addresses!
If you have cracked any Delphi apps, you have surely experienced the long chain of calls inside the library,
from the breakpoints on the API calls to the "do something" code. I hoped that these addresses could help
in pinpointing the relevant code."
to see :=) After first installation the weeks passed and I hadn't had the time to work on it... when I started
it, I found a nasty 'Your evaluation period has expired' message :-(
The first step is to gather the information about the target exe with a resource or form spy tool. You may
be tempted to investigate TVALIDATORDLG, the form where the user name and registration key is
obviously input. But all you'll find is a mere dialog. The real work is accomplished from its caller:
TSPLASHFORM. This is the nag window that appears at the beginning of the program, as well as when it's
shutting down and from the Help->About menu.
You can select TSplashForm and look at the text representation of it. A lot of information about the buttons
and labels will appear. Let's concentrate on the following part, near the end:
What's that? This is the button with the caption "Register". You can see its size, position... and something
with a suggestive name: "OnClick". "OnClick" tells us the name of the routine invoked when the user
presses this button. Once we have the name (yes, "nomen est omen" :) we can search for the address of
this routine. This is because the routine is bound to the button at run time by name.
Using a hex editor, I looked for "RegButtonClick" and I found it twice. The second occurrence is the
resource itself, the first is within an address table:
000A4990 ____ ____ ____ BC57 4A00 0E52 6567 4275 ______.WJ..RegBu
000A49A0 7474 6F6E 436C 6963 6B__ ____ ____ ____ ttonClick_______
Now look at the magic numbers before the name. There is a byte ('0E') indicating the length of
"RegButtonClick" (14 characters) and before that an address: 004ABC57.
Some disassemblers seem to think that file is too long and it doesn't disassemble this portion of the exe
correctly - however, with a special tool we can bpx on this and... right! It stops at the point just when we
push the button.
A couple of instructions forward you'll find a CALL. Tracing into it you'll find a "standard stack frame" in
44ECC8:
This is the kind of thing expected at the beginning of a high level routine, made by the application
programmer. We have avoided the whole chain of library calls through the VCL from Windows notifications,
and landed in the right place!
From this point, there are some calls you can easily test by setting breakpoints on them - you'll find that
their purpose is to show the dialog asking for the user name and registration key. Then, the key is
calculated from the user name and compared with the one the user entered. You can enter the name you
choose, and anything as the key, after BPXing 44ED69. Here, a call to a routine compares two strings. D
EDX will show the fake key you entered and D EAX will show the correct calculated key. Easy, isn't it? A ten
minute crack by a beginner!!
[description about spying the key generator routine comes next. It's been an average routine of about 10-20 Object pascal code lines.]
Read my tips above. The basics are: don't use automatic methods created by double clicking on the button
or the object inspector. Write your code somewhere else in your program, preferably in another module,
and bind it to the button using code such as:
RegButton.OnClick := RegButtonClick;
Of course you'll need to enter this code after the form is created and before it's called. Best if it's rounded
by a lot of unrelated stuff. This won't necessarily prevent your program from being cracked of course, but
things will not be as easy as you have seen in the lines above O:)
Search newsgroups
Unlike what polititians are trying to suggest to the public, it's in most cases quite easy to track down
who is posting cracks, serial numbers or even full licensed copies of your software in newsgroups like
alt.cracks.* and others. Just let your newsreader display all header fields and check carefully where
those people are writing from. Since almost any news server requires complete authentication before
posting, you have good chances to find out who "hides" hinter strange names like "Hackman" or
"Piratez2000". If you have no success, simply contact the webmaster of the server where the
message comes from or forward him the posting, requesting action against this person.
Use Web-Robots
Sites like http://202.114.22.131/mirrors/www.netmind.com/default.htm offer robots that notify you
by email when a page changes. Since you can also define result pages of, for example, AltaVista
searches for a crack or key to your program, this is a cool way to get "paged" as soon as some
spider hits a website of a child which "-cool, man!-" offers a crack page. You can even do that for
newsgroup searches!
I've heard and read many programmers telling "you can't do everything against them, there are too many
crackers around, too many warez sites on the Net, so that few people ever get caught."
Fact is, however, that you as a software author would have excellent chances to win any lawsuit against
operators of ISP's awaringly keeping crack/warez sites online or against the crackers themselves. Hundreds
of sites have been closed down during the last years due to offering or linking to pirated software. In some
cases, computers were confiscated, and the operators are still paying settlements.
So, you don't have just to accept if you find pirated copies or cracks for your software around .. try to
detect where it comes from and get into action against the source!
Forget about the BSA (http://www.nopiracy.com, http://www.bsa.org) - these are just commercial
organizations which just take "orders" for their paying clients. No, they don't work for everybody -
usually they only come in to action when the target is a large firm, using software from one of their
biggest clients (no prizes for guessing which one). Can you say "M$ Militia" ?
Do internic queries on the crackers site
(http://202.114.22.131/mirrors/www.checkdomain.com/default.htm), contact the sysadmin, explain
the situation. If the ISP is a fair and serious one, there are chances that the crackers will receive a
serious warning to remove all the illegal stuff from their sites or that it will even be closed without
delay.
If this doesn't help (seldom seen, but possible), contact the local authorities of the state where the
ISP is located. Most countries even provide email addresses for reporting crime activities (like
childporn, but they are also open for pirated software), or at least their police administration can be
reached by email. There are good chances that the ISP will be threatened to lose his licence.
Finally: get yourself a good glass of wine and enjoy it. You have written a good program! (otherwise
no one would lose time trying to crack it)
Myth: "None of the software offered was stored on my site - I only had links to the files."
Fact: You could be liable for anything that you do that contributes to the infringement of copyrighted
works. This includes facilitating a download by linking to remote files.
Myth: "I thought it was okay to download programs to try them out if I delete them within 24 hours."
Fact: This is a common Net Myth. You may only use the software as described in the end-user license
provided by the software publisher.
Myth: "What about "fair use"? I am only providing a service for "educational purposes."
Fact: Fair use is widely accepted to mean the reproduction of a part of a copyrighted work, not the
wholesale copying of an entire program or contributing to software piracy.
Myth: Writing a book about robbing banks and robbing them yourself are two different things, not?
Fact: A better analogy is "robbing the bank" vs. "driving the getaway car." Or, another analogy is stealing
software vs. marking the computer store window with an big X and telling people that, if they throw a brick
at the X, they can steal the software in the store window. Both are illegal.
Myth: Software is so expensive, and I've wasted a lot of money just to find out that an expensive program
is worthless! If it's any good, then I'll reward the authors. If not, forget the compensation!
Fact: Cars are expensive, too, but society doesn't allow people to use them and decide later if they want
to pay for them or not. In the same way, you cannot use pirated software and pay for it only if you want
to at some later date.
"Why the hell should a Cracker provide Richey with tips for his page!", you might ask yourself.. ;-)
As already mentioned, I don't believe that Software protection is the answer to all sales-related problems
(think of the enourmous -also financial!- success of some popular Freeware products, Open Source
projects and not the least weak protected programs like WinZip and so many others!) ... in most cases the
main reasons why developers don't see money is because they are producing the 1000'th clone of already
popular products, provide poor quality or simply don't have any idea of 1) really innovative products 2)
good design and 3) marketing.
However, there ARE reasons why protection might make sense. One of them might be the following: you
are investing 2 years (or many months) of hard work in a brand-new product with some new, advanced
features or logic no one else on the market has ever offered before. You have a limited number of potential
customers for which your product might be of real interest - but want to protect some specific parts of
your program from being reengineered or simply copied -> you need a working protection for that...
Well, I have to admit that I've been suprised that at least some crackers accept that and especially that
some of them even decided to provide us all with tips how to protect our work in a better way. Let me tell
those fair guys a big "THANK YOU" at this place.
BuLLeT's contribution
Note: I'm keeping all letters from Crackers strictly confidential except there's an explicit permission to publish them.
Links of Interest
"Contributory Copyright Infringement Lawsuit Settled Against Internet Pirate" (SPA press release)
How to battle Warez Anti-Warez Mailing List and -Tips
Anti Crack Information by Vitas Ramanchauskas
The "Sam Spade" whois tool find out who publishes Cracks for your Applications
Tracking Down Warez Sites how to find the responsible persons (page provided by Rob from Cat-Soft,
the link above)
Report Software Piracy (BSA / NoPiracy.com)
Report Software Piracy (SPA)
Decompilation page provided by the University of Queensland
Programming-related stuff
efg's CRC Lab good explanation of the "Cyclic Redundancy Check" algorithm and coding examples
By Shaikh Adeel
www.vngamecenter.com
In this tutorial you will learn how to hack games that use DMA (dynamic memory allocation. Ill use
AOE 2 to demonstrate using SI.
Tools Needed:
1. Softice (SI)
2. Game Trainer 2.01 or Game Hack 2.0
Lets find the addies for resources in AOE 2. First of all start Game Trainer and then the game. Start a
new game. While you are in the game see the value of your GOLD. My value was 1000. Press alt +
tab to switch to Game Trainer (GT) in WINDOWS. Select the process Empires2.exe from the process
list. From the type list choose Float coz u will find the address of GOLD in this format. In the value
tab enter the value of your GOLD and press search. You will find several matches. Go back to the
game and spende some GOLD (e.g. build a unit). See the new value of your woods. Now go back to
GT and in the value tab write the new value. Press Sieve. You will find lesser number of matches.
Repeat the same process till you find only 3 matches. Then just use the Trial and Error method to find
which address is the one you are looking for.
When you’ll find 3 or 4 matches what you will have to do is to change each value to a different
number. For example if you have found the addresses: 00FF1212, 00FF1244, 00FF7890 you could
change the value of the first one to 10,the second to 20 and the third to 30. Now go back to the game
and see if the value of GOLD changed. Normally it must have changed to one of the numbers above. If
the number has changed to 10 then the address we are looking for is 00FF1212,if the number has
changed to 20 then the address we are looking for is 00FF1244 and so on.
Now lets continue. Note down the address you found. Because you will use softice now you won’t be
able to see this tutorial till you exit from it so you must remember this part. Go back to the game and
press Ctrl+D to bring up softice (be sure that in the down right corner the word Empires2 is written).
bpm address w
Where address is the address you found. Let’s say that the address is 00FF1212.You should write:
bpm 00FF1212 w
The word bpm in softice sets a breakpoint to a specified address and the w means write.So with this
command we say to softice to breakpoint to the address we specified when a “new” value will be
written. Now when you write to this command press Enter and then F5.You are back to the game.
Now you must loose some GOLD. To do that, build a unit. Softice will pop up by itself and you will
see something like this:
highlighted.
If u don’t see the no of bytes then write CODE ON and press enter. In the above shown code the byte
representation is in RED.
As I write above the highlighted area is where the softice popped up. So now the general idea is to
use the NOP command (it means No OPeration and it is a special “command” for assembly) the first
command\address (beginning from the highlighted address and up) that decreases our value…That
address never changes. The command we use to decrease a value in assembly is dec or sub or
something like that. The command dec or sub will almost always be contained (e.g. it could be fsub).
So let’s check the first line above the highlighted one. The command is FSTP. Nope it’s not the one
we want…Let’s check the one that is above. FSUBR…Hmmm what’s that? It contains the sub! Maybe
it’s this one…Yes it’s this one! Ok now that we have found the address we must nop it. How can we
do that? Just follow me…As you can see this command reads 2 bytes (D829). So if we want to nop it
we will write in the command window E 0059F9DD (we write this address because that is the one of
the command. See left of the command FSUBR). The cursor will be to another window, the third from
the bottom, the data window. There just write 9090 and then press Enter (we write two 90 because
the command reads 2 bytes…. D829.So if it was reading 6 bytes we would write 909090909090).
Yes that’s it we hacked the game!!! This method can be used in all games.Now type bc * in the
command window to clear all the breakpoints (well the one we made J).Go back to the game by
pressing F5.Now whenever you build a building you will not loose GOLD!
Warning===> Some games have side effects by doing that.Age of Empires has a side effect.If you
build e.g. a unit (that costs 30 GOLD) and you have x golds (where x>=30) the current amount of your
GOLD will become 30!So if you had 1000 woods and built a unit the value would change to
30!!!This is a side effect.In most games you don’t have side effects.To remove the side effect you
must nop the address that causes it! Usually you must nop the address next to the sub address. In our
example is address 0059F9DF. So what you have to do is to nop it by using what you’ve learned so
far. When you do that and go back to the game you will see that the side effect is no longer exists!
NOTE:
This Tutorial is inspired by Miltos Raynor’s ( Miltiades ) tutorial.
U have learned here how 2 use Soft Ice to defeat DMA.
If u have any problems please mail me.
Hack Age of Empires 2 using Softice and Game Trainer 2.01
Tools:
Softice
Game Trainer
MSR LastBranchFromIp=0059F918
MSR LastBranchToIp=0059F9A0
Above the command window is another window.The code window.In this windows you will a
something like this:
0167:0059F9E1 83C006 ADD EAX,06 ç====Softice will pop up here (this will be highlighted)
As I write above the highlighted area is where the softice popped up.So now the general idea is to
nop (it means no operation and it is a special “command” for assembly) the first command\address
(beginning from the highlighted address and up) that decreases our value…That address never
changes.The command we use to decrease a value in assembly is dec or sub or something like
that.The command dec or sub will almost always be contained (e.g. it could be fsub).So let’s check
the first line above the highlighted one.The command is FSTP.Nope it’s not the one we want…Let’s
check the one that is above.FSUBR…Hmmm what’s that?It contains the sub!Maybe it’s this one…Yes
it’s this one!Ok now that we have found the address we must nop it.How can we do that?Just follow
me…As you can see this command reads 2 bytes (D829).So if we want to nop it we will write in the
command window e 0059F9DD (we write this address because that is the one of the command.See
left of the command FSUBR).The cursor will be to another window,the third from the bottom,the data
window.There just write 9090 and then press Enter (we write two 90 because the command reads 2
bytes….D829.So if it was reading 6 bytes we would write 909090909090).Yes that’s it we hacked
the game!!!This method can be used in all games.Now type bc * in the command window to clear all
the breakpoints (well the one we made J).Go back to the game by pressing F5.Now whenever you
build a building you will not loose resources!
Warning====èSome games have side effects by doing that.Age of Empires has a side effect.If you
build e.g. a house (that costs 30 woods) and you have x woods (where x>=30) the current amount of
your woods will become 30!So if you had 1000 woods and built a house the value would change to
30!!!This is a side effect.In most games you don’t have side effects.To remove the side effect you
must nop the address that causes it!To find that address I use my common sense and my little
knowledge of assembly.Usually you must nop the address next to the sub address.In our example is
address 0059F9DF.So what you have to do is to nop it by using what you’ve learned so far.When you
do that and go back to the game you will see that the side effect is no longer exists!Here’s the above
code with some more notes:
0167:0059F9DD D829 FSUBR REAL4 PTR [ECX] ç====This is the address we must nop
0167:0059F9DF D919 FSTP REAL4 PTR [ECX] ç====This is the address that makes the side effect
0167:0059F9E1 83C006 ADD EAX,06 ç====Softice will pop up here (this will be highlighted)
There are other things you can do instead of noping the address.If you want to know what keep
reading!
There is another thing you can do instead of noping the address.Why not making the address more
usefull?Here’s what you can do.You can reverse the command.That is instead of sub make it add!By
doing that whenever you build something you will gain money instead of loosing.For this you will
need Hiew (Hacker’s View).I will not use a game for example here.Open Hiew.Find and open the
exe file of your game using the browser of Hiew.The exe file will be in the directory where you
installed the game (when you’ll find it just highlight it and press and Enter).Wow what a mess!Now
press F4 and choose Decode from the menu.Press F5 (we do that to search a specific address) and
write .address where address is the address you found in the previous section.So if the address is
00FF1367 you must write .00FF1367 and press Enter.You will be exactly to the address we want to
change.We want to edit this one so press F3.Oh, by the way write down the bytes of this address so
you can remember them.Ok now we can write and change the command.The problem is that we can
write only numbers and we must find out which number is the command sub (well most times is
number above or below).Wouldn’t it be better to write the command add?So press F2.What’s that?
Hmm we can change the whole command as we are writing assembly!Ok clear the word sub and
write add.Now press enter and then ESC.The byte that changed is colored yellow.Compare the bytes
you have written down with the ones in Hiew.At least one is changed.In your paper write below the
number that has changed, the one that is in Hiew.Now what you have to do is go to the game and
while you are playing press Ctrl+D to go to Softice.Then write e address (where address is the
address you found in the previous section) and then write down the numbers you have in the piece of
paper (of course the new numbers with the changed byte\bytes).For example lets say the bytes were
0981 and after what you did with Hiew the byte 09 changed to 23.In softice you will have to write
2381.Easy huh?You might think it complicated but it’s not.Do it 5-6 times you’ll get used to it.
You could something else too but this is illegal because you’ll modify other’s exe file.So don’t blame
me if go to…….jail ;)!!!!!!Do it at your own risk…Let’s see now.When you change the bytes with
Hiew you can press F9 to update the exe file (you must not playing while doing that).In this way you
won’t need to go to softice every time you exit and reenter a game to change the command .
==================================
=== Age of Wonders 2: Map Hack ===
==================================
by Slurps
Hi there.... I've been working on a map hack for Age of Wonders 2 which I'm
gonna write some about. If you aren't too experienced with SoftIce and assembler
yet, I would recommend you to work on other kind of options first though(and
practicing SoftIce/assembler)... other than that, there's also gonna be a little
C++ and DirectX... but I'll just tell you what you have to know about that...
Another thing is that you have to run SoftIce in universal mode to make this
work. If SoftIce is running it's own full screen, the game won't be repainting
SoftIce which we need to happen to track down the game's drawing routines.
Well... you can track it down in other ways as well, but this is much faster and
easier so I won't bother with anything else.
If you're not running SoftIce in universal mode... just open up the video
setup/settings and hit the Universal Mode checkbox... now restart the computer.
So, that's it, time to start ;)
Start off by entering SoftIce. Right below the code window, you'll see something
like AoW2!CODE+some_number if SoftIce popped up while aow2's code was executing.
If it says something else, you'll have to close and reopen SoftIce until you're
in aow2.
Now that you're there.... this is when you need SoftIce knowledge/experience.
You have to be good at crawling around loops and functions, because that is what
you have to do now. You're gonna step out of loops and functions and execute
loops of code and just any code until SoftIce looks weird, because SoftIce will
look weird once the game updates the screen. Your aim is to get out of as many
loops and functions as possible.... the more functions you return from, the more
likely you are to run across the drawing-routine. This is something that you
HAVE to do on your own... you can appear just anywhere inside the code with
SoftIce, and there's no way I could cover all of it. Just keep in mind to check
that you're inside aow2's code, it has to say AoW2!CODE+some_number below the
code window, otherwise you're gonna have to try closing/opening SoftIce again.
In case you're curious as to what it looks like when you run across this screen
update, put a breakpoint at 4F4A9B, and then hit F10 when SoftIce breaks. This
is what it looks like and this is what you're looking for...
Once you do come across the update.... typing rs in SoftIce and hitting enter
twice will clear it up for you. rs is a command used to hide SoftIce, so that
you can see what is behind it, and it then waits for a key to be hit before it
returns... and once it returns, you'll have a new and fresh view of SoftIce.
If you have trouble getting to this call that paints the screen.... a tip is
that hitting F12 in SoftIce will bring you right below the call which executed
the function you were currently in... I'll show an example, suppose this is the
scenario:
...
push ecx
push eax
call 4785a1
mov ecx, eax
xor ebx, ebx
...
4785a1:
...
mov edx, [edx]
add ecx, edx <----- This is where SoftIce popped up
sub bl, 12
...
ret
Now.... if you hit F12... SoftIce will proceed until it gets to the ret
instruction at the end, execute it... and you're gonna be at the "mov ecx, eax"
instruction.
If you keep doing this and hit F10 ("p" command) to walk you through loops and
code and the like will get SoftIce messed up in time. Once this happens, take
note of the address of the instruction (it'll be a call, always will be...)
which messed up SoftIce.
This will take some messing around... but after doing it a few times you will
get there... you'll just stumble across it soon enough... there isn't really
much I can do to help you get to it.... but if you're familiair with SoftIce I'm
certain you'll find your way. ;)
This is the address which I found: 4F4A9B... now that you've found it, you're
gonna have to trace into(F8) that function and look for a call inside this new
function which messes up SoftIce.... and you do that over and over again...
AND... ultimately, you'll spot a call which jumps into DirectX code ;) (that
is... when it won't say AoW2!CODE+some_value below the code window, it would be
ddraw instead...)
To quickly trace into a function when the highlighted line is below the call...
you just leftclick at the call you wish to trace into, which puts the cursor
right at the call instruction... now hit F7. This will make SoftIce
automatically put a breakpoint on it, and let the game execute till it gets
there. So the call instruction will now be highlighted and you can trace into it
;)
Here are the calls I found by tracing downwards that draws onto the screen:
There... the last one is the DirectX call that puts a new frame on the screen...
as it says ddraw!.text below the code window when you trace into it, you'll know
it's DirectX(DirectDraw) code that you traced into.... and that's as far as we
have to go. Now, we're gonna have a look at this call to mess up the drawing ;)
Switching surfaces
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
I've written down the instructions that call for the screen update(the DirectX
call that is), and here they are:
004283F9 push 10
004283FB mov eax, [ebp-04]
004283FE push eax
004283FF mov eax, [esi+24]
00428402 push eax
00428403 mov eax, [edi+04]
00428406 push eax
00428407 mov eax, [edi]
00428409 push eax
0042840A mov eax, [ebx+24]
0042840D push eax
0042840E mov eax, [eax]
00428410 call [eax+1C]
You should recognize this from SoftIce, where the last instruction being the
call to DirectX. You saw when tracing into it that it's DirectDraw code...
IDirectDrawSurface7 is the latest version of the Direct Draw surface(from
DirectX 7), and if you look up the debug messages, you'll find that it's calling
DirectX 7/8 functions(requires the debug build of the DirectX SDK though)...
this would be enough to look up the IDirectDrawSurface7, but if you'd want a
more sophisticated assumption you can look up how DirectX creates it's surfaces
and break on those functions(I won't cover that, as this is enough).
What you need now is ddraw.h, which comes with the DirectX SDK for version 7.0
or later(there's a ddraw.h for earlier versions of the SDK as well, but those
versions of ddraw.h are too old).... inside it you'll find this piece of
information:
Alright, there.... aow2 is calling BltFast to paint onto the screen. Here's a
reference of this function:
-----------------------------------------------------------
The IDirectDrawSurface7::BltFast method performs a source copy blit or
transparent blit by using a source color key or destination color key.
lpDDSrcSurface
Address of an IDirectDrawSurface7 interface for the DirectDrawSurface object
that is the source of the blit.
lpSrcRect
Address of a RECT structure that defines the upper-left and lower-right
corners of the rectangle to blit from on the source surface.
dwTrans
Type of transfer. The following transfers are defined:
DDBLTFAST_DESTCOLORKEY
A transparent blit that uses the destination color key.
DDBLTFAST_NOCOLORKEY
A normal copy blit with no transparency.
DDBLTFAST_SRCCOLORKEY
A transparent blit that uses the source color key.
DDBLTFAST_WAIT
Postpones the DDERR_WASSTILLDRAWING message if the blitter is busy, and returns
as soon as the blit can be set up or another error occurs.
-----------------------------------------------------------
You might have noticed from the code disssembly that it has 6 pushes, while only
5 parameters are shown in the reference.... you can see at the declaration that
it does take 6 parameters. However, the compiler has been told to add the THIS_
variable automatically so that the programmer won't have to bother with it....
which is why only the other 5 parameters are shown in the function reference.
There.... and you should be able to add those yourself as well if you take a
look at the reference/declaration ;) ... just keep in mind that parameters are
pushed from right to left (when you look at the declaration)...
If you notice that dwX and dwY are zero even though it paints all over the
screen.... that's because when they are zero, DirectX will consider it the whole
screen ;) ... you could try changing those or the RECT structure if you'd like
to, you'll find that the screen starts looking weird or that only half of
SoftIce is messed up soon enough :P
What I've been looking for is just this... the destination surface and the
source surface. Games never paint directly onto the screen... they paint onto a
surface not situated on the screen, so that they can then put everything on
screen later on, otherwise it'll look very strange and far from smooth... as
you'll soon find out ;) First it paints the terrain... then objects/stuff..
and then comes blackness and lighting on top of that... this doesn't happen all
at once on the surface the game paints on which is not the screen(on the screen
it all does come at once)... though it does keep painting this all the time in
that order, which is what we're gonna use to hack the map.
Because THIS_ is a variable that points to the object which calls the
function... and the object is the surface which is shown on the screen(surfaces
call BltFast to paint onto themselves). The surface shown on screen is often
refered to as primary surface. Apparently, THIS_ is located at [ebx+24]... so we
now have the address which stores the primary surface.
NOW.... what you do is write down the values located at esi+24 and ebx+24... the
values are 4 bytes long... if you take a look at lpDDSrcSurface, it has the lp-
prefix, meaning long pointer(and the rest of the name meaning to a Direct Draw
Source Surface)... and those are 4 bytes... so, now.... we just switch the
surfaces... to do that, you copy the 4 bytes at esi+24 into ebx+24 and the 4
bytes at ebx+24 into esi+24. As the game's other drawing routines write to the
surface pointed to by that memory, they will now be accessing the screen
instead, now that you switched them.
When the surfaces were created by the game... it wanted one to be the surface
shown on the screen, and one to paint to before it's shown. This fact won't
change when you switch them... and when you put the primary surface in place of
the secondary surface, the game will be painting to the screen while it believes
it's just painting to a surface which isn't shown to the player. Then, when it's
done painting, it'll copy what is on the screen to the secondary surface... as
you switched them.
The game isn't really worth playing anymore...... but you can see how the game
paints everything!.... you can see the landscape appear... you can see the trees
grow... how the mountains appear... anything.... ;) ... including the blackness
spreading across the screen :P
Anyway... the call I came across is located at 4653DA... you'll find other
things being painted as well nearby that call if you look around ;)
004653C0 mov edx, ebx
004653C2 mov eax, [ebx+00000260]
004653C8 mov ecx, [eax]
004653CA call [ecx+00000100] ; Paints objects
004653D0 mov edx, ebx
004653D2 mov eax, [ebx+00000260]
004653D8 mov ecx, [eax]
004653DA call [ecx+00000104] ; Paints blackness/some stuff
004653E0 mov eax, [ebx+00000190]
004653E6 mov edx, [eax]
004653E8 call [edx+78] ; Paints blackness/some stuff
However... as these calls also paint some other stuff... that's apparently not
what we want ;) (the rainbow for example, some lightning around glimmery stuff,
objects at the edge of the screen... and more...)
The first call doesn't paint the blackness every time.... but if you follow the
second call, you'll just end up at a Direct3D IM call which isn't what we
want... if we trace the first call a few times, we'll come along this call which
puts the blackness on screen:
Then, we just trace into that call as well to see what happens... and find some
more interesting code ;) .... and in this new function, you'll find that the
call at 47FB5E also paints the screen..... as there are several conditional
jumps before this point in code, which jumps further down... let's just have a
look at them...
Both of these jump below the call.... perhaps you could try changing them
(turning either of them into jmp instead) and see what happens, it's not the
right one though(but it does affect the graphics)... so we look a bit further
up:
Try changing [esi+113] to 0(it should be set to 1 already)... see?... Then, try
setting the byte at [esi+112] to 0(it should also be set to 1 already)......
there, voila ;)
Apparently... these switches cleared the map for us... we can now see everything
and select things where there should have been blackness.... so that's it. Map
hacked ;) .... and this doesn't mess up the graphics for anything but the
blackness...
The cheat
¯¯¯¯¯¯¯¯¯
You should know some about code injection... otherwise, have a look at [sheep]'s
tutorial about it. Anyway.... for the cheat I just injected some code at
47FB2B(where the compare is) to set the flags to show the map... and this is the
little bit of code I injected:
645FB4 66C786120100000000C3
47FB2B E884641C009090
Thanks
¯¯¯¯¯¯
Thanks a lot [sheep]... you sure did improve the quality of this tutorial a
lot... giving VERY good feedback... spotting all the problems... helping with
improvements.... thanks ;)
slurps_@hotmail.com
http://slurping.cjb.net
.________. .________.
\ | ___///__ ._________ .__///____ | \_
::::::| ____|___ ____|__ |_| /_| / .____|_____ |:::::::
:: | | __/___| | ____/| ____/ | | ::
:: | |____ \_ | | _|_|______._|___|____. | ::
:: | | | | | | | __///___| ::
:: | | | | | | | | ::
:: |_. | |_____|\_____///________|__________| | ::
:: \___///________| |[sheep] |_ | ::::::::::::
:: \__________| |_______| :: :: ::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::
Gamehacking Tutorial Collection.. :: ::
::::::::::::
Well, it certainly has been a while since I last decided to take to the keyboard and inform
you lucky people of some of the new techniques and interesting tricks ive come across while
training the best titles the pc has to offer.. All of my tutorials from this point onward
are going to be for the experienced gamehackers, im not going to make allowances for people
who dont understand certain aspects of softice or asm, you should all be capable of working
at an advanced pace by now and if you are not then i suggest you stop reading now.
I seem to have gotten a reputation for being an asshole to newbies.. hehe.. come on .. ME?
all I have to say to this is that it takes a long time to create these tutorials and to be
honest I would be just as happy explaining this shit to JUST my friends.. and not the masses
but I feel that we all deserve a shot at creating cool trainers and understanding something
more than boring NOP hacks.. see.. im not so bad :)
TOOLS NEEDED: Softice, memory searcher (your choice) SAS (my tool for grabbing injected code).
locations...
SOFTICE SETUP
*************
When you press CTRL-D to pop softice you should see the following windows..
REGISTER WINDOW - this window is always at the very top of the softice window
(WR [return]) and displays the contents of all the registers..
DUMP WINDOW - generally situated close to the top of the softice window
(WD [return]) contains a split screen display.. one side is ascii the
other is hex.
CODE WINDOW - this is the main window.. sits just under the DUMP WINDOW
(WC [return]) contains the code of whatever process maybe running when
u pop softice.. the code is represented in ASSEMBLY LANGUAGE
instrutions..
The comments in the brackets are what you need to type to turn the different windows on..
you also need to type CODE ON.. this will bring up the OPCODES which are a set of numbers
displayed to the left of each ASM instruction and to the right of every memory location
in the CODE WINDOW..
Well, Its Sunday the 3rd of November 2002 and at this present time only the cheats for
AGE OF MYTHOLOGY has been rlsed to the public.. I have seen no trainers or even heard
of anyone managing a resource hack.. All this is going to change once you have read this
tutorial, I can fully understand why there are no trainers, the usual trainer muppets
that usually produce substandard trainers and then rls them onto the unsuspecting public
would have given up on this game a long time ago because you actually need to do some work
to get a working resource hack :) MAN IM GRUMPY.. :))
LESSON START
************
Sections..
i) Ground Work.
ii) Finding our values (the hard but secure way).
iii) Looking at the Decryption Routine.
iv) Code Injection (making the resource hack).
v) Final Words.
GROUND WORK
-----------
Ok, GROUND WORK is a term I use for the very first information gleaned from the game you are
trying to hack.
The first things I noticed about AGE OF MYTHOLOGY was that the searches take forever :) so its
not going to be a nice quick hack.. :( ..
After doing a few search patterns and wasting about an hour of my life I decided that the game
wasnt using the usual methods of INC/DECing the values, the only alternative was that it used
encrypted (usually XOR'ed) values which would be then converted only when the game uses them.
If there is one thing for certain in this world apart from death and tax its that commercial
programmers are lazy bastards and will certainly not do more work than is absolutely necessary,
for us this is very good news because it translates into there actually being values NOT encrypted
in the game that we CAN get a handle on to find the encrypted resources values..
APPENDED NOTE!!
===============
you can also find the values by doing a VERY long winded CHANGED/NOT CHANGED search, but i
to teach you some advanced techniques that DO have major advantages in the future, all will become
clear soon.. neways.. if you wish to obtain the values in this way be my guest but i suggest you
stick with me and do it the way I did.
Ok, there is lots of work to do so lets get on with it. First thing we need to do is find some
values that have direct contact with the ENCRYPTED RESOURCE VALUES but are not actually encry
themselves... This is how its acheived..
Once the game has loaded up we can start looking around for something useful to us, ive already
done this bit for you to save time..
Click on the icon of the FOOD RESOURCE, this should bring up a TRIBUTE DISPLAY DIALOGBOX
with all of your resources inside.. (this is for giving supplies to your allies HENCE the 2v2 necessity).
On this screen you will notice that you have 3 boxes with the value 0 in them, all next to
the name of your allies.. these are to indicate how much resource of that type you wish to
send over. If you left click on one of the 0 boxes it should place 90 into the box, now
click the right button on the same box and it will reduce the number to 0 again, do you
feel a search pattern coming on? :)
APPENDED NOTE!!!
================
Finding options in games that are difficult to obtain usually consist of 2 things, 1. a good
logical thought process 2. good debugging skills. In this instance we need to follow a simple
logical pathway to understanding why this resource sending approach will help us.
So you can see that the marked items on the list would be VERY valueable to us because they
are actually affecting the ENCRYPTED RESOURCES but its all linked to the FIRST STEP which is
clicking that resource box.. its just a thing to keep in mind in the future when trying to
get a handle on harder options :)
We now need to do an inc/dec search to find this RESOURCE_SEND_VALUE, this is how we do it..
Search Increased..
Search Decreased..
REPEAT!!!
because the RESOURCE_SEND_VALUE isnt too obviously linked to the resource values it seems that
ensemble studio have given us a break and not encrypted it so you will indeed be able to locate
this address eventually.. it took me about 5 minutes to come up with this address..
ok, once you have found this value we need to breakpoint it so that we can start our investigative
journey.
do this..
the above instruction will place an OPEN breakpoint on the address which means softice
will pop every time that value is either READ or WRITTEN to..
Once you have done this exit softice with F5 until you are back in the game, make sure you
have something in the resource box to send to your allies, 90 is fine.. and then press the
SEND button at the bottom of the screen.
BANG!!
Immediately you should be looking at softice with the code below in your main code
window display..
At this point you may want to type WF to take a look at the floating point stack.
oki.. basically the routine above checks to see if firstly you have entered anything
to send to your allies and then to see if you actually have enough of that resource
to send..
now we must press F10(trace) until we reach location 001B:0042EC04 its marked on the
code above...
before we go on its a good idea to clear all of our old breakpoints so do this...
BC* <return>
Once you have done this we need to dump EBX into our DUMP WINDOW... so type
D EBX <return>
this will display the location stored in EBX into the DUMP WINDOW, in the top left
hand corner of the DUMP WINDOW should now be the de-crypted value of our resource.
once we have got this far we need to place yet another breakpoint on the location
now displayed in the top left hand corner of the DUMP WINDOW this breakpoint needs
only WRITE access and we place it by doing this ..
Once this is set press F5 until you get back out into the game....
now click back on the FOOD RESOURCE icon to bring up the TRIBUTE DIALOGBOX again...
BANG!!!
when softice pops you should be looking at the code below in your code window.
ok, so now we know that the main decryption routine will live inside CALL 005862e0
because just after it the decrypted value is placed into the memory.. not always the
case but in this game it is :)
BD* <return>
so, now we are here we need to breakpoint 42e9ca, this time its an executing breakpoint
so we do this..
you could also either use your mouse to double click it (if your using one inside softice)
or you could highlight the address and then press F9.. doesnt matter as long as you
breakpoint that address..
so now.. again!! press F5 until you are back into the game..
BANG!!!
we are back where we just breakpointed.. but now we are here BEFORE the value is decrypted
so we can see exactly what is going on with our resource values :)
trace into the call at 42e9ca by pressing F8.. you now see this..
001B:005862E0 833900 CMP DWORD PTR [ECX],00 <---- ; you are here...
001B:005862E3 7419 JZ 005862FE
001B:005862E5 8B442404 MOV EAX,[ESP+04]
001B:005862E9 85C0 TEST EAX,EAX
001B:005862EB 7C11 JL 005862FE
001B:005862ED 3B057028A300 CMP EAX,[00A32870]
001B:005862F3 7D09 JGE 005862FE
001B:005862F5 50 PUSH EAX
001B:005862F6 E885FAFFFF CALL 00585D80 <----- ; main decryption routine..
001B:005862FB C20400 RET 0004
once again keep tracing with F10 until you come to 5862f6 then press F8 to
trace into the call.. you will see this...
few notes..
===========
EDX = start of YOUR RESOURCES STRUCTURE.. ie. EDX+0(GOLD) +4(WOOD) +8(FOOD) +C(F
9b9f6c = DECRYPTION KEY TABLE. consists of 5 values..
12345678...09abcdef...0badf00d...deadbeef...76543210 <-- these are all hexadecimal decryption keys..
WELL!! lots to take in there eh? .. this is where all the business goes down :)
as you can see from my description the value we really need to look at is at
address 585d98.. this address contains the REAL ENCRYPTED ADDRESS of our
RESOURCES.. so now do this..
D ecx*4+edx <return>
and if you have followed this tutorial exactly, in the top left hand corner of the
DUMP WINDOW you should now see the REAL ENCRYPTED GOLD RESOURCE VALUE...
if you now look into EAX you will see the key that is used to decrypt that RESOURCE VALUE
we can do a little test for this..
^ = XOR in softice
?12345678^42c80000 <return>
if you enter that number into the top left hand corner replacing your original encryped
RESOURCE VALUE you will have changed your gold value to 100.
press F5 to get out of softice and back to the game and you can make sure that your
gold value is indeed 100. :)
return to the game.. without the TRIBUTE DIALOGBOX showing.. now press
the FOOD RESOURCE ICON again..
BANG!!
EBX = 0 (this is the index used to calculate what key to use from the table)
ECX = 0
EDX = 59d2010 (may be different on yours.. this is the base address of your resource structure.)
with these 2 values and a the location to inject at 42e9cf.. we are all ready to do our injecting..
oki.. first thing to do is find a nice spot to place your injected code.. anyone that is still
reading this tutorial AND FOLLOWING IT!! will be able to do this.. so im not going to explain
how to do it.. use your fave method and keep reading once you have done this....
i chose a93e10...
so type..
A 42e9cf <return>
then type
JMP a93e10 <return> (you obviously have to use your code injection place not mine :))
nop <return>
nop <return>
nop <return>
this will balance up the bytes we just destroyed (we need to recreate them in our code injection)
oki.. im going to just give you my injected code and then explain it afterwards..
D91E FSTP REAL4 PTR [ESI] ; re-create the instruction we destroyed with our jmp
8BAEF0FDFFFF MOV EBP,[ESI-0210] ; re-create the instruction we destroyed with our
53 PUSH EBX ; save EBX onto the stack
51 PUSH ECX ; save ECX onto the stack
33DB XOR EBX,EBX ; EBX = 0
8B0C9D6C9F9B00 MOV ECX,[EBX*4+009B9F6C] ; Mov decryption key into ecx
81F10000C842 XOR ECX,46C80000 ; encrypt 25600.0 with the encryption key..
890C9A MOV [EBX*4+EDX],ECX ; move the new encrypted value back into memory
43 INC EBX ; increase loop counter
83FB04 CMP EBX,04 ; have we done ALL resources?
75EA JNZ 00A93E1C ; if we havent it will jump back and do the next resource
59 POP ECX ; restore ECX
5B POP EBX ; restore EBX
E99BAB99FF JMP 0042E9D4 ; jmp back to normal game code execution..
as you can see it looks a little more complex than your usual code injected hacks mainly
because all the code is actually specific to its location .. ie .. you wont be able to
grab the decryption keys and the BASE locations of the encrypted resource from just anywhere
they need to be taken at certain places.. well.. this is it..
what it does is takes the first BASE address of the key.. encryptes the 25600 value with the key
which gives us the value to save back into memory.. we then move this value back where it should
be and carry on to the next KEY and the next VALUE.. doing the same.. until we reach 4 which is
the end of the loop and the amount of resources we are hacking :)
:)))
a small note.. the favor resource is regulated by other factors .. during the game it may switch back to
a lower number.. this is its maxxed number.. so dont worry about it..
SO.. now.. everytime you click on the resources and bring up that TRIBUTE DIALOGBOX you will re
all of your resources with 25600 cool eh? :)))
well, once you have done all of that i guess all that remains is to either write down all of those op
codes or you can use my SAS tool which will grab that data for you and place it into a MASM array,
anyone coding a trainer in MASM?? your the lucky ones.. :))
FINAL WORDS
-----------
Man, i love coming to the end of a tutorial.. it means my normal life can continue :).. i hope some of
you guys have learnt something new i know i sure as shit did :).. dont forget.. no matter what you
think you know.. or how good you think you are there is always someone better, so next time that newbi
asks for a little help.. do ME a favor and help him out.. its the decent thing to do..
******************************************************************************************
******************************************************************************************
I would just like to greet some people that support and inspire me....
I'm not going to go into it but I will tell you this. Starting at 009B9F6C, there is a table of 8
encryption/decryption keys:
After those, there is another key used for encrypting/decrypting other values: 5AA5A5A5h
Now, the reason why we overwrite all these keys with 0 is because of the way the
encryption/decryption scheme works. Its a simple XOR. In case you didn't know, anything XOR'd
with 0 is itself. So therefore, when the program attempts to encrypt/decrypt values, they will always
be the originals.
Once you've patched your exe you can train away and find values a lot quicker. Or if you'd prefer, you
could add code to your trainer to overwrite the keys. Just remember, the game has to be launched
from the trainer so you can overwrite the keys immediately otherwise it will most likely crash after
having encrypted some values with the keys and then having them changed to 0.
NOTE: [sheep] has already done a very good job of explaining how to train this game in his
tutorial and I recommend you read it and learn it. I'm just posting this to open your eyes to a
different way of going about things and to save you some hassle on finding values.
Well that about covers it. I won't be going any deeper into this one.
- mrboggles
[Age Of Mythology v1.0]
Resource / Population Hacking
[PREFACE]
This is my quick and dirty solution to a resource hack for
Age Of Mythology. I will say that [sheep]'s method is by far
more efficient as it only modifies YOUR resources. With this
method the game will modify everyones resources, including
the computer.
[HACKING RESOURCES]
//Begin basic n00b tutorial now
So the problem per say with Age Of Mythology is that the game
used a single function to set the values for a number of things.
It uses the function so that peasants gather resources, like
gold from a gold mine or food from a sheep. This routine was also
responsible for changing the values of the resources depending
on if you had gained or lost some. Also it seems to affect the
"tooltip" part of the game, where if you hold your mouse over
something to build, it will tell you how many resources are
required. By NOP'ing some of this function it would display the
stats for the cost of a peasant. Which in my opinion is very bad
and looks very amatuer.
Eventually you should come down to like 3-5 addresses, all 4 bytes
each, and in order. For me i had 42059C8, 42059C9, 42059CA. Next
put a BPM W on the address and see if SOFTICE pops. (If you are
using TSearch, the autohack option is the same thing as a BPM)
If we NOP this line we will get a variety of errors that make this
a bad method of doing this hack. This prevents new values from being
written into memory, so the game will never adjust resource values or
anything else. Your villagers will chop wood forever, yet never take in
a single piece of wood. Also that display error I mentioned earlier occurs.
So here is our dilemma, we want to prevent the game from adjusting the
values but we can't do it here. Okay well, it took me a while to figure
it out because I wasn't thinking clearly. If we look at the routine in
WinDasm we see that this routine is called 9 times. If you double click on
any of the CALL addresses you will go to that part of the code. I looked
through each of the nine functions and :0058601D contained something interesting.
[HACKING POPULATION]
Population is controlled by another routine, the value is XOR encrypted as well.
You should get 3-4 addresses again, BPM on the last one with SI and you
should pop here:
If you NOP :00535783 you can build as much as you want, and your population will not increase.
[CONCLUSION]
In conclusion, if you trace back far enough eventually you will find where the game code
actually modifies your values using your run of the mill inc/dec add/sub operations so
from there you can change it to whatever you want. However as noted above, the computer
also uses the same routines to adjust its values so when it spends, it will gain the
resources too. This is why [sheep]'s solution is proper. Mine is the simple solution,
but simple isn't always better.
^chaos^
idxchaos@hotmail.com
www.s-i-n.com/chaos/trainerology.htm
<~~greets~~>
[sheep], MiCRal, Archmage, MrNOP, Visual Perfection, MiraMax, cppdude.
#gamehacking on efnet
By Dumbhead 2003
I'm not sure if this is the correct forum for this, but the most important code I will be showing is
mostly asm, so I'll start here. Feel free to move it if it's not.
I was checking out Sheep's tutorial/trainer for Age of Mythology and figured there had to be a better
way of handling the DMA for the resource values. Turns out there is, atleast for single player mode
not sure if this works for multiplayer or not.
I won't go through all of the groundwork, as Sheep pretty much covered it.
From breaking on a memory write to the resource area after purchasing a villager, and then riding the
ret, we get back to this area of code:
CODE
Through some investigating, we come to the conclusion that this is the function call that reduces your resources after you start to build
something. We find that this function is also used by the computer, so we can't just go nuts with the NOPS.
Through our own genius analysis, we figure out that ESI is a pointer to some player-specific structure, and that [ESI+244] holds the
pointer to the beginning of the resource memory for the current player being processed.
But there's no way to tell which player is currently being processed... Or is there?
In fact there is. After riding through here several times with user and computer purchases, we notice a constant pattern. The value of
ESI is always the lowest when your player is being processed. Therefore we can use the value of ESI at this juncture to tell us if this is
us or the computer. You will need to use a code cave to accomplish it.
I chose the following address for my code cave, although Im not sure if it will cause any problems later: 0x400a1f
CODE
jmp 400a1f
I don't worry about NOPing the addresses between it and the operation at 5381e3, because those addresses will never be accessed
anyway.
CODE
offset 0x400a1f
push edi
lea ecx,dword ptr ds:[esi+244]
call 585fe0
jmp 5381e3
offset 0x400a5f
jmp 5381e3
I use 400a10 as a place to hold some memory that will hold the lowest pointer value, and 400a14 will hold the pointer to the resource
memory.
First I check to see if 400a10 is zero. If it is, then this is the first time we've been here, so we go ahead and set the value to the current
value of esi.
If it is not zero, then we test the currently stored value, against the currently processed value, and if the stored value is greater or equal,
then we need to store esi. If it's not, then it's definitely a computer player, and we just execute the regular code. (We could do some
other stuff here, like reduce their resources even more, since we know for a fact that this is not us.)
There is a catch to this scheme. The value at 400a14 will not hold the pointer to the player's resource memory until the player has
purchased something. It may contain zero, or it may contain the pointer to a computer opponent's resources.
As soon as we buy a villager, however, it will point to our resources, and we can manipulate it at will.
So now what? Well, we want to set some hotkeys for our trainer which will increase the value of our resources at will. I'll do it a bit
different than sheep, instead of setting it at a fixed number, it will increase the resource by a specified number each time you hit the
hotkey. So we would have some functions like this:
CODE
if (!proc)
return;
float f = 0;
DWORD val = proc->readInt( (void*)addy );
val = val ^ 0x12345678;
memcpy( &f, &val, sizeof( val ) );
f += add;
memcpy( &val, &f, sizeof( val ) );
val = val ^ 0x12345678;
DWORD dw = val;
addM emorySet( (void*)addy, &dw, sizeof( dw ) );
setAllM emory();
}
if (!proc)
return;
float f = 0;
DWORD val = proc->readInt( (void*)addy );
val = val ^ 0x09abcdef;
memcpy( &f, &val, sizeof( val ) );
f += add;
memcpy( &val, &f, sizeof( val ) );
val = val ^ 0x09abcdef;
DWORD dw = val;
addM emorySet( (void*)addy, &dw, sizeof( dw ) );
setAllM emory();
}
DWORD addy = 0;
float f = 0;
DWORD val = proc->readInt( (void*)addy );
val = val ^ 0x0badf00d;
memcpy( &f, &val, sizeof( val ) );
f += add;
memcpy( &val, &f, sizeof( val ) );
val = val ^ 0x0badf00d;
DWORD dw = val;
addM emorySet( (void*)addy, &dw, sizeof( dw ) );
setAllM emory();
}
float f = 0;
DWORD val = proc->readInt( (void*)addy );
val = val ^ 0xdeadbeef;
memcpy( &f, &val, sizeof( val ) );
f += add;
memcpy( &val, &f, sizeof( val ) );
val = val ^ 0xdeadbeef;
DWORD dw = val;
addM emorySet( (void*)addy, &dw, sizeof( dw ) );
setAllM emory();
}
These functions make use of a set of generic classes I am creating for game hacking, but you should be able to get the idea of what it is
doing. If not, ask and I'll try to explain it. Eventually I will be releasing the source to the class library. I'll also probably be releasing a fully
functional trainer with source for AoM that uses this soon. Just want to add a few more cool options I'm working on first :)
later
The Immortal Descendants
Level: Date:
Beginner Aug. 14, 2000
Training Arkanoid 2000 v1.5
The Immortal
by Muad'Dib muaddib(at)immortaldescendants(dot)org
Descendants
This is a very easy game to train and is great for the beginner. For this essay you will need Arkanoid
2000, Teraphy's Trainer Creation Kit, and MASM.
http://www.terminalstudio.com/files/arkinst.exe
http://unixfu.box.sk/files/tools/pc_tck41.zip
http://masm32.cjb.net/
For this trainer we'll be using Win Mem Search v1.0 (included in the TCK v4.1). Load up the game in
Win Mem Search and start a new game on any episode you want (easiest on Episode III).
As soon as you begin to play, notice that the score has 5 digits, seemingly a WORD for the score.
ALT+TAB out of the game and do a WORD search for 0 (or your current score) and then go back in.
Get a few points and note down the score and then ALT+TAB again. This time put in your current
score but do "Continue Search" in order to search through all of the previously obtained results. You
should only have a few results. If any at all show up in the list box, click memory patch, otherwise, if
some were found, repeat the process.
Alt+TAB back and note down your new score. Then go back to the memory searcher and find your
score as the far left value in the list box. This is the memory location for score. Why is this? Because
Win Mem Patch sets the values incrementally if it has a narrow enough array of search results. Now
we are going to do the same but with balls. Start a new game and note down how many balls you
have. Do a BYTE search this time (balls have 2 digits) and then continue to play. Each time you get a
new ball (a +1 icon falling when you hit a brick) continue the search. Once you have a narrow enough
array of results, do a memory patch and then go back and note how many balls you have. Then do the
same as you did with score to get a memory location. Here are the results I got:
Now to make a trainer. I'd reccomend looking in your API guide for how to use the API functions I
use. Here is a source listing:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
ArkanoidWindow db "Arkanoid2000",0
.data?
hWnd_Arkanoid dd ?
pid_Arkanoid dd ?
process_Handle dd ?
number dd ?
hInst dd ?
.code
main:
invoke GetModuleHandle, 0
mov hInst, eax
invoke DialogBoxParam, hInst, 1, 0, OFFSET MainDialog, 0
.elseif ax == 102
invoke ExitProcess, 0
ret
.elseif ax == 103
invoke MessageBox, hWnd, OFFSET About, OFFSET About_Title, 0
.endif
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd, 0
.endif
ret
MainDialog ENDP
end main
I hope you enjoyed this essay and learned something. This technique can be used in many games. I
hope to bring you an essay on savegame editors and more advanced training soon.
muaddib(at)immortaldescendants(dot)org
~+---------------------------------------------------------------+~
| Date: 6-30-2003 |
~+---------------------------------------------------------------+~
NOTE: THIS TUTORIAL IS BATTLEFIELD 1942 SPECIFIC. IF YOU DO NOT HAVE BATTLEFIELD
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
Table of Contents.-.-.-.-.-.-.-.-
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
1. Introduction | . | |
7. Closing Statements |
--------------------------------+
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
1. Introduction.-.-.-.-.-.-.-.-.-
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
For best viewing: Non-Maximized Notepad Window --- 1024 * 768 Monitor Resolution.
I have done my best to make this tutorial incredibly throurough, easy to understa
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
TSearch 1.6
Description: TSearch is a very very good easy to use memory searcher. It is used
Description: Trainer Maker Kit is an easy to use tool for making trainers. No pro
* I apologize if these links are dead, as of the date posted in the header they w
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
3. Skills Needed.-.-.-.-.-.-.-.-
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
Patience
Light Typing Proficiency
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
4. Trainer Compatability.-.-.-.-
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
RTR
:) - Pure/Non-Pure Servers - :)
This trainer will work under pretty much any condition unless it is patched by EA
This trainer will only work on your machine. The fog memory address is known as a
I am currently working on a Fog Removal trainer that uses code injection techniqu
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
Start TSearch
Click BF1942.exe
In TSearch Click the Magnifying Glass Under the Open Process Button
Click Ok
In TSearch Click the Magnifying Glass With the Ellipse (...) by it Under the Open
Click Ok
^^- You Will Now Have 1 Address This Address Will Appear Under the Magnify Glasse
Close TSearch
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
Click Create
In the Styles Tab Enter Remove Fog in the Caption Text Box
In the Pos Tab Enter 14 in the X-Pos Text Box ~|-|~ Enter 10 in the Y-Pos Text Bo
In the Key Tab Click Shift ~|-|~ Enter F in the Hokey Text Box
Select Add
Select Word
Enter the Memory Address You Found and Wrote Down in the Address Text Box
Enter 300 in the Value Text Box
Click Apply
Click Apply
In the Styles Tab Enter Replace Fog in the Caption Text Box
In the Pos Tab Enter 105 in the X-Pos Text Box ~|-|~ Enter 10 in the Y-Pos Text B
In the Key Tab Click Shift ~|-|~ Enter R in the Hokey Text Box
Select Subtract
Select Word
Enter the Memory Address You Found and Wrote Down in the Address Text Box
Click Apply
Click Apply
Click the Bottom Right Corner of the Interface to Resize the Window.
Resize the Window So That it Looks Good With the Buttons Where They Are
Click the Build Settings Tab Near the Bottom Left Side of the Window
Double Click the Yellow Box Right Next to the Gray Box Thats Says Process Name
+=+ The Box Will Turn White and an Ibeam Will Appear
Enter BF1942.exe
Double Click the Yellow Box Right Next to the Gray Box Thats Says Exe Name
+=+ The Box Will Turn White and an Ibeam Will Appear
Double Click the Yellow Box Right Next to the Gray Box Thats Says Exe Type
Select Linked
You're done, the trainer executlable file is now located in the Trainer Maker Too
Remember what you named it. Once you find it put it on your desktop or wherever i
_________________________________________________________________________________
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
7. Closing Statements.-.-.-.-.-.-
,.-'`'_.,.-'`'_.,.-'`'_.,.-'`'_.,
Congratulations you now have a fully functional fog remover that works under almo
By Clicking Remove Fog or pressing Shift + F in game you reduce the fog by 300% e
By clicking Replace Fog or pressing Shift + R in game you increase the fog by 300
This trainer is more effective then the average no fog hack. The reason is becaus
****WARNING=-=-!+!****WARNING=-=-!+!****WARNING=-=-!+!****WARNING=-=-!+!****WARNI
ONLY REPLACE THE FOG AS MANY TIMES AS YOU REMOVED IT OR YOUR GAME WILL CRASH CAUS
****WARNING=-=-!+!****WARNING=-=-!+!****WARNING=-=-!+!****WARNING=-=-!+!****WARNI
| | || | |\ | | |
| | || | | | \ | | |
.'.
. '.' .
This time we don't search the memory locations with SoftICE, we will use a famous tool called
'GameHack' (http://www.gamehack.com/), but you will need SoftICE anyway, just to have a deeper
look at the process and the stuff that is going with the data/code you want to patch in memory. Now
let's begin, run the game and have a first look.
The process list will show up, look for the name of window of the process we want to train ("Beavis
and Butt-head Hock-a-Loogie"). Select it with your mouse and click the OK-Button. Start a new
search for an *Exact value*, a type of *4 Bytes* in *Decimal* base. As Value1 you take your current
score - remember we had a score of 0/20. So you take '0' and click the OK-Button. Wait until the
search has finished (it is rather slow, because it "mirrors" the process to a temporary file on your
hard disk). A message box will be shown saying "Too many addresses found, they wont't be shown" -
click the OK-Button, the addresses have been saved. Switch to the game and try to spit onto the
bicycle, your score will be 2/20. Back to GameHack you do a "next search" and feed the textbox with
your current score (yes, 2). After you made and drunk your coffee GameHack has found a few
addresses, mine has found 3 addresses, they all contain the value "2" of course.
But we need to go on until we have the exact location where Hock-a-Loogie stores the score. We
could test it by patching different values into each address, but we don't want to crash the game
(though I assume the score sleeps in 412F74). So spit another time onto a bicycle, you will have a
score of 4/20, so you can do a next search with the value "4". Most probably you now have the exact
address. For my session it was 412F74.
So this is where SoftICE comes into play. We want SoftICE to pop up when the game accesses this
memory address (412F74) by writing to it. This can be done with the SoftICE command "bpm". It
will break on access of a specified address. You can look it up in SoftICE with the help command "h"
- just type "h bpm" and SoftICE will display a short description of the bpm command:
Breakpoint on memory access BPM[size] address [R|W|RW|X] [debug register] [IF expression] [DO
bp-action]
We need the "double" type; remember we were searching for 4 bytes? For the "address" parameter
we take the address GameHack found (412F74), the next parameter must be "W" for write access
only, so SoftICE will break if your score increases. What we have to do now is switching back to the
game and pressing CTRL-D to get into SoftICE. Be sure the active process is the game (in this case
you will see the string "Loogie" on the bottom of the SoftICE "window" at the very right). Then you
can bpm on our address (bpmd 412F74 W). Get back to the game (x^) and score ;) Sice pops up:
:00403320 CMP DWORD PTR [0041453C],0
:00403327 JNZ 00403334
:00403329 MOV ECX,[ESP+04]
:0040332D ADD [00412F74],ECX
:00403333 RET
SoftICE broke in at relative virtual address 403333. Look at the code above, especially at RVA
40332D. It adds the double stored inside ECX to address 412F74. Remember this address? Yeah,
this MUST be the location where the score is stored, as SoftICE broke in immediately after the code
at RVA 40332D (and... by the way.. it was the address we were talking of all the time). What else can
we get from the code? It must be static data, because the code adds ECX ALWAYS to [00412F74] -
and- I do not assume that we have a case of self modifying code.
What does all that mean for our trainer?. It means we can for sure add some score by writing into that
address directly - no patching of code or seeking for the address, as it is fixed. Now it's time to begin
coding the trainer. We will use a hotkey that will add some score. GetAsyncKeyState will be the
perfect API for it. So look it up in the Win32 Programmer's reference (win32.hlp) :-
The GetAsyncKeyState function determines whether a key is up or down at the time the function is
called, and whether the key was pressed after a previous call to GetAsyncKeyState.
excellent... now the standard stuff for doing a trainer: WriteProcessMemory is the API that we have to
use to write to memory. WriteProcessMemory needs a handle to the process to patch.
BOOL WriteProcessMemory(
This handle can be retreived with OpenProcess, but OpenProcess needs a process identifier .
HANDLE OpenProcess(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle, // handle inheritance flag
DWORD dwProcessId // process identifier );
This process identifier can be retreived with GetWindowThreadProcessId, and we finally need a
handle for the window to pass to GetWindowThreadProcessId.
DWORD GetWindowThreadProcessId(
HWND FindWindowEx(
HWND hwndParent, // handle to parent window
HWND hwndChildAfter, // handle to a child window
LPCTSTR lpszClass, // pointer to class name
LPCTSTR lpszWindow // pointer to window name );
So we finally got the basic APIs for our trainer: FindWindowEx, GetWindowThreadProcessId,
OpenProcess, WriteProcessMemory and GetAsyncKeyState. Another API that we will have to use is
ReadProcessMemory to read the game's current score to a variable, then add the value we want and
finally write it back.
The ReadProcessMemory function reads memory in a specified process. The entire area to be read
must be accessible, or the operation fails. BOOL ReadProcessMemory(
invoke GetAsyncKeyState,VK_F12
invoke TrainProc
.endif
Return to Trainers
Start up this game, and look at it. To the right you see that you have six balls left to play with. Since I'm
not very good at arcanoid, I want to have some more. ;-) Make a copy of the main .exe-file and
disassemble it. Look in the string-references for "Balls left:". You'll see that the string is a resource, with the
ID 00027. Since the string is a resource, we could tell that when the program needs to use it, it has to call
LoadStringA, and that's useful to know. If you search for it in the disassembly, you'll find that W32Dasm
finds it at many different locations, but only one is followed by a call to LoadStringA, and that's the real one.
Take a look futher down. We see a reference to the string " %u ". Now I'm really convinced, and I
think that everybody who knows the syntax for the formatspecifiers for sprintf in C is too. And what do we
see right after that? Yep, a call to wsprintfA. We've come right! ;-) The syntax for wsprintfA is:
"..." is the arguments that should be formatted according to the FormatSpecifier and be placed as a string
in DestinationBuffer. So what does this program pass to wsprintfA?
movsx eax,si 1
push eax 2
lea ecx, dword ptr [ebp+0ffffff00] 3
push 414110 4 This is the formatspecifier, "%u"
push ecx 5
call wsprintfA 6
Okey.. We'll find the most interesting thing on the top. In this case, ecx is set to point to DestinationBuffer
at line 3, and is pushed as the first argument on line 5. The formatspecifier is pushed as the second
argument at line 4. But the things we want to know, is where it gets the number of balls left. At line 2 eax is
pushed as argument #3 (...), so at that point eax holds the number of balls left. At line 1, eax gets its value
from si, and if we look a couple of rows up, we see that si gets its value from a fixed memoryaddress with
this code:
Bingo! From this we could tell that the address 416700 holds the number of balls left. From this point, we
have many different ways to patch this code, let's say that we found the location where it set the value to
6 and then patched it to give us 1000 balls to play with. Or we could find the location where it decreases
the value when you loose a ball and nop it out. But if we don't always want to be cheaters then? Wouldn't it
be nice to have a button to push every time you want to have more balls? I definitely think so.. Let's open
this program in Resource Workshop. You'll see that it has a couple of dialogboxes, most of them for the
leveleditor, but the last one is the About-box. Open that one in edit-mode and simply add a button, set the
text of it to "Cheat" and make sure to note the Control ID of it. Save the whole project, start the game
and open up the about-box. Hehe, there's our nice button, but nothing happens when it's clicked. Let's fix
that! Remeber from Resource Workshop that the dialog ID of the about-box was 114? Anyways, it is. 114
is equal to 72 in hex, and that's what we need to find the message-procedure of the about-box. Back to
W32Dasm, and click the Dlg-ref button. The second last in the box is "Dialog: DialogID_072", and that's the
one we're looking for. Doubleclick it to find that it is displayed with DialogBoxParamA. This is what win32.hlp
says about that API:
int DialogBoxParam(
HINSTANCE hInstance handle to application instance
LPCTSTR lpTemplateName identifies dialog box template
HWND hWndParent handle to owner window
DLGPROC lpDialogFunc pointer to dialog box procedure
LPARAM dwInitParam initialization value
);
So the fourth argument of this API is the offset of the message procedure. Look in your disassembly, and
see that the fourth argument in this one is 40192E. This is the first point we should patch this program at,
but not yet. Let's think of what we could do in this situation. We've got a button in the dialog, the offset of
the message procedure and we've got the location where the message procedure of the dialog is set. What
if we included some of our own code into the .exe, which would check if the messages sent to the
dialogbox is WM_COMMANDs from our button, and if it is, we do some cool things, if it's not, we just pass
t he message to the original procedure? Sounds like a good idea to me! ;-) Now, we've got another
problem. Where are we going to put our code? What would Win95.CIH do in this situation? Yes! It would fill
up one of the gaps that is present in almost every PE-executable and then just make a slight change in the
header of the file to make sure that enough memory is allocated when the game is loaded. Let's do the
same! Open the .exe in HIEW and go to disassembly mode. Press F8 to get info from the header and press
F6 to get the object-table. We'll see that the biggest object is .text, and that the PhysSize of it is 11E00
bytes, but the VirtSize is only 11C8C bytes. That means that the object has 372 unused bytes at the end
of it, and that should be more than enough for our code! To find out where the used code ends, just add
the VirtSize with the RVA and the imagebase (11C8C + 1000 + 400000 = 412C8C). This will be the offset
of our code, and therefore, we could now do our first patch. We change the fourth argument to
DialogBoxParamA from 40192E to 412C8C, and now we've redirected the messages to the spot where
we're going to put our code. The next step is to write the code at 412C8C, but first we need to list what
we're going to do.
Now there's only one thing left, to update the header. The last byte after our code is at 412CBD. To get
new VirtSize, subtract it by the imagebase and then by the RVA of the object (412CBD - 400000 - 1000 =
11CBD). Switch to hex-mode in HIEW and go to the beginning of the file. proceed a bit and you'll see the
.text-label. The VirtSize is specified 8 bytes after the label begins, and should look like this: 8C 1C 01 00,
since the old VirtSize was 11C8C. Change it to: BD 1C 01 00, and you should be ready to go! Exit HIEW
and start up the game. It should give you six balls to play with. Open the about-box and press the Cheat-
button, and you should have 10000 balls to play with!
-* TMG *- Copyright © 00/2001 TMG. Credits: Automatization by flaket - Web. and Stats by Statman - Gfx and design by tHE EGOiSTE
Caesar III Demo Tutorial
Requirements: Caesar 3 Demo, Memory Editor (Gamehack 2.0), Softice (Softice 3.22.)
This tutorial assumes you have softice installed and a basic knowledge of it.
3. Select name.
5. Alt-tab to windows.
9. Choose Search: "Exact value", Value 1: 6500 , Type: 2 Bytes and click ok.
11. Return to the game and spend some money, I chose build housing. (note the amount of money you have after
spending)
13. Click the binoculars with the arrow under it for next search.
20. Go into the game and spend some more money noting how much you have left after spending. (I chose house again)
22. Go into gamehack and see which value matches your money. (mine is 29990)
23. That means that the bottom value is the real one so click the top value (click on description) and delete it.
24. Now write down the real value. (mine was 00574DB8)
27. Type "bpm 00574DB8 w" and hit enter, this sets a breakpoint on your address and it will break upon any write.
31. Since the game is subtracting money we look for a "SUB" above the code softice landed on.
32. The code in green is the "SUB" command we are looking for.
33. Double click the green code in softice, that sets a breakpoint at that address. (if any problems, type in "bpx
004B36BD")
34. Type "bl" and hit enter. (this lists all current breakpoints)
38. Type "a" and hit enter, type "nop" enter, "nop" enter, "nop" enter and hit <ctrl-d> to exit softice. (if any problems
you can manually nop the address by typing "a 004B36BD" and then the nops.) (the reason you nop 3 times is this, the
code is 2B450C so you nop once per 2 digits, 6 divided by 2 is 3)
39. <ctrl-d> to enter softice and type "bc *" to clear all breakpoints.
41. Now you can create a trainer that nops address 004B36BD 3 times, or 90 90 90 which is nop in machine language.
42. Enjoy...
Written by Logician
Proud member of X²
TUT no2
~~~~~~~
Hacking Captain Claw - Advanced GameHacking
INTRO
~~~~~
Hello boys (and girls), fans of game-hacking!
Well, in the following I'll show you (in case you already know) how to
hack a game using it's own cheats !
THIS TUT IS A GENERAL PROPOSE HACKING, BUT I'LL USE A SKELETON GAME TO BE
MORE CLEAR ! REMEMBER, IT'S NOT A SPECIFIC GAME!
IF YOU PLAN TO LEARN SOMETHING USEFUL ( OR REMEMBER SOMETHING YOU ALREADY KNOW ),
READ THE FOLLOWING WITH THE MIND, NOT THE EYES !
===========================V I C T I M================================
===========================T O O L S================================
========================H A C K - T Y P E=============================
What we'll hack ? Oh, a good question ! I will not show you how to hack
the pistol ammo or grenades (because it'll be boring and too easy !) !
This game has it's own cheats, you know. It has some cheats for the ammo,
and some good cheats that will help you much more than some bullets !
One of these is "MPJORDAN" ! If you type this in the game, your cat will jump
higher (it's called "SUPER JUMP MODE") ! But if you type the cheat, the game
will not save your finished-level and you will be treated like a fuc*ing
cheater (i.e. : no high-score etc, etc) !
SO, I'll tell u how to make a trainer that fools the game -- you will be
using the SUPER JUMP MODE, but you will not be a cheater for the game
(your game will be saved as well as the high-score !) !
================H A C K - T Y P E - E X P L A N A T I O N==================
Explanation of the game routines (in general). This routine is not valid for
money/ ammo/ health/ resources cheats, as well as any other cheat that
affects the QUANTITY (with some exceptions)...
Most of games that have their own cheats think and act like this:
2) Gamer wants to use the benefits of the cheat (walk through walls,etc)
or it does different actions in the game or he just plays the game:
3) Gamer finishes level, reach rally_point, accomplish the mission, reach the goa
check var2. If var2=FALSE ==> good gamer, save his score, give him another
mission etc
else ==> cheater, don't save his character or score,
or the most annoying thing: put the word "CHEATER"
in the front of the screen, wrote with hate (and
the red color). Man, I hate when someone calls me
a cheater (even if I really am one :)
variables:
- var1 that holds the curent state of the cheat (ON/OFF) -- this was initially
- var2 that holds the state of the gamer (FALSE/TRUE). At first this is OK for
the user (game is started with no cheat, and var2=FALSE ==> good gamer!)
but in the moment that he typed a cheat, or the game finds var1=ON,
var2 will be against him all the game (var2:=TRUE)! And this var will NO
modified again! This means that if the gamer deactivate the cheat, he
will remain a cheater for the game and will be treated like a cheater!
In short words: THIS VAR WILL BE CHECKED AT THE END OF THE LEVEL AND IF
GAMER CHEATED ==> NO HIGH-SCORE for him !
1) Trap the var2 and set it to default (FALSE ==> the gamer is "clean") even if
he cheated
2) Use that part of program that makes the good thing in games (i.e. : jump highe
be invincible etc) CALLED from a different code than the original one
(original one = the one that it's being executed when we type a cheat) !
I'm a lazy bastard and I'll show you the SECOND method !
====================H A C K - B E G I N I N G==========================
Start:
STEP 1 :Enter the game and pause it (press [ESC]). Do ALT+TAB and start the
mem. finder (in my case is Game Trainer).
As process, select Claw.exe then click the dump button! Wait until it
finished dumping the mem.
STEP 2 :Go in the game and type MPJORDAN to ACTIVATE the cheat! Pause the game
again and ALT+TAB. In Game Trainer hit the Diff button ( the "var1"
changes ! it's the one we want ! )
STEP 3 :Go in the game and type MPJORDAN to DEACTIVATE the cheat! Pause the
game again and ALT+TAB. In Game Trainer hit the Diff button ( the
"var1" changes again! )
STEP 4 :Follow SETP 2 and STEP 3 until you have ONLY a few memory addresses
( a few <= 6, less or equal ! )
STEP 5 :Look at the memory addresses and grab the ones that holds 0 OR 1
( usually, 0=cheat disabled ; 1=cheat enabled ). If none of the mem.
addr. holds 0/1, you should use REPLACE AND TEST METHOD ( fill a mem.
addr. with diff. number and test it ! if nothing happens, go for the
next mem. addr. and change it ! Repeat this procedure until you end up
at the desired place ! if this fails, it means that you didn't find the
correct addr., OR the game has some in_game_checks, OR the number you
written is not corresponding to the game calculations etc, etc ! In thi
case you must "play" more with the found addr. ! ) ...
Fortunately, we have a memory addr. that holds 0/1 ! It's a static one,
and let's say it's 3021000 !
STEP 6 :OK ! Address found ! To check this is the right address, switch it
( 0:=1 or 1:=0 ) and go inside the game ! If you have the cheat ON, go
ahead and jump ! You'll notice that your jump will be normal (like when
the cheat is OFF) !
STEP 7 :Now comes the SoftIce part ! Let's put a breakpoint on that address ! But
what kind of breakpoint ? Let's think : If we put a write only breakpoi
SoftIce will pop only when we type a cheat ! We don't need that ! We wa
SoftIce to pop when the game checks if the cheat is ON\OFF. This means
game reads the addr., then do the check ! So, we'll put a read_only bre
BPM 3021000 R
STEP 8 :Jump inside the game to pop SoftIce ! SI popped, take the instruction's
address ! Press F5 again, take the instruction's address ! Mmmmm, we ha
2 different addresses... F5, SI popped at the previous address ! Wow !
F5 again, SI pop at the same address ! What the fuc* ? F5 UNTIL you are
back in the game ! You will notice that you will have ONLY 2 addresses
Why's that?
STEP 9 :SI kept popping at the second address. And the pops were during the
different altitudes the cat reached from the time you jump! This means
only one thing : WE HAVE FOUND THE CODE THAT MAKES YOU JUMP HIGHER WHEN
THE CHEAT IS ENABLE !
Game is checking the cheat state ! If the cheat is OFF, jump to the
non_cheating code (that lowers your jump) ! If the cheat is ON, process
the code for the SUPER JUMP MODE !
STEP 10 :If you want to build a trainer, all you have to do is to patch the memor
to change the conditional jump jz at yyy:yyy:yyz into a jnz (or 2 nops
But what about the first address where SI popped at the first time
(at xxx:xxx:xxx)? And what about that "add eax,ecx" ? Can this be the
calculation of the altitude (i bet it is :)? Strange questions, heh ?
========================T R A I N E R - C R E A T I O N============
I'll skip this part, I assume you already know how to use TMK !
NOTE : At this type of hacking, you mustn't poke in memory big numbers (of money,
resources, etc), you must patch the game's code in memory !
===========================L E G A L - S T U F F=====================
Nothing to say here, you can have this tut on your sites, you can change it if
you have better ideas or if I did some mistakes - correct me !
Sorin ( Splinter@email.ro ).
2003
eof
Tutorial Author: Razali Rambli @ Bie
Email: razali_bie@hotmail.com
Homepage: http;//bie.cjb.net
Tool:
Tsearch
This is a not a tutorial on Tsearch, this is a tutorial on how to make God Mode and Instant Kill in Cold Zero Demo.
So it is required to you to know Tsearch to be able to follow this tutorial.
CODE
004998c3 895040 mov [eax+0x40],edx
004998c6 8B4DDC mov ecx,[ebp-0x24]
004998c9 C781FC01000001000000 mov dword ptr [ecx+0x1FC],0x1
004998d3 8B4DDC mov ecx,[ebp-0x24]
004998d6 E8F59BF6FF call 0x004034D0
004998db 85C0 test eax,eax
3. put r/w bpx on your health address, found this, look at register, yep... only our pointer... not
shared between human and ai.
CODE
004a51d4 837A4000 cmp dword ptr [edx+0x40],0x0
004a51d8 7F29 jg short 0x004A5203
004a51da 8B45E8 mov eax,[ebp-0x18]
004a51dd 8B8888030000 mov ecx,[eax+0x388]
004a51e3 E8B882F7FF call 0x0041D4A0
4. use my Code Cave tool on it, make code cave at address 40032F
5. i test it, get hit or get shot, my life still 100%, get hit more than enough that should make my life
reach 0, but the life bar still show 100 and i still alive, try to hit all the enemy, they all die instantly...
huahahaha...
GOD MODE & INSTANT KILL trainer for Cold Zero Demo source code by ßié (if u use this, give proper
credit)
How to make instant build trainer Tutorial -- by Groza / May 2001
I wrote this tutorial in order to show you how I made the instant build
option in my trainer for Red Alert 2. Because of a great demand I will
write how to make reveal map and skip mission options too. All the tutorials
will be available to download from my page http://grozatt.cjb.net so check
it out time to time.
WHAT WE NEED ?
--------------
- SoftIce ( the best tool, can't live without it )
- Winhack
To make an instant build trainer we have to find out the code that
cares(calculates) how long something will be building. There are many
possibilities how to find it out. I will explain just one of them, which
worked fine with me. Now if we think a little, there should be some parameter
in memory that is increasing or decreasing(depends on the game) during the
build. We are going to find it out.
So let's start building something. Now during building process we have to
find all the memory locations which are decreasing or increasing. First we
will try to find out those which are decreasing. In the game we start
building Barracks and as soon as it starts we pause the game(we press ESC),
ALT+TAB to WinHack choose the process of RedAlert 2(game.exe) and start
searching the locations. Then ALT+TAB back to the game, unpause and wait a
little. Back ALT+TAB to Winhack and use the -has decreased- option to search
only those memory locations which were decreased since the last search.
Then back to the game... we need to repeat doing this till we don't find only
one or few locations.
In Winhack we can also use other options like -has decreased by Less than %-
which can be very useful but I won't explain them here.
OK, everything should come well and we find the location(by me is 88FCEEC).
Let's check it out.
Back to the game and ALT+D to Softice. Be sure that we are in RA2(game.exe)
and not in some other process. Let's put a breakpoint on the address
bpmb 88FCEEC w and ALT+D to return to the game. SoftIce should pop up.
But don't give up, let's check that cmp at the 004B953E. Seems it's comparing
the location pointed to [esi+24] with 36 hex. Let's check it out, disable
all breakpoints and put a bpmb [esi+24] w.
Hm, we can see that here is some other counter, which increases something.
And when it reaches 0x36 it is done. OK, let's modify the code in this
way then:
mov edx, 36
nop //this 3 additional nops are because this instruction is
nop //shorter than that we've replaced
nop
mov dword ptr [esi+24], edx
OK, disable all breakpoints and let's go back to the game. YES, IT WORKS !!!!
We have the instant build. Now we only need to make a trainer that will
modify the code when we press a button.
And that's all that has to be done. Easy isn't it ?
Please check the tutorial section on my page to find out more about
writing a trainer...
Greetz to MICRaL from TekZ 8193 for trying to make my page better !
Email: grozatt@email.si
Web: http://grozatt.cjb.net
Tutorial Author: Razali Rambli @ Bie
Email: razali_bie@hotmail.com
Homepage: http://bie.cjb.net
Other known method to contact the author
http://www.gamehacking.com/ipb/index.php
http://www.devious.tsongkie.com
http://www.extalia.com
Introduction:
I have seen lots of trainer for this game and have try it all. They are great trainer with infinite money, power, speed build, etc.
But the bad thing is, all the trainer also give benefit to the AI (computer player) thus making it is more difficult than ever.
So, after I get a tips from The Lord Of The Gamehacking, [sheep] I manage to get speed build for Command and Conquer General Zero Hour.
I decided to created a tutorial on making one side speed build starting from Red Alert 2. I hope I have time to make tutorial for One Side speed
build for General Zero Hour.
So, let get started and enjoy the tutorial. Remember, this is not a tutorial on using the tool, this is a tutorial on making speed build option. Learn
to use the tool and read the method tutorial.
Target
Tools
1. Tsearch http://membres.lycos.fr/tsearch/
2. Bie Code Cave Tool http://bie.cjb.net
Method
Collecting Info
When we building something in Red Alert 2, we don't see a numeric value to give us a hint on our building progress. The only indicator are a
layer of translucent blue on top of the building we wish to build and it will move clock wise to show us the building progress.
Since we don't know how much is the value are, we can choose 3 type of search in Tsearch
1. Unknown, Increase
2. Unknown, Decrease
3. Unknown, Change, Not Change
Choose one of the search method above, for this tutorial, I choose the 1st method. Remember, different game have different method.
Opcode
After you have found the address, we have to put a write breakpoint on it to get to the opcode that control the value.
Then I let the game finish building and I look at my address, the value inside it show 54, so now I know that when our value reach 54, that
mean our building is complete.
So what we need to do it just make our value that is put inside the edx register with 54 and it will build instantly.
Since this address is share between human player and AI player, we need to find a staple intersection. So to find the staple intersection, we
have to put read breakpoint on our address.
1. Pause the building by right click on the building icon, don't pause the game, just alt+tab out
2. So in autohack, put a Read/Write breakpoint on our address.
3. Get back to game and don't do nothing, just alt+tab out again.
We will find a few breakpoint. But we only need only one that are not shared. In autohack, click the read breakpoint and register it one by one
one. At Register tab, just focus on register in the bracket [ ].
4. Get back to game and don't do nothing, just alt+tab out again.
Look at the register and compare it with our pointer, if the pointer show different address with our pointer, that is not our staple intersection. So,
after looking at all the read breakpoint, only 1 opcode is not shared between human player and AI player.
Read breakpoint on our address that are not shared [Staple Intersection]
Use Bie Code Cave Tools to open the 400300 address for code injection or use Tsearch easywrite. If you don't want to make code cave there,
just use SAS at http://www.sheeprec.cjb.net
Code Cave
Offset Hex Asm Detail
00400314 8B4124 mov eax,[ecx+0x24] jump from staple intersection, original code
move staple intersection pointer to 400370 to be compare later. our
00400317 890D70034000 mov [0x400370],ecx
code
0040031d C3 retn get back to call opcode
0040031e 393570034000 cmp [0x400370],esi compare write pointer with our staple intersection pointer
00400324 740D je short 0x00400333 if equal go to 400333
00400326 8B5624 mov edx,[esi+0x24] if not equal, recreate original code
00400329 03D0 add edx,eax recreate original code
0040032b 895624 mov [esi+0x24],edx recreate original code
0040032e E9578B0B00 jmp 0x004B8E8A jump back to normal next write opcode
00400333 BA36000000 mov edx,0x36 move 36 (hex) = 54 (dec) into edx
00400338 EBF1 jmp short 0x0040032B go to 40032B
In case anyone did not get this step-by-step guide, then here is an example. I ha
Advanced Game Training Techniques - Tutorial 1
C&C:Tibieran Sun and Dynamic Memory Allocation
NOTE: C&C: Tiberian Sun was protected with SAFEDISK, which has
anti-softice code in it. This tutorial assumes you have the the unpacked
executable, mostlikely available from http://www.gamecopyworld.com/.
Also it is suggested that when you setup softice, choose the universal vga
driver if possible. Most other video drivers will cause games/your system
to freeze when popping into Softice.
If your are lucky, you should have found three values. 00712A04,
00712A08, and one other one. If you only found two, load up a different
mission or reload the game again. Continue until you get three values. I will
tell you right now that the third value is random every time, and it is the
TRUE value of how much money you have, while the other two values are
for the on screen display. Play around with ...04 and ...08, you will see that
04 holds the value which 08 has to count up or down to. If you freeze these
two values at 31337, your display will say 31337 with some fluctuation (it
will try to reset itself to its real value, but since you froze the values it will
stuggle between the two values). EFFECTING 04 and or 08 WILL NOT
GIVE YOU ANY MORE MONEY, it will say that it did, but in reality it
did not. You will run out eventually, check for yourself. You CAN however
freeze the third value, but since its random every time, there really isnt a
chance that you would write a trainer for it (without a lot of work, and this
solution is much easier and faster) and you would have to refind the new
third value every time you got to a new mission, but as i said before,
sometimes this third value can not be found. So now we begin...
Get your third random everytime memory value (i will use 00431337) ,
now pop into softice with control + d, and now type in the following
(replace my value with yours!!!!)
:BPM 00431337
Now get out of softice, use either control + d or F5. Softice should pop up
immediatley with the following:
When softice poped up, it is because your memory address that you BPM'd
was accessed at this point in the code. So.. now the best general advice i
can give is to NOP the closest MOV to where SI popped. In this case it
would be the one at the address 004B4BE0. So just replace
8B8E90010000 with 909090909090, this means that it will do nothing at
this point. This can be done by typing the following at the softice prompt:
:E 004B4BE0
Another window should pop up in softice, this one called the edit window,
here you can change values in memory (like a trainer does), change those
values above with the following 909090909090, then hit enter.
This will erase all the breakpoints you have set. If you do not, Softice will
continue popping up until you remove the breakpoints.
CONCLUSION:
Okay, I got bored towards the end too..but i really hope that this tutorial has
helped you understand the basics of using softice to edit memory. I
REALLY suggest you learn ASSEMBLY if you really want do do some
profesional, clean, trainers for games that use dynamic memory allocation
or other trickery.
IN GENERAL:
-search until you only have the true memory location left.
-BPM on the address
-enter the game
-do something that would effect the value (build something)
-Softice should pop up
-you will see something in the style of mov [addy], eax or sub [addy], 1 or
dec [addy], 1 ..anything in that style (LEARN ASM!@#!@#)
-now all you have to do is nop the instruction, closest to where si poped
usually works well
^chaos^
NOTE: C&C: Tiberian Sun was protected with SAFEDISK, which has
anti-softice code in it. This tutorial assumes you have the the unpacked
executable, mostlikely available from http://www.gamecopyworld.com/.
Also it is suggested that when you setup softice, choose the universal vga
driver if possible. Most other video drivers will cause games/your system
to freeze when popping into Softice.
If your are lucky, you should have found three values. 00712A04,
00712A08, and one other one. If you only found two, load up a different
mission or reload the game again. Continue until you get three values. I will
tell you right now that the third value is random every time, and it is the
TRUE value of how much money you have, while the other two values are
for the on screen display. Play around with ...04 and ...08, you will see that
04 holds the value which 08 has to count up or down to. If you freeze these
two values at 31337, your display will say 31337 with some fluctuation (it
will try to reset itself to its real value, but since you froze the values it will
stuggle between the two values). EFFECTING 04 and or 08 WILL NOT
GIVE YOU ANY MORE MONEY, it will say that it did, but in reality it
did not. You will run out eventually, check for yourself. You CAN however
freeze the third value, but since its random every time, there really isnt a
chance that you would write a trainer for it (without a lot of work, and this
solution is much easier and faster) and you would have to refind the new
third value every time you got to a new mission, but as i said before,
sometimes this third value can not be found. So now we begin...
Get your third 'random everytime' memory value (i will use 00431337) ,
now pop into softice with control + d, and now type in the following
(replace my value with yours!!!!)
:BPMD 00431337 W
Now for a a little explination if you did not understand that screen shot
above. BPM is the standard command, the D represents Dword (a 4 byte
value). The W means WRITE. So, when the memory address is accessed
and WRITTEN TO softice will pop up.
Now get out of softice, use either control + d or F5. Softice should NOT
pop up immediatley this time, if it did you forgot the W. In order to trigger
SI this time, you must build something. Okay, NOW SI popped up with the
following:
Okay, what exactly has happened here? Well Tiberian Sun accessed and
WROTE to our memory address so softice poped up just after. So we know
somewhere around here, in the memory, in the code, something has
decreased our value. If you scroll up 3 lines you will see a sub eax, ebx
command. This is out target, EAX is the a value of our counter and ebx is
the value of our unit. So to get rid of this command, back in softice.
CONCLUSION:
I REALLY suggest you learn ASSEMBLY if you really want do do some
profesional, clean, trainers for games that use dynamic memory allocation
or other trickery. This was the clean crack version of the tutorial.
IN GENERAL:
-search until you only have the true memory location left.
-BPM[type{b,w,d}] ADDRESS W on the address
-enter the game
-do something that would effect the value (build something)
-Softice should pop up
-you will see something in the style of mov [addy], eax or sub [addy], 1 or
dec [addy], 1 ..anything in that style (LEARN ASM!@#!@#)
-now all you have to do is nop the instruction, closest to where si poped
usually works well
^chaos^
NOTE: C&C: Tiberian Sun was protected with SAFEDISK, which has anti-
softice code in it. This tutorial assumes you have the the unpacked executable,
most likely available from http://www.gamecopyworld.com/.
Also it is suggested that when you setup softice, choose the universal VGA driver
if possible. Most other video drivers will cause games/your system to freeze when
popping into Softice.
Okay, hiew found it (well it should of). Now press F4 again and select DECODE.
This will turn all of your code into the ASM representation of it.
Now Press F3 to get into EDIT MODE. Move your cursor to line 004b7126, then
hit F2 (which is now labeled ASM). A dialog will pop up called ASSEMBLER.
Right now it has SUB eax, ebx written in there. In asm there are a variety
commands to subtract and add. The addition ones are: ADD & INC, and then you
might see some variations of it like FADD, but their functions are the same. Next,
the subtraction ones are SUB and DEC.
So lets think for a minute now. In the last tutorial we erased the whole SUB
routine, so that when we clicked to build a unit, no money would decrease. Now
we are going to change the SUB to an ADD, what this will do is, if you click to
build a unit, it will ADD cost of the unit to your total money, so the more you
spend, the more you earn. If you had just NOP'd it, you would have to rely on
gaining money by collecting it through your harvester.
Anyway, back to the Assembler dialog. Move your cursor under the SUB, now
type in ADD (so it looks like add eax, ebx) , then hit ENTER, and then escape to
close the dialog. To save the changes to your file, hit F9, which will update the
exe. Then you can exit with F10.
You now have a permanently patched exe file so that every time you build a unit, it
will deposit its cost into your bank account. However if you just want to write a
trainer for it, follow the part two tutorial and rather then writing 90 90 to memory,
you have to write 03 into memory in the same memory address for the first 90.
You do not need to modify the 0C (which is the second 90 in part II) because the
ADD function needs to know what values to add together.
FINAL CONCLUSION:
Here ends the series of the C&C:TS money tutorials. Possibly some more will
follow on how to make a reveal map, power, and fast build. The whole intention
was to teach you how to deal with dynamic memory allocation. I have taught you
several ways to track down the commands you need to find and how to effectively
patch them.
Why is patching the sub eax, ebx routine better then writing a trainer that writes to
that memory address every 1/10th of a second? Well first off all, with TS that isn't
possible because of dynamic memory allocation. The real bank account value is
moved around every time you play a level. Next, you only have to write to
memory 1 time, meaning that your trainer will not be a CPU hog. If you write the
value to memory every 1/10th of a second, you will use a lot of spare CPU. It is
best to patch the code in memory, and not write to it every second.
^chaos^
3. Stuff
If you don't manage to use this tutorial right please mail me... ==> mdk
If ya don't know how to use Trainer Maker Kit or GameHack please go to... ==> htt
Also check out my trainers and other members' at TekZ, which ya can find in the *
Wish ya luck and pls read the next releases I make... C ya...
T-RaiNeR
GAMEHACKING ... COMMANDOS 2
The tool used: TSearch.
Max ammunition for pistol = 120, rifle = 15, machine gun = 150; bazooka = 6.
PISTOL / RIFLE / MACHINE GUN / BAZOOKA Ammunition; Exact Value Search + 4 bytes +
Write
Endurance
Unknow Value Search, Has Changed, Has Not Changed + 4 bytes + Write
Tsearch pops up at 6b357e:
006b3578 D825740BAE00 fsub dword ptr [0xAE0B74]
006b357e D99E1C020000 fstp dword ptr [esi+0x21C]
1st option: NOP the FSUB instruction so the Endurance bar won't decrease; 909090909090 at
6b3578.
Underwater Air
Unknow Value Search, Has Changed, Has Not Changed + 4 bytes + Write
Tsearch pops up at 6b338c:
006b3386 D825740BAE00 fsub dword ptr [0xAE0B74]
006b338c D99618020000 fst dword ptr [esi+0x218]
1st option: NOP the FSUB instruction so the Underwater Air bar won't decrease; 909090909090 at
6b3386.
Cold
Unknow Value Search, Has Changed, Has Not Changed + 4 bytes + Write
Tsearch pops up at 6b36dd:
006b36d7 D825740BAE00 fsub dword ptr [0xAE0B74]
006b36dd D99624020000 fst dword ptr [esi+0x224]
1st option: NOP the FSUB instruction so the Cold bar won't decrease; 909090909090 at 6b36d7.
Invisibility
Invulnerability (+max Endurance bar + max Underwater Air bar +max Cold bar +no ammunition
decrease)
By trying to change the memory addreses around 144C303 ==>144C302: 1 byte: 1=On, 0=Off.
Victor D. "Wolverine"
From Porto, Portugal, Europe
victordwolverine@yahoo.com
victordwolverine@gamehacking.com
www.geocities.com/victordwolverine
members.fortunecity.com/victordwolverine
Copyright © 1996 - 2002 The World Of Game Hacking. All Rights Reserved.
Regulations, Trademarks and Privacy Statement are property of The World of Game Hacking.
Copyright © 1997 - 2002 The C.E.S Game Hacking Team (Cogito Ergo Sum).
Users of this site agree to be bound by the terms of the International Internet Web Site Rules and
Regulations.
This tutorial have been modify to maintain the size of this book. For tutorial + picture, please go to
http://www.gamehacking.com/
Making a Mass Kill
Target:
Crimsonland version 1.9.8
http://www.crimsonland.com
Tools:
-Softice
-Tsearch 1.6b (http://fly.to/mtc/)
-Code Cave Chaos (http://www.s-i-n.com/chaos/)
Objectives:
With One hit kill hacks being all the rage these days, we will take it a step
further and turn a one hit kill into a kill all mass killer.
Begin:
The first step is that we have to find the routine that deals with the enemy
health. A good idea would be to get the DOCTOR perk (0x48E6C0 = 1),
which allows you to see enemy health by holding your mouse cursor over
them. The problem at the beginning of the game is that enemies die off too
quickly to be able to search for health, so wait until level 1.5 ( Alien Dens )
and shoot at those big red white enemy spawners.
Doing the standard dec / inc search you should have come up with
something in the 499xxx range, then put a breakpoint (bpm w) / autohack it.
Executing an fstp st(0) instruction effectively pops the data off the top of
stack with no data transfer. Examples:
fst mem_32
fstp mem_64
fstp mem_64[ebx*8]
fst mem_80
fst st(2)
fstp st(1)
Take a look at the registers and jot down some notes. F5 out of Softice and
attack a different monster. Try to understand what is going on in those
registers when you get popped back into SI due to attacking the monsters.
You will also see at the far right that DS: holds the memory address of what
you are currently attacking, then the number after the equal sign is the value
of their health in hex.
? xxxxxxxx ; where xxxxxxxx is the number after the equal sign. You will
notice that it is a large value like 1140457472, this is because it is in
DWord (4 bytes) format. To get the float version of it, either change it from
4 Bytes to Float in TSearch or divide it by 2280914.944
--- end side note ---
You will see the following pattern as you go through a bunch of times:
EDI ESI
00 00
01 98
02 130
03 1c8
04 260
05 2f8
06 390
struct Monster
{
float xposition;
float yposition;
float health;
float speed;
};
Load up TSearch and open up the Easy Script section, its time for some
coding fun. Make sure you have the latest version of TSearch which
supports labels inside of EasyScript.
offset 004200dd
//jumps to my function
jmp @myfunction
//gets rid of the extra byte that was left over from
//destroying the original fstp dword...
nop
//creates a label to jump back to.
@home:
offset 46cb58
//create a label to jump to by name rather then offset
@myfunction:
//recreates the instruction that we destoryed
fstp dword ptr [esi+0x499434]
//jumps back home to the instruction after our created jmp
jmp @home
So with that code above we created a jump to our code cave, which just
recreated the original fstp instruction. At this point nothing has changed
except that when you attack a monster, the game now goes through our
function before returning back to the games own code.
So now let us add some code that will cause the current monster's life to be
set to 0 when it passes through our function.
offset 004200dd
//jumps to my function
jmp @myfunction
//gets rid of the extra byte that was left over from
//destroying the original fstp dword...
nop
//creates a label to jump back to.
@home:
offset 46cb58
//create a label to jump to by name rather then offset
@myfunction:
//recreates the instruction that we destoryed
//we are going to replace this with a mov instruction
//fstp dword ptr [esi+0x499434]
//move the value of 0 into the pointer, thus killing current monster
mov dword ptr [esi+0x499434], 0x0
//jumps back home to the instruction after our created jmp
jmp @home
Okay, there you have it. When a monster is attacked, its health will be
replaced with 0 and it will die. However this is not good enough, we
would like to be able to kill all monsters at once. The monster's health
pointer is [esi+0x499434], so if we were able to go through the whole list
of created monsters and replace their health with 0, then they all would die
when one was attacked.
Remember how I made you pay attention to those two registers? EDI &
ESI? Now we are going to use them in a loop to help point to the proper
memory address of the monster's health and then we will write a 0 into it to
kill them.
offset 004200dd
//jumps to my function
jmp @myfunction
//gets rid of the extra byte that was left over from
//destroying the original fstp dword...
nop
//creates a label to jump back to.
@home:
offset 46cb58
//create a label to jump to by name rather then offset
@myfunction:
//pushes all registers so that they are backed up
//on the stack so we can pop them back later so that we have no
//adverse effects on the game
pushad
//set esi to 0
xor esi, esi
//set edi to 0
xor edi, edi
//move the value of 0 into the pointer, thus killing current monster
mov dword ptr [esi+0x499434], 0x0
//pop all registers so that they are at the value they were at right before
//we started messing with them.
popad
//jumps back home to the instruction after our created jmp
jmp @home
So this time around we backed up the registers so that we could reuse them
at the end of our function, just incase we modified any of them during our
code.
Then we created a loop that looped 300 times, increasing the value of EDI
until it reached 300 - all the while writing 0 to the health address of each
creature as it goes through the loop.
Conclusion:
For the most part games store players and enemies an arrays of structs so
once you find a pointer for health you can do some math and go through
memory and write new values there.
In the case here, EDI (0,1,2,...) * ESI (0x98) + 0x499434 pointed to the
health of the current monster. We modified it so that it would go through
and write 0 to each Monster.health address. When a monster is attacked by
the player, the game jumps to our code and writes 0 to all currently
spawned monsters - killing them all for one. The only glitch is you only get
exp for what you kill with your bullet, but that's a story for another time.
offset 004200dd
jmp @myfunction
nop
@home:
offset 46cb58
@myfunction:
pushad
xor esi, esi
xor edi, edi
@loop:
mov dword ptr [esi+0x499434], 0x0
lea esi, dword ptr [esi+0x98]
inc edi
cmp edi, 0x12c
jne @loop
popad
jmp @home
^chaos^
idxchaos@hotmail.com
http://www.s-i-n.com/chaos/
^chaos^
November 15th, 2003
Here is what you need to search once you have selected either Show Nothing, Show Friendly or Show Everything:
:: Show Nothing to Show Friendly = Has Increased
:: Show Nothing to Show Everything = Has Increased
:: Show Friendly to Show Everything = Has Increased
:: Show Friendly to Show Nothing = Has Decreased
:: Show Everything to Show Nothing = Has Decreased
:: Show Everything to Show Friendly = Has Decreased
For it to show everything on the game you will need the value for it, in which will be shown if you have a game with "Show
Everything" on. Then apply this addie to the game for it to work.
Go into a game;
Alt & Tab out to TSearch and search "Unknow Value";
Go back into the game and put Auto Run on (Scroll Lock);
Alt & Tab out to TSearch and search "Has Increased";
Go back into the game and put Auto Run off (Scroll Lock);
Alt & Tab out to TSearch and search "Has Decreased";
Repeat this until you have found the addie.
For this option, you will need to host your own games;
Host your first game with no start delay;
Alt & Tab to TSearch and search "Unknow Value";
Go back to the game;
Exit the map and go to "Host Options" and host a game with a long enough start delay to give you time to search;
Host the game;
Alt & Tab to TSearch and search "Has Increased";
Go back to the game;
Exit the map and go to "Host Options" and host a game without the start delay;
Alt & Tab to TSearch and search "Has Decreased";
Keep on doing that until you have found the addie for start delay.
Before you search for this addie, you will need to make about 2 or 3 maps in the mission editor;
Set the wind speed as 1 for the first map, and save it as eg, "wind1";
Set the wind speed as 2 for the second map, and save its as eg, "wind2";
Set the wind speed as 3 for the third map, and save it as eg, "wind3";
Go onto the first map you made (wind1);
Alt & Tab out of the game and search in Tsearch for "Exact Value" 1;
Go back to the game and Exit;
The go onto the second map you made (wind2);
Alt & Tab out of the game and search in Tsearch for "Exact Value" 2;
Go back to the game and Exit;
The go onto the third map you made (wind3);
Alt & Tab out of the game and search in Tsearch for "Exact Value" 3;
Now keep on going through these maps until you have found the remaining addie;
To remove the wind, you will have to set the value of the addie to "0".
Poke ***** 90 90 90 90 90 90
SUB BYTE 02
This will subtract 2 from the value of your scope zoom.
Poke ***** 90 90 90 90 90 90
poke ***** 06
This will set your scope zoom to 6.
Auto Weapons:
Auto Weapons will also make Auto Knife.
Ok enter a game get a Pistol go into TSearch and search UNKNOWN VALUE.
Return to the game and get a weapon that is Auto like a Saw or FN MAG.
Go into TSearch and search HAS INCREASED. Return to the game and get your
pistol again and search HAS DECREASD. Continue gettin a pistol and saw and
search in HAS INCREASED for the SAW and HAS DECREASED for the Pistol.
You should find a addie which will increase with the saw and decrease with the pi
Take that addie and freeze it when u have a saw on and then change to different
weapons and those weapons should now shoot at the speed of the saw.
There are other methods of finding autoweapons but i find this to be one of the e
---------------------------------------
Jump:
This jump will work for Host and if u find the rest of the addies for Join.
Go into a Game that has a lader. Get on the lader and search for UNKNOWN VALUE.
Go back to the game and go up the lader a little and search HAS INCREASED.
Return to the game and go back down or up the lader and
search HAS INCREASED for when u go UP and HAS DECREASED for when you go DOWN.
And you should find one addie that when you poke it or inject a Higher number wi
you as high as the Value u up in. Now for this to work on Join what you must do
Jump address for Every SLOT. Most DF Games there are a Maximum of 50 Slots.
There is one good way to find them. This is a hard way but the way to start. go i
and Find jump for Slot 1. Then find it for Slot 2. and find out how much the dif
between Slot 1 and 2 then count up 50 times. That way is hard but if u find the
for the first few slots and figure out how much it is between each Addie for a Sl
up or down and find all 50 of them. This is proboly one of the easier ways to fi
But theres always another way.
----------------------------------------
GPS:
By hosting we have 2 options: Show Friendly and Show Nothing.
By single player we have 3 options: Show Default, Show Friendly, and Show Everyth
Host a game with the GPS setting show nothing. Go to TSearch and start an
unknown value search. Go back into DF and exit your current game, then host
a new game with the GPS setting show friendly. Since show nothing to show
friendly is increasing the GPS value, click search next and then choose "Has Incr
Now exit your current game and then start a single player game with the GPS sett
show everything. Since show friendly to show everything is increasing the GPS val
click search next and choose has increased. Now exit your current game and host
game with the GPS setting show friendly and since show everything to show friend
decreasing we click search next and then choose "Has Decreased". Exit your curre
game and host a new one with the GPS setting show nothing and since show friendl
show nothing is decreasing, click search next and choose has decreased again. Re
above steps until you find the GPS address.
Now to find the address that controls whether your playing Multi or Single Player
Host a Multiplayer game and do an unknown value search. Now exit your game, start
Singleplayer game, and click search next, then choose "Has Decreased".
Then host a Multiplayer game and do has increased. Repeat these steps until you f
address that controls whether your in a Multiplayer or Singleplayer game.
-------------------------------------
Raise or Lower Buildings.
Ok for this u will need to make 3 or 4 maps. Each map needs to have a few buildin
1st map: Make all buildins at 0 height. 2nd map: all building need to be in the s
as the first one,but the height of the buildings needs to be higher.
make the next 2 in the same way. Each one needs to have higher buildings then bef
But the buildings HAVE to be in the SAME place.
Now start the first map and search UNKNOWN VALUE.
Now go to the next map and search HAS INCREASED.
go on to the next map and search HAS INCREASED.
now continue on in that manner until u find the correct addresses.
-----------------------------------------------
Fog,Water,Day ON/OFF:
Now for this one u have to make maps. u need to make 4 or 5 maps each map
needs to have a higher Fog level then the next one. eg-1st Map: Level 1,
2nd Map: level 2. Now start the first map and search EXACT VALUE and the Value i
Now go to the next map which should be Fog at Level 2.And seach INCREASED BY and
Continue searching that way until u find the correct addie. Now if searching by
INCREASED BY or EXACT VALUE doesnt give u the correct Addie.
Try instead the first map searching for UNKNOWN VALUE and the next map HAS INCREA
When u find the correct Addie simply put 0 in it and u should have no Fog.
If the fog doesn cut off right away((like in DFLW)) Freeze the addie at 0 and go
the next map and the Fog should be gone.
You can also apply the same method for finding Water On/OFF and Day/Night.
Just make it with diff levels of whatever u are wanting to hack and then search a
-----------------------------
Ammo:
Ok so u want to hack ammo for any DF game..or any game for that matter heres what
Go into a game. Get the weapon u want to hack the ammo on up. Look at the value((
of ammo u have remember that. Open TSearch select the process for the game u wan
Now go to the first search and under EXACT VALUE put the value in that box and b
Now when its done go back to the game. Now shot 2 or 3 shots, go back to TSearch
DECREASED BY from the SEARCH NEXT and put the amount of shots u shot off in ther
((if u shot 3 put 3 in that buton)).Now search. Continue going in the game and sh
searchin DECREASED BY or HAS DECREASED until u come to about 3 to 10 addies.
Now go through all those addies and put new Values in and see if the ammount of a
in the game changes. If so then u have found the correct Addie. Now games that us
you will need to do is. After u find that addie. Enable the AUTOHACK option on th
to the game a shot and then return and it should have the Root Addie.
------------------------------------------
Weapons:
If u want to find the Addies that control what weapon is on what slot.
Go into a game get a weapon up. Already have TSearch ready. Do an UNKNOWN VALUE s
Return to the game and change the weapon that is on that slot. Go back to TSearch
HAS CHANGED search. Return back to the game when done and change the weapon on t
again and do a HAS CHANGED search again. Continue changing the weapon on that sl
searchin HAS CHANGED and u should find the addies u are looking for. You can use
to find what addie controls what weapon is on what slot.
You can use the weapons method to also find weapons like Autonade,.50 Caliber Mou
All u have to do is either get into and Autonade or .50 caliber mount and look at
Or
Start putting values from 1 up and see whatr weapons u find.
-------------------------------------------
Tracers:
Go to SETTINGS in DF and find where Tracers is set and select ON. Go into a game
UNKNOWN VALUE search.Once its done leave the game and go back to SETTINGS and se
Go back to a game and search HAS CHANGED. Continue cutting Tracers ON and OFF and
HAS CHANGED until u find the correct Addie.
-------------------------------------------
LW-TFD-BHD Only
Crosshairspread/ScopeDrift/No recoil:
All work in the same way, there are many other ways to find these, but this is th
Set your multiplayer settings to Crosshairspread On. Then start a game and search
Leave the game and set it to Crosshairspread Off. Then start another game and sea
Leave and set it to Crosshairspread On. Start another game and search has increas
address's. You can use the same method for ScopeDrift/Norecoil.
------------------------------------------
LW-TFD-BHD Only
Speed:
Get into a game and press Scroll Lock. Leave and search Unknown value. Come back
Then search Has Decreased. Turn Scroll Lock back on and then search Has Increased
what you are looking for.
-----------------
A few words
-----------------
The tutorial was a general refrence to Delta Force. The many tuts on hacking diff
in most every game. And these aren't the only ways they can be found. Every optio
---------------------------------------------------------
DEVIOUS - http://devious.tsongkie.com
TCB - www.tcb-hacks.com
CES - www.gamehacking.com
CC - www.cheat-core.com
---------------------------------------------------------
Greetz fly out to all DEVIOUS & TCB
---------------------------------------------------------
Date: 7th Of July, 2003
---------------------------------------------------------
Best viewed in Arial, Regular, 9
Bie comment:
This info is taken from http://www.gamehacking.com forum
Unknown
Namehack in BHD
---------------
Author : eVoByte-h4x-
Music : Fat Joe and P.Diddy ft.Dre - Girl, I'm A Bad Boy
The Roots ft. Musiq - Break you off
Description : Namehack = the ability to change the name you type under, as to appear to be other
player / use hexed letters while talking in game. Note that the name on the kill list is not changed
when name hack is used, only the one you type under.
Right, before we start I wanna get 1 thing clear. Incase anyone has the wrong idea here, this tutorial
is only for host mode. I'm not writing a tutorial so that everyone can copy the code at the bottom
and say they made a name hack, thats not the point. However, if you learn the information in this
tutorial, the same methods can be applied to make a name hack for join.
evo: fucknut
Right, so the names evo for me. Now, minimize the game and open up artmoney. Select BHD as the
process, and search for exact value, type as text and enter your name, in my case "evo"; for me 28
addresses were found.
To narrow these down I edited each one so that they had a different letter after them, e.g.
address 1 = evoa
address 2 = evob
...etc
After you've changed the name of each, go back in game and type a message. I typed under the
name evon. So, go back to Artmoney and find the address which holds the name you typed under.
Mine was :
0943005C
Ok, load up T-Search, select BHD as the process, and go to Autohack>Enable Debugger, then
Autohack>Autohack window. Just to note, I havent bothered rebooting the game to see if it has
DMA, I'm just guessing it does, and for tutorials sake I'd do it this way whether it did or not. This idea
of this bit is to be able to find the address each time you press the button/hotkey on your trainer, as
its the best way to defeat DMA on namehack.
Ok, so now your in the autohack window, goto Edit>Set Breakpoint, and type your address in, leave
the bytes as 1, and select Read/Write. What this means is, whenever your address ( in my case
0943005C ) is read, or written to, then the code which does it will be listed here. Ok, I got 5 entries
and you should too :
CODE
5C7087: cmp [eax],al
5C73DA: movsx eax, byte ptr [esi]
4AC88D: mov edi,edx
4Ac8C2: mov edx,[ebp+0x8]
4Ac8D4: rep movs dword ptr es:[edi],dword ptr [esi]
Ok, just because I'm used to looking at this code, I prefer to look into the following ones :
CODE
4AC88D: mov edi,edx ; copy the value edx holds into edi
4Ac8C2: mov edx,[ebp+0x8] ; copy the value which the address in ebp+0x8 holds to edx
NOTE : When you see things in [ and ], what it means is the value in the address it holds. E.G., in this
case, if ebp+0x8 holds 123456, it moves the value which 123456 holds into edx. Another thing to
note is mov does not really mean move...it means copy. After 'mov edi,edx' is completed, the value
will be in both registers.
Ok, next step? We need to see what goes on at these addresses so we know if we are safe to inject
code at them. For example, we dont want to split up a comparison and a conditional jump. Ok, so i
want to see whats around 'mov edi,edx', so in the autohack window goto Edit>Disassemble and
type in '4AC880'. We dont type in the exact address as the idea is we want to see what goes on
before it as well. After you have done this, click on Disassembler at the bottom of autohack window,
near debug event, thread and register.
Ok, heres the code around the area :
CODE
004AC880 Push ebp
004AC881 mov ebp,esp
004AC883 mov edx,[ebp+0xC]
004AC886 push esi
004AC887 push edi
004AC888 or ecx,0xFFFFFFFF
004AC88B xor eax,eax
004AC88D mov edi,edx ; where breakpoint put us
004AC88F repne scas byte ptr es:[edi]
004AC891 not ecx
004AC893 dec ecx
Ok, well, breakpoint put us on the mov edi,edx line, so one of these held the address for our
name...and being as it is being copied, its safe to say that after this line both will contain it. Xor
eax,eax is safe to put in a code cave, it just clears the eax register, and repne scas is also ok...so
thats where I will write.
Ok, one thing you might not know is a jmp takes up 5 bytes, 1 for the jmp opcode and 4 for the
address. We will be rewriting this over the xor line, so we will overwrite that, overwrite the next line,
and half overwrite the repne scas line with our jump.
The main rule of code injection is replace game code which you overwrite, and make sure the byte
numbers add up, heres why:
Say we overwrote where we said, and jumped back on 004AC891, then a byte from the repne scas
line would be blank. What would happen is all the code below would shift up 1 byte to fill the gap, and
there for all jumps in the entire code which jump after the line 004AC88F would jump 1 byte too far,
and cause the game to crash. To stop this, we put in a nop, which fills the space but does fuck all so
the game isn't screwed.
I found a huge group of blank codes which is the same in LW, TFD and BHD. From about 00400360
up until about 00400FF0. So, I'v decided I'm going to write my code to 00400370 and store the
address in 004003C0.
You're probably wondering whats going on here, so I'll finally explain. What we are doing, is making it
so we can find the address out easily each time.We are going to copy edi or edx after the line
004AC88D, as they contain the new address for our name, and then put it somewhere else in
memory. Then, in our trainer, we will use ReadProcessMemory to get this address, and then we can
write our name to it.
So, I'll write the code then explain it. By the way, this is wrote into EasyWrite in TFD which converts it
to Pokes:
CODE
Offset 004AC88B
jmp 00400370;jump to code cave
nop;to fill the blank space
Offset 00400370
xor eax,eax; replace code we overwrote
mov edi,edx; replace code we overwrote
mov [4003C0],edi;put our names address in 4003C0
repne scas byte ptr es:[edi];replace code we overwrote
jmp 004AC891; jump back to code
This code replaces the original code to jump to our code cave, where we are storing the code to
store our address.
--
--
CODE
Offset 00400370
xor eax,eax; replace code we overwrote
mov edi,edx; replace code we overwrote
This just replaces the code we overwrote with the jump command
--
--
CODE
mov [4003C0],edi;put our names address in 4003C0
This stores the address for our name into 004003C0. In our trainer we will use readprocessmemory
on this address, and the value will be the address of our name.
--
--
CODE
repne scas byte ptr es:[edi];replace code we overwrote
Jump back to the line after the bytes we overwrote, its important not to miss any lines out, which
we havent :-)
--
So, now we have all the code we need to store our address for us. To get this into a form where we
can write it easily, press TMK and then press CHECK ( the button, not the check box ). This will give u
pokes on the right hand side. If you don't know how to convert these TMK pokes to your
programming language, stop reading this tut, walk near a wall and face it, lean back, wrap your right
hand around the back of your head and push very hard.
Well, if you've managed to get upto here without knocking yourself unconcious on a wall, then I'm
guessing you have a brain cell, so I'm not going to write the source code for the trainer out for
n00bs to copy.
Well, finally, thats the end of a long, shit tutorial on Name Hack for BHD. We covered the following
topics:
Simple Hacking to get first name address
Basic Debugging
Beating DMA
Code Injection
Trainer Using Read/Writeprocessmemory
By the way, you can easily adapt this for join, and the whole Delta Force series...infact, any game,
any option.
Shoutouts : Zehcnas, Just M3, i.Brid, jb, OxY, Diablo, Demented, Bie, Predator
- No Order, just cool people -
www.evobyte.net
www.df-hacks.com
www.toxic-cell.net
www.btcsquad.com
www.gamehack.net
www.gamehacking.com
Tutorial by [mdk] / eVoByte / Rookie / [oz] / GTi / ...so many other fucking names. :-)
ADVANCED GAMEHACKING TUTORIAL
TARGET: DIABLO
~~~~~~~~~~~~~~
WRITTEN BY: Sorin ( Splinter@email.ro )
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TOOLS NEEDED: SoftIce, TSearch(or other mem finder), HexWorkshop, ProcDump
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TYPE OF MEMORY THAT THE GAME USES: STATIC MEMORY
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WHAT WILL BE THE HACK: all spells, automap reveal, spell casting in town
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
REMARKS: You'll need some brain, too :(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_______
INTRO:|
~~~~~~~
Hello again dear game lovers! If u stay with me for a moment, i'll show you some
techniques in gamehacking. But first I must tell you that sometimes a good ga
MUST BE a good game-player! Don't forget this !
Now, in Diablo see what level is the spell you have that 3-4 in inventory. Let's
firebolt. See what level is. Press [ESC] to pause Diablo, then do ALT+TAB.
OK. Open TSearch, and select Diablo as process. Now search for the level your fir
is. Let's say it's 3. Search for 3 (BYTE search!). Now, go back in the game,
the level of your firebolt spell by right-clicking on one of the 3-4 books th
to find.
Your firebolt level should now increase to 4. Pause Diablo, and in TSearch click
and enter 4 as value (BYTE search).
You must repeat this steps until you have ONLY 1 address! (for me that was 53317A
differs from version to version (game version) ).
After you found the address, modify it to see if it's the right one. Make your fi
be 8 (within TSearch, of course)! Go back in the game and voila! You have lev
spell!
But what about the other spells? We don't want to do this for every spell!
Most of the games hold your data in memory locations CLOSE one from another.
ex: If your life is at address 15, then your bullets will be (in most of cases)
address around 15 (let's say the bullets are at addr. 20). And your miner
at address 12! Get the trick? The addr. are one around other! (around mea
far).
=================================================================================
So, we have the starting address (mine was 53317A). Let's dump the memory around
then modify something in the game, then dump again the memory around that add
compare the results and try to figure out where is holding the "key"!
=================================================================================
For this we'll use TSearch again. In the "Misc" menu, select "memory dump -> save
The begin address should be the one you found, and the end address should be
found+200 (or 300, or 1000, etc - this is the range). I suggest to set this r
between 200-300. If you don't find anything, increase the range! ALSO, this w
dumping the memory AFTER the known address. If you can't find what you want,
memory BEFORE the known addr, by setting (in TSearch) the start addr to known
addr-(minus)range, and the end addr to known addr! It seems a little bit comp
but it's a kid's play!
~~~~~~~~~~~~~~~~~~~~~~~~~ |
~ start address: 53317A ~ |> in TSearch
~ end address: 53337A ~ |
~~~~~~~~~~~~~~~~~~~~~~~~~
Now, in Diablo learn a NEW magic spell (by right clicking on a book in your inven
IT'S VITAL THAT YOU DON'T DO ANYTHING ELSE IN THE GAME !(not even move !). Pause,
ALT+TAB & your back in TSearch.
All you have to do is to dump the memory again (don't change the start/end addres
Now, you have 2 files with a part of diablo's memory. To find out the differences
HexWorkshop and compare the 2 files...
In HexWorkshop, delete the first 12 (twelve) bytes from BOTH dump files. They are
signature and we don't need them.
If you did EXACTLY what I told you, you should have 3 differences. First is the s
(that changed from 0 to 1). The second difference is the spell enabler and th
diff. is not important to us. I guess that those addresses 53317a,53317b,5331
the levels for all your spells. Let's modify some of them (not in HexWorkshop
and set them to 8! Go back in the game, and what you see? ONLY the spells you
their level. That's because difference no.2 from above. The byte at that diff
the spell you have just learnt! Change that byte (also in TSearch & not in He
(the biggest). Go back in the game, and you have some new spells, but not all
That's because we changed only one byte, and not a DWORD! So, change the dword at
at the second diff. to FF FF FF FF (in TSearch). Go back in the game and voil
(of course some of them are level 0 because you just enabled them and you did
their level).
PS: This hack will not enable the "Bone Spirit", "Blood Star" & "Heal Others-mult
spells. These are treat separately by the game. If you want to hack them, f
books & repeat the hack as above!
Ok, now that we know how to hack the spells, let's practice a little more the "du
We have already a starting address: 53317A (the firebolt level from above). S
the memory again, but with a bigger range (let's say 20000).
Again we'll use TSearch. But first go into the dungeon in a level that you didn't
all the map. Pause Diablo, ALT+TAB in TSearch!
~~~~~~~~~~~~~~~~~~~~~~~~~ |
~ start address: 53317A ~ |> in TSearch
~ end address: 55317A ~ |
~~~~~~~~~~~~~~~~~~~~~~~~~
I must tell you again that we're dumping the memory ONLY AFTER the known addr.(53
we can't find anything, we'll dump the memory BEFORE known addr.
Now, go in that level & discover a new part of map. Pause the game, dump the memo
the SAME ADDRESSES!
And again you have 2 files containing a part of game's memory! Let's compare them
<Don't forget to delete TSearch signature from both files!>
Uuuh, now we have not only replacements, but insertions & delections! But we are
only in replacements (differences). If you follow carefully every replacement
land in some bytes like : ... 01 00 01 01 01 01 00 00 00 00 01 00 01 01 00 00
01 00 01 00 01 01 00 00 01 01 01 01 00 01 01 01 00 01 01 00 01 01 (a lot of t
In this bytes, HexWorkshop found not only differences, but matches, too! And thes
bytes are in BIG NUMBER! Isn't this possible to be a map skeleton? Let's chan
40-50) 01 bytes to 00's (within TSearch). Now, go back in the game and look a
minimap? Is it changed? Of course it is! You see that the map you had discove
it's "hidden" again!
So, we got lucky! Also, I must tell you that this map_memoring is the oldest in t
Diablo uses byte 0 where your character hadn't been before and ,of course, di
the map, and byte 1 where he discovered the map. And if you want to see all t
replace the 00's to 01's! But be careful not to overwrite other game's data !
PS: of couse you could hack the map by finding a shrine (in the game) that reveal
save your game before you click on it, then click on it, dump the memory, loa
dump the memory, see the differences. But this takes alot of time before you
shrine, and you must save your game every time you find one(because you don't
the beginning what it'll do *hehehe*). And this is not so professional like t
above!
We'll use the same mem. dump trick on this one, too!
But first, let's set some hotkeys in Diablo! Set F6 to be your hotkey for firebol
healing.
Explanation:
Diablo let us cast healing in town, but not firebolt. So we'll need to know when
reads your current spell. Then the game must compare something with the "heal
If they match, then your spell is healing and you can cast it in town. If the
then you must go in the dungeon to cast! :) Our solution is to find out what
"healing's key", and trick the game to believe that our firebolt is allowed i
giving to firebolt the healing's key). Easy huh?
But this time dumping the memory after the known address won't work! (you can try
don't believe me!). So we'll need to dump the mem. BEFORE 53317A. The length
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ start address: 532F7A -> we're dumping backwards and 53317A-200=532F7A ~
~ end address: 53317A ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Next, like always, compare the files (don't forget to erase the signature!).
And we have this time only one difference. To be more precisely, a byte differenc
located at address 53316C (532F7A-> start addr + 167 -> hexworkshop addr = 53
Now comes the SoftIce part :). But first change your spell to healing.
Put a
bpm 53316c
in SI. And right click to use your healing spell. SoftIce breaks:
That "jnz 41b69B" was taken by the healing, but the firebolt didn't take it (didn
So we need to change the 0 held by the byte at [eax+49a2a0] to another number
our firebolt will jump over the "firebolt not allowed", and our character ca
spell in town.
Use this method for the others spells. Their "key" is one after another!
Like always, I hope you understood something from this. If anything is unclear, c
Because I LOVE old games (diablo,starcraft,dark colony etc) and because i saw ove
thousands of diablo trainers, but not even 1 tutorial on how to hack it! Mayb
searched enough, or maybe there really aren't any others...
FUTURE PLANS:
~~~~~~~~~~~~~
Also, I'm looking for different methods of map-hacking, not in diablo, but in str
If you know something and you want to share your knowledge with the others, s
tips. Again, you will be full credited! If you don't trust me, write your own
spread them over the net. I'm satisfied with BOTH options :)
Sorin ( Splinter@email.ro )
eof
Author: Bie @ Razali Rambli
Email: razali_bie@hotmail.com
Website: http://bie.cjb.net
Demonstar
http://www.mking.com
Tools: Tsearch
Ghost Ship
Collecting information & Explanation:
We try to create an 'advanced' cheat, by making our ship invulnerable to anything.
But how we going to do that? What value to look for? Is this even possible?
Yes, it is easy actually. Don't believe me? Read more.
1. We die.
2. Timer start, as long as the timer haven't reach it limit, we can go pass everything without any damage.
3. Timer stop, our ship turn to normal again.
Searching:
1. Search Unknown 1 Byte
2. Die and let the new ship load and Pause [Press P]
3. Search Next Has Increase
4. Unpause and Pause again
5. Search Next Has Decrease
6. If the ship still flashing, repeat step 4-5. If the ship have return to normal, repeat step 2-5
7. You will found one address.
Testing:
1. Add the address to Cheat table
2. Change the value between 1-255
3. Freeze the address
4. If your ship keep flashing, and doesn't get damage at all. Yep, you have found it.
Conclusion:
Not so advanced cheat right? Ok, next time I'll show you how to make a cleaner way to handle this like what I have done inside my trainer.
Sample of this cheat in action can be download at my homepage at http://bie.cjb.net
Next time it will involve code injection, you wont have to make your trainer keep poking at that address & your ship will not flashing.
Advanced Game Training Techniques
Diablo 2: Money On Character
STEP 1:
Your character should at least have 1 piece of gold, if you do not have,
attain it. The value for money is stored in 4 bytes (dword) in "exact value"
format, meaning that the value that you see on screen is the one that you
want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how much gold you have and hit the
FIND button. This may take a few seconds to a few minutes depending on
how fast your CPU is because d2 seems to be a memory whore. Hop back
into Diablo 2 and change the amount of gold you are holding. Now alt + tab
back to GT and enter your new gold value in the GT edit box, but this time
hit the SIEVE button. This will only look at the addresses which matched
your first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value. Hop back into Diablo 2, the value of your
money will still be the same until you change it by buying an item or
dropping some gold. The value I had was 00d19530, this address is static
in memory and will never change. So it will work every time you start up
Diablo 2.
Conclusion:
Enjoy your new found fortune.
^chaos^
STEP 1:
Your character should at least have 1 piece of gold, if you do not have,
attain it. The value for money is stored in 4 bytes (dword) in "exact value"
format, meaning that the value that you see on screen is the one that you
want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how much gold you have in the
STASH BOX and hit the FIND button. This may take a few seconds to a
few minutes depending on how fast your CPU is because d2 seems to be a
memory whore. Hop back into Diablo 2 and change the amount of gold in
your STASH BOX. Now alt + tab back to GT and enter your new gold
value in the GT edit box, but this time hit the SIEVE button. This will only
look at the addresses which matched your first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value. Hop back into Diablo 2, the value of your
money will still be the same until you change it by buying an item or
dropping some gold. The value I had was 00d72cc8, this address is static
in memory and will never change. So it will work every time you start up
Diablo 2.
Conclusion:
Enjoy your new found fortune.
^chaos^
STEP 1:
This is really 4 easy tutorials in one. Your character should at least have 2
or 3 STAT UPGRADE POINTS that you can distribute, if you do not have,
attain it by LEVELING UP, OR CHEAT using the previous tutorial. The
value for ATTRIBUTE POINTS is stored in 4 bytes (dword) in "exact
value" format, meaning that the value that you see on screen is the one that
you want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how much your STRENGTH
currently is and hit the FIND button. This may take a few seconds to a few
minutes depending on how fast your CPU is because d2 seems to be a
memory whore. Hop back into Diablo 2 and use one of the STAT
UPGRADE POINTS on STRENGTH so that the value for STRENGTH
goes up 1. Now alt + tab back to GT and enter your new value of your
STRENGTH ready to distribute in the GT edit box, but this time hit the
SIEVE button. This will only look at the addresses which matched your
first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value, increase it for best results. Hop back into
Diablo 2, the value of your STRENGTH will match whatever value you
entered. The values I had were: STRENGTH: 00d194c0, DEXTERITY:
00d194d0, VITALITY: 00d194d8, ENERGY: 00d194c8, these addresses
are static in memory and will never change. So it will work every time you
start up Diablo 2.
STEP 3:
Now repeat the steps over to find the other values for DEXTERITY,
VITALITY, and ENERGY.
Conclusion:
Enjoy playing with your attributes. Remember that if you just modify
VITALITY/ENERGY to a high value you will NOT get 2 life/mana per
point, so its best to invest actual upgrade points into these two values. Also
don't forget that you can set these stats back to 0 and upgrade them again
and again.
^chaos^
STEP 1:
Your character should at least have 2 or 3 STAT UPGRADE POINTS that
you can distribute, if you do not have, attain it by LEVELING UP. The
value for STAT UPGRADE POINTS is stored in 4 bytes (dword) in "exact
value" format, meaning that the value that you see on screen is the one that
you want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how many STAT UPGRADE
POINTS you currently can distribute and hit the FIND button. This may take
a few seconds to a few minutes depending on how fast your CPU is because
d2 seems to be a memory whore. Hop back into Diablo 2 and use one of the
STAT UPGRADE POINTS on a stat such as strenght so that the value for
STAT UPGRADE POINTS drops 1. Now alt + tab back to GT and enter
your new value of your STAT UPGRADE POINTS ready to distribute in
the GT edit box, but this time hit the SIEVE button. This will only look at
the addresses which matched your first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value, increase it for best results. Hop back into
Diablo 2, the value of your STAT UPGRADE POINTS will match
whatever value you entered. The value I had was 00d194e0, this address is
static in memory and will never change. So it will work every time you
start up Diablo 2.
Conclusion:
Enjoy playing with the stat upgrade points and creating an ultimate
character. Remember that you must have at least 1 STAT UPGRADE
POINT to distribute so that the [+] icon is enabled. Otherwise you will not
be able to distribute your points, but you will still have them for later use.
^chaos^
STEP 1:
The value for CHARACTER LEVEL is stored in 4 bytes (dword) in "exact
value" format, meaning that the value that you see on screen is the one that
you want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter what CHARACTER LEVEL you
currently are and hit the FIND button. This may take a few seconds to a few
minutes depending on how fast your CPU is because d2 seems to be a
memory whore. Hop back into Diablo 2 and kill some more enemies until
you level up and gaint a CHARACTER LEVEL. Now alt + tab back to GT
and enter your new value of your EXPERIANCE in the GT edit box, but
this time hit the SIEVE button. This will only look at the addresses which
matched your first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value, increase it for best results. Hop back into
Diablo 2, the value of your CHARACTER LEVEL will NOT match
whatever value you entered, it is ONLY AFTER YOU SAVE & EXIT will
the results be apparent. The value I had was 00d19520 addresses are static
in memory and will never change. So it will work every time you start up
Diablo 2.
Conclusion:
Change your level and then, SAVE AND EXIT, do not check your
Character screen because it might set your level back to the original.
^chaos^
chaos world (c) 1999
Do not distribute as your own
please link here
Advanced Game Training Techniques
Diablo 2: STAMINA
STEP 1:
The value for the STAMINA BAR is stored in 4 bytes (dword) in a "bar"
format meaning that you can't see the value, OKAY I know you can see it
but I am tired of doing exact searches and its always good to know another
method of searching. So start up GAME HACK, select GAME.EXE or
DIABLO II from the process window (press the left most button).
In Diablo 2 make sure that your stamina bar is filled to the top. Next click
on the BINOCULARS and select ADVANCED from the drop down list
under the SEARCH header. This will take the current state of memory.
Back in Diablo 2 make sure you have RUN enabled (hit R). Run around till
the bar decreases a bit. Pause the game with ESC, and get into Game Hack.
Now select the BINOCULARS ICON that has a small arrow under it (the
one that is next to the BIG binoculars). Under the search select DECREASE
and hit OKAY.
After Game Hack stops, go back into Diablo 2, run some more. Do the
Decrease Search yet again.
Now go back into Diablo 2 and let your stamina bar fill up 100%. Now in
game hack rather then a DECREASE search, do an INCREASE search.
Continue this cycle until you get as few values as possible, 8 of them:
00d1950e <-real
00d1950f <-real
00d19510 <-real
00d19511 <-real
043a3efe <-just for show
043a3eff <-just for show
043a3f00 <-just for show
043a3f01 <-just for show
The first four values are the real values, I know this because if I froze these
values I could run forever, however the next four values if I froze, they did
nothing and my stamina still went down.
So for the easy solution, just FREEZE only ONE of these four values (to
SAVE some CPU cycles since freezing a value pushes it into memory every
so often), 00d19511 preferred, and you can run forever.
Conclusion:
The freeze solution takes some cpu cycles. Another solution would be to
find a STAMINA SHRINE and see how that works via the ADVANCED
search + increase/decrease and then freeze that.
^chaos^
STEP 1:
Use a spell caster for best results, I used the Necromancer. The value for
the MANA ORB is stored in 4 bytes (dword) in a "bar" format meaning that
you can't see the value. So start up GAME HACK, select GAME.EXE or
DIABLO II from the process window (press the left most button).
In Diablo 2 make sure that your MANA ORB is filled to the top. Next click
on the BINOCULARS and select ADVANCED from the drop down list
under the SEARCH header. This will take the current state of memory.
Back in Diablo 2 use a spell till the bar (orb) decreases a bit. Pause the
game with ESC, and get into Game Hack. Now select the BINOCULARS
ICON that has a small arrow under it (the one that is next to the BIG
binoculars). Under the search select DECREASE and hit OKAY.
After Game Hack stops, go back into Diablo 2, run some more. Do the
Decrease Search yet again.
Now go back into Diablo 2 and let your mana orb fill up 100% by waiting
or just use a potion of mana. Now in game hack rather then a DECREASE
search, do an INCREASE search.
Continue this cycle until you get as few values as possible, 8 of them:
00d194fe <-real
00d194ff <-real
00d19400 <-real
00d19401 <-real
043a3ef6 <-just for show
043a3ef7 <-just for show
043a3ef8 <-just for show
043a3ef9 <-just for show
The first four values are the real values, I know this because if I froze these
values I could use bone armor or raise skeletons as many times as i wanted,
however the next four values if I froze, they did nothing and my mana still
went down.
So for the easy solution, just FREEZE only ONE of these four values (to
SAVE some CPU cycles since freezing a value pushes it into memory every
so often), 00d19401 preferred, and you can run forever.
Conclusion:
The freeze solution takes a some cpu cycles. Enjoy your spells.
^chaos^
STEP 1:
The value for the HEALTH ORB is stored in 4 bytes (dword) in a "bar"
format meaning that you can't see the value. So start up GAME HACK,
select GAME.EXE or DIABLO II from the process window (press the left
most button).
In Diablo 2 make sure that your HEALTH ORB is filled to the top. Next
click on the BINOCULARS and select ADVANCED from the drop down
list under the SEARCH header. This will take the current state of memory.
Back in Diablo 2 use a spell till the bar (orb) decreases a bit. Pause the
game with ESC, and get into Game Hack. Now select the BINOCULARS
ICON that has a small arrow under it (the one that is next to the BIG
binoculars). Under the search select DECREASE and hit OKAY.
After Game Hack stops, go back into Diablo 2, loose some health. Do the
Decrease Search yet again.
Now go back into Diablo 2 and let your health orb fill up 100% by waiting
or just use a potion of health. Now in game hack rather then a DECREASE
search, do an INCREASE search.
Continue this cycle until you get as few values as possible, 8 of them:
00d194ee <-real
00d194ef <-real
00d194f0 <-real
00d194f1 <-real
043a3eee <-just for show
043a3eef <-just for show
043a3ef0 <-just for show
043a3ef1 <-just for show
The first four values are the real values, I know this because if I froze these
values I could get hit as many times as I wanted, however the next four
values if I froze, they did nothing and my health still went down.
So for the easy solution, just FREEZE only ONE of these four values (to
SAVE some CPU cycles since freezing a value pushes it into memory every
so often), 00d194f1 preferred, and you can run forever.
Conclusion:
The freeze solution takes a some cpu cycles. Enjoy your longevity.
^chaos^
STEP 1:
Your character should at least have 2 or 3 SKILL POINTS that you can
distribute, if you do not have, attain it by LEVELING UP. The value for
SKILL POINTS is stored in 4 bytes (dword) in "exact value" format,
meaning that the value that you see on screen is the one that you want to
search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how many SKILL POINTS you
currently can distribute and hit the FIND button. This may take a few
seconds to a few minutes depending on how fast your CPU is because d2
seems to be a memory whore. Hop back into Diablo 2 and use one of the
SKILL POINTS on a skill so that the value for SKILL POINTS drops 1.
Now alt + tab back to GT and enter your new value of your SKILL POINTS
ready to distribute in the GT edit box, but this time hit the SIEVE button.
This will only look at the addresses which matched your first search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value, increase it for best results. Hop back into
Diablo 2, the value of your SKILL POINTS will match whatever value you
entered. The value I had was 00d194e8, this address is static in memory
and will never change. So it will work every time you start up Diablo 2.
Conclusion:
Enjoy playing with the skill points and creating an ultimate character.
Remember that you must have at least 1 SKILL POINT to distribute so that
the [+] icon is enabled. Otherwise you will not be able to distribute your
points, but you will still have them.
^chaos^
STEP 1:
Your character should at least have 1 experience point, if you do not have
some experiance, GO KILL SHIT! The value for EXPERIENCE is stored
in 4 bytes (dword) in "exact value" format, meaning that the value that you
see on screen is the one that you want to search for.
Start up Game Trainer (GT from now on), select GAME.EXE under the
PROCESS: heading. Under TYPE: make sure that DWORD is selected, it
is the default. Now in the edit box enter how much your EXPERIENCE
currently is and hit the FIND button. This may take a few seconds to a few
minutes depending on how fast your CPU is because d2 seems to be a
memory whore. Hop back into Diablo 2 and kill some more enemies so that
your experiance goes up. Now alt + tab back to GT and enter your new
value of your EXPERIANCE in the GT edit box, but this time hit the SIEVE
button. This will only look at the addresses which matched your first
search.
STEP 2:
You should have only a few values, 1 - 3, add them to the list by clicking
the >> button. In your new list of matches, double click under the VALUE
header and modify the value, increase it for best results. Hop back into
Diablo 2, the value of your EXPERIENCE will match whatever value you
entered ONLY AFTER YOU KILL ANOTHER ENEMY. The value I had
was 00d19528 addresses are static in memory and will never change. So it
will work every time you start up Diablo 2.
Conclusion:
Don't put your experience to high, as having a level 99 character would
probably lead people to suspect that you cheated.
^chaos^
chaos world (c) 1999
Do not distribute as your own
please link here
TUT no1:
~~~~~~~~
Hacking Disciples: Sacred Lands - Advanced Game-Hacking
INTRO
~~~~~
OK! In the following, I'll teach you how to find the instruction that decrease
your money in DISCIPLES: SACRED LANDS. I must tell you that it uses DMA and
has an unusual (at least for me) method to dec your money!
Start the game,and choose to PLAY A QUEST(not saga) and take a look at the money.
Write the value down on a piece of paper, then press alt+tab. Now, start
GameTrainer or any other memory finding/editing tool (Gamehack,Tsearch,etc.)
and search for that value [if you don't know how to do that, i'll explain to
you but only for GameTrainer.
GameTrainer: <- JUST for newbies and those who don't know(yet) how
~~~~~~~~~~~~ to use a memory finder
----------------------------------------------------------------------
STEP 1: As "Process", select the game(---in my case disciple.exe);
STEP 2: In the "Value" box, type the amount of money you have;
STEP 5: Now, down the "Find" button, it's the address list. Here you'll look
to see the money address. But after the search, this should contain
many addresses. That's because not only one memory address holds the
number you typed, but many more (in most of the cases). But you need
just the money address.To get that, go back in the game and spend some
money (ie: hire a unit, or build something). Now, you have less money -
remember the value or write it down.
STEP 7: Look at the address list. If there are more than 3-4 addresses, you must
lose (or gain) some money in the game and start a new search by typing
new amount of money in the "Value" box, and always use the "Sieve" butt
STEP 8: Repeat this until you'll have only 3-4 addresses (in our case just one if
you play a quest). Very good...]
-----------------------------------------------------------------------
Well, we have the money addr. In my case is: 03B00A20. Since this game uses
DMA (dynamic memory allocation) your address WILL BE DIFFERENT. But that's
doesn't matter...
============================from here==================================
mov dx,[ecx]
mov [eax],dx
mov dx,[ecx+02]
mov [eax+02],dx
mov dx,[ecx+04]
mov [eax+04],dx
mov dx,[ecx+06]
mov [eax+06],dx
mov cx,[ecx+08]
mov [eax+08],cx --->>>here i land in SoftIce
ret 0004
===========================till here===================================
Well, eax+08 holds our money. But eax+08 is 03B00A20 (in my case, in your case
is the address you found with GameTrainer). If you don't believe me, type:
? eax+08
We can't overwrite this instruction, because it's used NOT only by the money_rout
but by others as well (i.e.: when you hire a unit, this instruction MUST be e
Otherwise, the unit can't be hired!). We can't set another breakpoint on eax+
because we already have one. MMmmmm... What to do???
Let's put a breakpoint on 03B00A20 (in my case). But this time the breakpoint
should be rw(READ/WRITE) not only w(WRITE). So, in SoftIce type:
bpm 03B00A20 rw
OK...
Let's test it. Inside the game lose some money. SoftIce will break, and you'll be
But this time eax+8 will not be 03B00A20(my case). It'll be a different value.
When you lose some money, the game uses different addresses to hold your money
FROM WHERE IT DEC THE AMOUNT. Then it stores the new amount (after you lose s
in 03B00A20 (in my case). Let's say that you lose some money. The game saves
money you had (before losing) in a temp. address, it does the operations (dec
this temp. address, then stores then new value in 03B00A20 (in my case). That
how the game works (in my opinion). Now, we only need to trap this tmp. addre
BEFORE THE GAME WILL DEC THE AMOUNT. This means we must trap it when the game
to put in it the money you have BEFORE the game will dec the amount. That's w
a read/write breakpoint. When SoftIce popped the second time, eax+08 stores t
address. So, put a breakpoint on it:
bpm eax+8 w
We'll use a write-only breakpoint because the game will now modify that amount.
Now,F5 to exit SoftIce, and you'll be again in SoftIce. But guess where? Exactly
instruction that dec your money!!!:
===============================from here===============================
mov dx,[ecx]
sub [eax],dx
mov dx,[ecx+02]
sub [eax+02],dx
mov dx,[ecx+04]
sub [eax+04],dx
mov dx,[ex+06]
sub [eax+0],dx
mov cx,[ecx+08]
sub [eax+08],cx *** what can this be ?!?!?! hehehe...***
mov cx,[eax] <-- here I land in SoftIce
test cx,cx
=============================till here=================================
So looking at the code, I figure it out that the "sub [eax+08],cx" is the nasty
instruction that dec our money. Now all you have to do is to nop or change o
do whatever you wanna do with that instruction! You can also make a trainer
modify the .exe ...
Well my job here is done. But there is another question: what are the rest of the
"sub"-instructions do there? I'll let you figure it out what they do! (you m
play the game if you wish to know)...
HUH!
~~~~
This was my first tutorial about gamehacking. I hope you learnt something useful.
I'm glad I can share my knowledge with all of you, and remember : If you kno
something useful, don't keep it just for you! Because you are not the only o
knows it, and sooner or later, it'll be clear like the sunlight for EVERYBOD
it took a long time for you to discover that, but the happyness of teaching
others will be huge !
You are free to do whatever you wanna do with this tutorial. But if you think tha
is good and people will learn something from it, spread it!!!
NOTE : This tutorial is dedicated to the wonderful people in the GameHacking foru
~~~~~~ ~~~~~~~~~
mail-me! ( Splinter@email.ro )
Sorin greets you!
2003
eof
Advanced Game Training Techniques - Tutorial 2 PART I
Drakan and Dynamic Memory Allocation
NOTE: Drakan was protected with some kind of exe protection, which has
anti-softice code in it. This tutorial assumes you have the the unpacked
executable, most likely available from http://www.gamecopyworld.com/.
Also it is suggested that when you setup softice, choose the universal VGA
driver if possible. Most other video drivers will cause games/your system
to freeze when popping into Softice.
If you play around with these values, and you freeze the 0117a988, you will
see that the ball is fluctuating if the two values do not match. Since that
second address is different every time you can't just make your trainer
freeze that memory address because it will not work. So now lets load up
Softice, type (USE YOUR SECOND RANDOM EVERY TIME MEMORY
ADDRESS):
:bpm 03447e30 w
Now go find an enemy, when the enemy hits you, softice should pop up.
NOTE: you can use the softice command BPX (break point on execution) to
get to 010824e1 the next time you need to for whatever reason without
having to find that random value again (that is if you died in the process of
figuring this tutorial out). Just type:
:bpx 010824e1
Also be sure to clear all breakpoints when you are done with BC *
Okay, some really quick asm before we move on, please learn asm !
JLE = jump if less or equal, the arrow I drew shows where this jump hops
to
RET = return to the spot right after the last CALL, a CALL calls a function
In softice, if you look around where SI popped up, you will NOT see any
kind of ASM code like DEC or SUB. You could possibly take out one of
the MOV instructions but you might take out something important and make
the program crash. So now in SI press F10 (to go to the next instruction)
until you get to the RET 0004, or press F12, which brings you to the
instruction right after the last CALL (which happens after you exit the
function using the ret). Please consult your softice documentation if you do
not understand. Every call has a RET inside of it to signal the end of the
call. So I pressed F12, this lead me to the following code:
When you pressed f12, the current highlighted line in SI is the one right
after that call (in red). If you scroll up just a bit you will see a SUB EAX,
EDX. So you know you can NOP this with two 9090 or you can change the
SUB to an ADD by changing the 2b to 03. A quick explanation of this is that
damage (edx) is subtracted from life (eax), and then its pushed back into
EAX (kept for later reference) and then in the CALL it is used to determine
how much health you have.
I know this part of the tutorial was very messy, I was trying to teach too
many things at once. ASM, how to use softice..etc. Hopefully you
understood it. Now we will tackle the air supply meter.
Do the following:
:bpm 0363f278 w (I think the value is random so use your own)
Okay we found where its doing the subtracting. But take this into account, if
your NOP that red line, you will really be multiplying (fmul) some value
with 0 (what you nop'd) the next time it passed through this function, which
ultimately would be 0. Because any value multiplied by 0 = 0. This WILL
give you infinite air, but your counter will always zero out the second you
get underwater. If you scroll up you can't find another DEC or SUB in sight,
but right above it is a MOV eax, [0117ae98]. By NOPing that line the air
meter will no longer decrease. AND it won't zero out.
This part is unnecessary. If you press f12, and then scroll up you will see
that there is one CALL function before the one you just RETurned out of.
Above that is a SUB instruction. So it looks something like this:
SUB EAX,EDX
.....
04000000 CALL 00123123 ( I made these numbers up!!! )
.....
0400fefe CALL 04930293
0400feff pop esi
That SUB is very far away, Eax is probably not even the air supply value at
this time. So if you NOP'd that SUB you might get rid of something
important causing the game to crash or freeze. EAX is manipulated in the
first CALL, which could do a number of things. Eax becomes the air supply
value some where in the CALL 04930293.
You could BPX 0400fefe (this is NOT the right value, I made it up!), and
then you could trace into the call with F8 in softice.
Conclusion:
Yes, I know this tutorial was pretty sloppy. I am trying to educate the
newbie too, not just the SI/ASM expert. This "hack" would transfer over to
multiplayer, so do not cheat in multiplayer even though its lagged as hell
already.
Please read your softice manual, SI is a great tool only if you know how to
use it. Next, I'd suggest learning some ASM. Your best resource would be
"the art of asm", you could probably find it in .pdf format on most search
engines. If you have any questions, feel free to ask.
^chaos^
Alt + tab out of D2k. Start up Game Hack. Select Dune2000.dat as the
process. In most flag related cases we are looking for a 0 (not complete
yet) or a 1 (mission objectives complete). Below I try to find the value as if
I did not know it was a 0 or a 1, it could be two different values instead.
Conclusion:
There we go, when you push the value 1 into 006B0DD4 your mission is
accomplished. You have to remember that a flag may not always 0 or a 1, it
could be any two different values one meaning true and the other false. In
some games you might notice that the flag values are reversed, 0 might
mean true and 1 means false sometimes.
^chaos^
Step 1:
As you may have read in tutorial 4, Dune2000.exe is just a pre-loader for
the real game Dune2000.dat. So open up Dune2000.dat with WinDasm.
This is referred to as 'dead listing' because you will soon have the read out
of the games assembly instructions at your disposal to browse as you
please, this is not a 'live' approach because we are not going to search with
game hack for a increase or a decrease in values while playing the game.
Now that you have the listing of the game go to the string references
(second to last icon on the tool bar). At this point you would look for any
reference to what you were looking for, in this case anything to do with map
or reveal. The reference I found was 'Ex_CrateReveal', so using my
previous knowledge that there were crates that reveal the map I assumed
this is what I was looking for. So double click on the Ex_CrateReveal
reference, it should take you to the spot pictured below. This
Ex_CrateReveal function would be called if you picked up a crate in the
game that revealed the map for you.
A way to find the same value in 'live' mode would be to play the 'practice'
mode with crates ON, play until you find a crate but save it just before you
pick up the crate. The contents of the crates are not random, they are the
same every time so reloading the save game won't give you something
different the next time. So if its a map reveal crate then your in luck,
otherwise keep on playing till you find another crate and save it again
before you get it. You save the game before you pick up the crate because
is_map_revealed = 1 (1 = false this time around), and after the you get the
crate is_map_revealed = 0 (true). You would figure this out through trial
and error. This approach will work in all Westwood games as they include
crates in all of them. As you can see there are two ways to solve this: a
dead and a live approach, do whichever one you deem easier.
^chaos^
1. Start a practice game, I played Harkonen, the address for each of the
three sides is different incase you wanted to know.
2. Deploy your MCV.
3. Click on the Wind Trap and start building it, wait a second and right
click to make it go "on hold".
4. Start Game Hack and do the Advanced search.
5. Back in D2k left click on the picture of the building so that it builds a
little bit more and then once again put it on hold.
6. In game hack do Next Search, select 2 Bytes (word) and select
"increase" under the search type.
7. Repeat steps 5 and 6 until you get as little values as possible, I came out
with like 5. Add those values to Game Hack with the [>] button.
8. Back in D2k left click on the picture of the building so that it builds.
9. Since the game does not pause them you Alt + Tab, go watch the values
in GH and see which ones increase incrementally.
10. You will see that 007BAA36 (this is a static address) holds the 'Current
% Done' value, it counts from 0 to 23040
You will have to repeat this cycle for the right slider as well. This will
work for infantry, vehicles, and super weapon.
There is a problem however, when you get a super weapon. It will always
be "READY" so when you try to build a infantry or a vehicle they will go at
a normal build rate.
Since you can build a vehicle and a infantry at the same time we can infer
that there are some secondary counters, one for infantry and the other for
vehicles, just search the same way as above.
Conclusion:
That is how to make a fast build, just push the the value 23040 into the
addresses every couple seconds.
^chaos^
Wow it popped back into SI with a hit. This must mean that something was
writing the real value into 007b8ac8. (The yellow is where the SI highlight
is when you pop back into SI, however as you should know the line
ABOVE the highlight is the one that affected your value)
If you look above and below (go until you see the RET's), this function
checks how much energy you have and writes it back to memory. There are
no sub or add or anything like that, so hit F12 to go to to the RET(urn).
If you NOP 004328ce then the game will never check how much power you
have and try to set it back to its real value. So in softice do:
Conclusion:
Now if you build a wind trap your power will not go up or if you
sell/destroy your current wind traps your power will not down. Now that
the game never modifies the power value, feel free to push 999 into
007b8ac8.
^chaos^
Unknown
Introduction
Yep, again. For those of you who liked my first article "Minesweeper, Behind the scenes" I present here his natural sequel. The idea came when a friend of mine read the former article and joked
me about it, "now do hearts.." he said, so I did and this article is the final result. At this point I would like to thank some friends who helped me, Itay Langer, Michael Kuperstein and Yoav Sion (in
alphabetical order).
Two weeks ago, when I wrote the first article, I've explained the use of API functions with C# (using P/Invoke) to read another process memory. Also I've written an example for using this class
library in order to read the Minesweeper mines map. In that article I've claimed and I still claim that the goal of the article was not how to hack Minesweeper. The goal of that article was to provide
the reader a simple class library in C# that will allow them to read another process memory. To my surprise, many people who read the article was very interested in the example I've brought.
Because of that I cant really claim that the goal of this article is to learn how to use some new API functions in order to have functionality unsupported by C#. The goal of this article is to see what
is happening behind the scenes of the two Microsoft card games: FreeCell and Hearts. In spite of this goal my conscience cannot let me publish an article with no new coding feature, So I've
enhanced the library and now it supports also writing into another process memory. I've even done a use of this function in one of the examples.
Main Goals
1. FreeCell behind the scenes and developing a cool app that uses this knowledge.
2. Hearts behind the scenes and developing a very cool app that uses this knowledge.
Note: The first two sections are using a debugger to investigate the games, my personal favorite debugger is Olly Debugger v1.08 but any debugger will do.
Section 1: FreeCell, How does it work?
I imagine you ask yourself what is to crack in FreeCell? you already see all the cards! Well the point is to understand what it does and how it gets these cards. Also suppose you can read the cards,
you can write a program that plays Freecell by herself.. but you must have a way to read the freecell memory.
The first step, like always, is opening the file in the debugger. In this case we need the freecell.exe file which is found in the windows\system32 folder. After opening the file we need to find an
interesting starting point. When you look at the beginning of the file you see a list of functions imported from dll's as follows:
01001188 DD USER32.GetDlgItemInt
0100118C DD USER32.SetWindowTextW
01001190 DD USER32.wsprintfW
01001194 DD USER32.GetSysColor
01001198 DD USER32.GetWindowDC
0100119C DD USER32.IsIconic
010011A0 DD 00000000
010011A4 DD msvcrt._except_handler3
010011A8 DD msvcrt._controlfp
010011AC DD msvcrt.__set_app_type
010011B0 DD msvcrt.__p__fmode
010011B4 DD msvcrt.__p__commode
010011B8 DD OFFSET msvcrt._adjust_fdiv
010011BC DD msvcrt.__setusermatherr
010011C0 DD msvcrt._initterm
010011C4 DD msvcrt.__getmainargs
010011C8 DD OFFSET msvcrt._acmdln
010011CC DD msvcrt.exit
010011D0 DD msvcrt._cexit
010011D4 DD msvcrt._XcptFilter
010011D8 DD msvcrt._exit
010011DC DD msvcrt._c_exit
010011E0 DD msvcrt.isdigit
010011E4 DD msvcrt.time
010011E8 DD msvcrt.srand
010011EC DD msvcrt.rand
This is only the final part of the list, but If you look carefully you see that the last imported function listed is the function rand from the msvcrt dll, which is off course the randomize function from
the microsoft visual c runtime dll. So I've decided to search where this function is being used.
I've found two places where this function is being used. Then I put a breakpoint on both places and run the program. After I've started a new game the program stopped on the first breakpoint
once and 52 times on the second breakpoint. Here is the part where the brain needs to kick in, mine said that the first breakpoint randomize the game number and the second breakpoint
randomize the position of each card (or the card of each position) (remember you got 52 cards..).
So, I did a little test to prove me theory. I ran the program till the first breakpoint, then step over the rand function and look at the eax register, the value of this register was 0x00006A26, then I
continue to run the program, the game number (displayed in the caption) was 25254.. bingo, 0x6A26 = 25254. So now I knew I was right I needed to find where freecell stores this value and the
cards values, so I could read them later with my program. I started a new game and now I've investigated the second breakpoint. A few instructions before the breakpoint I've found a very
interesting piss of code. The code I've found store a value in a specific place in the memory, and then formatted the string "FreeCell Game #%d" with this same number, so THIS is where it stores
the game number.. The code is presented here:
As you can see, the first line store the eax register value (which is the randomized number from the first breakpoint) in the specific memory address 0x0100834C. By the way, there is no way you
can tell from the code what the value of eax is, But when you actually use the debugger, at runtime, you can see this is the same value you got from the first rand function.
Back to the second breakpoint. As I said earlier the second breakpoint is being heat 52 times which is exactly the number of cards we have. So what's now interest me is where this code stores the
randomize cards. So lets look at the relevant code:
So, what we see in this code is calling the srand function with the seed as the game number randomize earlier. this is an important part to note. freecell has game numbers, and you can select a
specific game, so how is that possible that the game is randomized but if you select over and over the same game number, you get the same cards? well, the answer lies in the first two lines of
code, the "randomized" cards are randomized with the game number as a seed number to the randomize function. If the rand function is initialized with the same seed in the srand function, the
randomized number it will creates will be the same.
Line number 5 is a beginning of a loop, this loops iterate 52 times, and in each iteration, randomize a card number, and puts it on the next location in the memory. The line 010032FD is where the
randomized card number is saved in the memory. After tracing with the debugger a few timer on these addresses I can tell you this, there is 8 arrays of cards, the first iteration put the card number
as the first item in the first array, the following iteration puts the card number in the first item of the second array, and so forth. when it gets to card number 9 it starts over, putting the card
number as the second item in the first array..
So what's the point with these 8 array? Well, the reason we got 8 array is because freecell has 8 columns of cards. so each array is a column of cards. Again, after tracing the loop a few times I've
discovered that the formula for the address where the card is saved is: CardAddress = BaseAddress + 0x54*I + 4*J, where BaseAddress is 0x1007554 (mentioned in line 010032FD), I is the
column number (0..7) and J is the row number.
So, now that we got the addresses we can go on and make the Freecell Memory Reader app. The form contains 8 listbox controls, one for each column. The first thing we do is checking which
operating system are we on, the freecell I've checked was on XP, I've also searched the addresses for win2K, but I couldn't test the program, so if it doesn't work on win2K, please leave a
comment and I'll fix it. Anyway, I check the operating system and according to it I set the addresses I'm going to use later. Then I search the process of freecell using the static method
Process.GetProcessesByName() and then I open a new instance of my ProcessMemoryReader class. This class was introduced in my previous article so check it for details explanation on the use of
this class. After opening the process I read the game number from the game number address. then I loop over the cards array and for each place in the array I read its memory, convert the card
number to a normal card number and place it on the proper listview (according to its column).
"Convert the card number"? Well, here I need to explain how the card is stored in memory. The number that was randomized earlier was a number between 1..52, so I need to convert it to the
card's number (1..13) and the card's kind (1..4). At first I thought that the conversion is simple, I thought that it was organized like this:
1 1 1
1 2 2
1 3 3
1 4 4
...
2 1 14
2 2 15
...
4 12 51
4 13 52
Well, it turns out that is not the case.. instead of specifying all the cards from one kind and them the next kind and so forth (1..13,1..13,1..13,1..13) they decided to specify the sets of card
numbers. (1..4,1..4,1..4, 13 times), like this:
1 1 1
2 1 2
3 1 3
4 1 4
1 2 5
2 2 6
...
3 13 51
4 13 52
I hope its clear now, That's why a conversion is needed. One Last thing to mention is that when I read the game number from the memory I get a 4 bytes array and I need to convert it to an
Int32, there are better ways to do it then how I did but I kept my way for simplicity. So the code is as follow:
IntPtr GameNumAddress;
IntPtr CardsAddress;
pReader.OpenProcess();
int iGameNum;
int readBytes;
byte[] buffer;
int CardNum, CardKind;
string ItemString = "";
bool bAddCard;
switch (CardNum)
{
case 11:
ItemString = "J";
break;
case 12:
ItemString = "Q";
break;
case 13:
ItemString = "K";
break;
case 64:
bAddCard = false;
break;
default:
ItemString = CardNum.ToString();
break;
}
if (bAddCard)
listArray[i].Items.Add(ItemString ,CardKind -1);
}
}
pReader.CloseHandle();
This game was far more difficult to debug from the rest, because of the complex ways the cards are stored in the memory. Also the example works only on XP, cause I couldn't find Hearts on a
win2K system, so I couldn't search for the parallel addresses. Because of its complexity I'll will keep my explanations nice an simple, and I won't get into details.
So, how many of you knows how do I start? That's right, we open the program in the debugger (mshearts.exe) and search the file for the famous rand() function. We will find to places, and we
will put a breakpoint on each place. Then we will run the program. As soon as we start a game, the first breakpoint will pop once and the second breakpoint will pop 52 times.. I think we have
found the interesting part.. So as always we will look at the code and search for the memory addresses where the values are being stored. Brought to you here is the code of the second
breakpoint:
Yea, I know, lots of ugly code.. But I've bolded the parts that interest us, the first line is where we set out breakpoint, the rand() function is being called. The second bolded line (01007FF1) is the
line where the randomized value is stored in the memory. note that this is the first operation of the kind: MOV <memory address>,<value> ,So I've check carefully what is happening in this
command. After tracing it a few times I've found some logic in what address are being used to store the values. The first 13 iterations of this loop (by the way, the code brought here is a loop) are
accessing a zone in the memory, we will call it zone A, the next 13 iterations access a different zone in the memory, zone B, and also the next 13 iterations and the last 13 iterations. so what do
we got here. 52 iterations, each 13 we change to a different zone in the memory. Also I've found that the difference between the memory addresses in each set is equal to 16.
So, you see, we have 4 main base addresses, each one is an array, so the first item is in ZoneA + 0, the second is in ZoneA + 16 and so forth. According to the picture the 4 base addresses are
stored in an array, this is correct. I've discovered that there is an array of 4 addresses, each item of that array is a pointer to another array of 13 items. All this is very nice, but I still have a
problem, all of the addresses involved in this structure are dynamic, meaning they changed from run to run. I need to find an address that every time the program starts, it will always be a static
pointer to the base address (the Base address is the address of the 4 pointers array). How do I know this kind of static pointer does exist? well, this involves explanations on what happens when
you create a variable on the stack, and what happens when you create a variable on the heap (I'm talking about unmanaged code off course). So when you create a variable on the stack, its
address is written to the file and so cannot change when you run different instances, but if you create a variable dynamically, his address is not known at design time and so cannot be written to
the file. now suppose you got a pointer to an array, so the array can be in every size you want, and you cant create it dynamically and so on, BUT the pointer itself IS static and declared on the
stack so there is always a need for at least a static pointer that holds the structure, and this static pointer has always the same address. So now I know it exists, how do I find it? Well, I've just did
a search. I ran an instance of the program, and saw what was my Base address (the address of the array of addresses) and then I've did a search on the memory to find where is this base address
is stored on the memory, and I've found only one such address. bingo. Now, the trick is to know in which region of memory to look for, cause how can you tell if the memory you are looking on is
the dynamic memory or static memory? Well, the region of memory that is between 0x0100D000 and 0x0100E000. This is only for this specific file. Each file has its own .data section, and this is
the section where all the static memory is stored.
If you didn't understand all the details it is not important, all you need to know is that we got a Static address = 0x0100d514, this static address is a pointer to another pointer we will call
PointerArrayAddress, the PointerArrayAddress is a pointer to an array of 4 pointers. Each pointer in the array is a pointer to an array of 13 items. each item contains a card number. each array of
cards is a player. and now all I need to do is read this structure and display it on the screen.
So what does out code do? First we find the Hearts process, then we read the static pointer, then we read the 4 pointers of the arrays, and then we read the 52 items out of the arrays, for each
item we convert its card number into a normal representation. if you remember from the previous section the conversion to the cards, here it's the same. and finally we add it to the proper list on
the screen (we got 4 lists). The code is as follows:
pReader.OpenProcess();
int i;
int readBytes;
byte[] buffer;
switch (CardNum)
{
case 11:
ItemString = "J";
break;
case 12:
ItemString = "Q";
break;
case 13:
ItemString = "K";
break;
case 64:
bAddCard = false;
break;
default:
ItemString = CardNum.ToString();
break;
}
if (bAddCard)
listArray[i].Items.Add(ItemString ,CardKind -1);
}
}
pReader.CloseHandle();
In the next section I will give an example of writing to a process memory using in the Hearts game.
Section 3: WriteProcessMemory bonus
As I've said in the beginning, I could not write an article with no new feature presented so I've enhanced the functionality of the class library so now it can also write into another process memory.
This is done using the API WriteProcessMemory. This function excepts a byte array, an address and a process and writes the byte array to the address of the process. Simple as that. Its normal
header looks like this:
BOOL WriteProcessMemory(
HANDLE hProcess, // handle to process
LPVOID lpBaseAddress, // base of memory area
LPCVOID lpBuffer, // data buffer
SIZE_T nSize, // count of bytes to write
SIZE_T * lpNumberOfBytesWritten // count of bytes written
);
[DllImport("kernel32.dll")]
public static extern Int32 WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[In, Out] byte[] buffer,
UInt32 size,
out IntPtr lpNumberOfBytesWritten);
For this function to work, you need to first open the process with the access permissions PROCESS_VM_WRITE and PROCESS_VM_OPERATION.
Brought to you here is an example of using this function, the example opens the Hearts process again, only this time the goal is to write me a good game. Here is the code:
pReader.OpenProcess();
int i;
int readBytes;
byte[] buffer;
int writtenBytes;
buffer = new byte[1];
btnReadMemory_Click(sender,null);
That's it.
Code Caves and Code Injection
By Tsongkie / CES 2003
www.gamehacking.com
I. Introduction
Code caves are series of 00 and/or 90 hex bytes located in the process memory of our games. We
can use these code caves as a place wherein we can write our own code/routine/function.
II Needed Tools
I have searched the game as normal and found the value 010BAFDC for money. I also noticed that
the money is being updated when the time returns to 00 (e.g. 10:00, 11:00). Also, 010BAFDC is a
COUNTER Address, changing it wont have any effect with the real value.
For SoftIce Users be sure that the you enabled the following in SoftIce:
Press ctrl+d
Type bpmd 010BAFDC w
X
And wait for SoftIce to Pop when time reaches 00…
type d [ESP+0C]
BINGO! [ESP+0C] is equal to 010BAFDC, our money address ?. If we simply NOP this, the money
wouldn’t change…It wouldn’t either increase nor decrease… the answer to this problem is code
injection…
IV Code injection
First, Get TCCT (Tsongkie’s Code Cave Tool… Yeah ? ) and search Gangsters2 Window for code
caves. Look at the results and select one… I chose 00400319. In SoftIce type:
D 400319 [return]
U 00400342
A 00400342 [return]
2) The instruction at 0028:00400342 is the same code at 0177:005650F9. We rewrote this because
we are going to overwrite the instruction at 0177:005650F9 when we call our own function.
What we need is to overwrite the code at 0177:005650F5 and 0177:005650F9 with a CALL
Instruction. Lets assemble and overwrite the said codes.
Now type:
A 005650F5 [return]
Type again:
U 005650F5 [RETURN]
V. Our Trainer
00400342 BF FF FF FF 00 85 FF C3
005650F5 E8 48 B2 E9 FF 90
Author : Snaky[GHU]
--===Let's begin===--
2. Play the first level until you find the password for level2.
That will be : RASP482
3. Leave the current game (Press F2). In the game options choose Password.
Enter RASP482 and in SoftIce type "bpx Getdlgitemtexta" without
(") mark. This tells SiftIce to break when the game reads the
password. Exit SoftIce and press the OK button.
6. If you type "d edi" you should see the code you entered (RASP482)
Now trace with F10 until you reach this piece of code:
40314D: cmp [43eb74],ebx ->ebx holds our level (second level is ebx=7
jz 40316f third is ebx=8 etc)
mov eax,[4eeaa4] ->mov the level map in eax
mov eax,[ebx*4+eax] ->localize the password's level on the map
test eax,eax ->if no level for where ebx is pointing
jz 40316f ->jump to search a new level for entered pass.
push edi ->else (a level matched with our pass.)
push eax ->then check to see if it's the real
call ->pass. for that level inside this call
add esp,8 ->this is for stack, unimportant
test eax,eax ->if eax=0 then all is ok
jz 40317a ->and we jump to the beginning of that level
40316F inc ebx ->inc the level pointer
cmp [43ea78],ebx ->had it exceeded the value in 43ea78 (48) ?
jg 40314d ->if not, then search the next level
7. Trace until you are (in SoftIce) on the "push edi" instruction.
Type "d eax" and you'll find the codes for all levels! Don't forget to
type "d eax+10" or "d eax+N" (0<N<300) to scroll the codes in SoftIce's display!
8. I give you some cool pass. : PARADISE - for SUPER BONUS LEVEL-u'll love it
COOLGUY - for the last level
9. BTW: TO PLAY THE CHRISTMAS-LEVELS DO THE FOLLOWING :
i) when you are in pacman's code put a "bpx 402bbe"
ii) go to the password dialog and enter a random incorrect pass.
iii) when SoftIce breaks, type "r fl z" and hit [ENTER]
iv) when you'll see "GAME OVER" screen, hit [SPACE]
v) then hit [SPACE] again to play CHRISTMAS LEVELS (you'll love this ones to
In one phrase,
"Long live GHU"
Snaky[GHU]
GHU ( http://www.ghu.as.ro/ ).
eof
Multi-Tools tutorial with ... HomeWorld, HomeWorld Raider Retreat, HomeWorld Cataclysm
Tool used to find the memory addresses: GameHack 2.0 and Winhack 2.0.
Tools used to set the BreakPoints: SoftIce & TSearch.
Tool used to take a look at the code: W32Dasm & TSearch; screenshots taken from W32Dasm.
All of them available here at http://www.gamehacking.com/ .
Since there are many game versions and cracked exes in this tutorial I will use as example the
HomeWorld and the HomeWorld Cataclysm demos available in FILEPLANET as reference.
INSTANT RESEARCHING
UNLIMITED FUEL in HW
After getting the "SHIP FUEL BAR memory address" set the BPM in:
* SOFTICE: bpmd "SHIP FUEL BAR memory address" w
* TSEARCH AUTOHACK: "SHIP FUEL BAR memory address" BPM SIZE 4 WRITE
Fly to decrease the fuel and dock to refill the fuel; in TSearch you get 3 FSTP and 1 FST, if you
NOP them the results aren't the expected.
The solution to this problem is from MegaBajt/Origin's Homeworld 1.03 +5 trainer.
Replace the code between [ ] with a dword memory address elsewhere so the fuel variation that
was been calculated in the code replaced doesn't affect the current amount of fuel.
In the MegaBajt/Origin's Homeworld 1.03 +5 trainer the change was from FSTP DWORD PTR
[EAX +000002C8] & FSTP DWORD PTR [EDX+000002C8] to FSTP DWORD PTR
[00958F00].
We change the code to D91D 00 8F 95 00 - with the memory address reversed (00 95 8F 00 =>00
8F 95 00).
RU CURRENT SU MAXIMUM SU
#A 8A2290 --- ---
#B #C 8A4B10 --- ---
#D 85D8B8 --- ---
#E #F 8A4B10 --- ---
#G #H 8BC630 --- ---
#I 8BB650 --- ---
##A ##B ##C 8BB5F0 --- ---
###A 9152E4 9152F0 9152EC
###B ###C ###D A0C884 A0C890 A0C88C
###E ###F B67504 B67510 B6750C
UNLIMITED SHIPS
SOFTICE TSEARCH CHANGE FROM TO
IN
#A 582C63 582C60 582BE4 741B 9090
#B #C 584453 584450 5843D4 741B 9090
#D 55CDFD 55CDFA 55CD94 741B 9090
#E #F 584433 584430 5843B4 741B 9090
#G #H 5892D5 5899D2 5898F5 0F8479000000 909090909090
#I 589A15 589A12 589934 0F8479000000 909090909090
##A ##B
588855 588852 588774 0F8479000000 909090909090
##C
UNLIMITED SU (SUPPORT UNITS) => UNLIMITED SHIPS
CHANGE
SOFTICE TSEARCH FROM TO
IN
453959 453956 453956 015110 909090
###A
4539AB 4539A8 4539A8 295110 909090
###B ###C 455049 455046 455046 015110 909090
###D 45509B 455098 455098 295110 909090
459AB9 459AB6 459AB6 015110 909090
###E ###F
459B0B 459B08 459B08 295110 909090
INSTANT RESEARCHING
CHANGE
SOFTICE TSEARCH FROM TO
IN
#A 6237C8 6237C5 6237C9 7705 7605
#B #C 625278 625275 625279 7705 7605
#D 5F5CE8 5F5CE5 5F5CE9 7705 7605
#E #F 625258 625255 625259 7705 7605
#G #H 62C2E8 62C2E5 62C6E9 7705 7605
#I 62C308 62C305 62C309 7705 7605
##A ##B
62AEE8 62AEE5 62AEE9 7705 7605
##C
###A 4E9F38 4E9F35 4E9F46 0F848C020000 0F858C020000
###B ###C
4EDE68 4EDE65 4EDE76 0F848C020000 0F858C020000
###D
###E ###F 4F2AC5 4F2AC5 4F2AD6 0F848C020000 0F858C020000
UNLIMITED FUEL (HW & HWRR only)
SOFTICE TSEARCH CHANGE IN FROM TO
54BE0F 54BE09 54BE09 D998C8020000 D91DF06F9500
#A and/or and/or
54BE4A 54BE44 54BE44 D99AC8020000 D91DF06F9500
54D5BF 54D5B9 54D5B9 D998C8020000 D91D008F9500
#B #C and/or and/or
54D5FA 54D5F4 54D5F4 D99AC8020000 D91D008F9500
52967A 529674 529674 D99ABC020000 D91D008F9500
#D and/or and/or
5296B5 5296AF 5296AF D999BC020000 D91D008F9500
54D59F 54D599 54D599 D998C8020000 D91D008F9500
#E #F and/or and/or
54D5DA 54D5D4 54D5D4 D99AC8020000 D91D008F9500
5515FF 5515F9 5515F9 D998C8020000 D91D008F9500
#G #H and/or and/or
55163A 551634 551634 D99AC8020000 D91D008F9500
5515FF 5515F9 5515F9 D998C8020000 D91D008F9500
#I and/or and/or
55163A 551634 551634 D99AC8020000 D91D008F9500
55043F 550439 550439 D998C8020000 D91D008F9500
##A ##B
and/or and/or
##C 550474 D99AC8020000 D91D008F9500
55047A 550474
Victor D. "Wolverine"
victordwolverine@yahoo.com
victordwolverine@gamehacking.com
www.geocities.com/victordwolverine
members.fortunecity.com/victordwolverine
Copyright © 1996 - 2002 The World Of Game Hacking. All Rights Reserved.
Regulations, Trademarks and Privacy Statement are property of The World of Game Hacking.
Copyright © 1997 - 2002 The C.E.S Game Hacking Team (Cogito Ergo Sum).
Users of this site agree to be bound by the terms of the International Internet Web Site Rules and
Regulations.
.________. .________.
\ | ___///__ ._________ .__///____ | \_
::::::| ____|___ ____|__ |_| /_| / .____|_____ |:::::::
:: | | __/___| | ____/| ____/ | | ::
:: | |____ \_ | | _|_|______._|___|____. | ::
:: | | | | | | | __///___| ::
:: | | | | | | | | ::
:: |_. | |_____|\_____///________|__________| | ::
:: \___///________| |[sheep] |_ | ::::::::::::
:: \__________| |_______| :: :: ::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::
Gamehacking Tutorial Collection.. :: ::
::::::::::::
Once again I feel its time to unleash another tutorial onto the world of
gamehacking freaks, this one is a little shorter than most.. Hope you all
get something from it though.
RANTS!
------
I notice a lot of fucking idiots around the trainer community that seem
to think bashing out the same shit day after day is helping the community
in some way, people sitting on forums talking about how to make a trainer
engine for the last 2 years need to get a fucking life..
The REAL!! trainer scene which is part of the WAREZ RLS scene with groups such
as MYTH, CLASS, DIVINE, DEVIANCE, FAIRLIGHT etc.. seems to have gone to shit
these days, its infested with lame ass groups rlsing substandard trainers to
gain rls numbers. Lets hope these lame fucks read my tutorials and educate them
selves so that the standard of trainers can at least raise a little.
locations...
SOFTICE SETUP
*************
When you press CTRL-D to pop softice you should see the following windows..
REGISTER WINDOW - this window is always at the very top of the softice window
(WR [return]) and displays the contents of all the registers..
DUMP WINDOW - generally situated close to the top of the softice window
(WD [return]) contains a split screen display.. one side is ascii the
other is hex.
CODE WINDOW - this is the main window.. sits just under the DUMP WINDOW
(WC [return]) contains the code of whatever process maybe running when
u pop softice.. the code is represented in ASSEMBLY LANGUAGE
instructions..
The comments in the brackets are what you need to type to turn the different windows on..
you also need to type CODE ON.. this will bring up the OPCODES which are a set of numbers
displayed to the left of each ASM instruction and to the right of every memory location
in the CODE WINDOW..
LESSON START
************
Ok, as stated above the game we will be working on is HOMEWORLD 2 without any updates
installed. Im choosing this game because Ive just created a HOMEWORLD 2 trainer and the
options are fresh in my mind. I suppose even if u dont have the game u can still learn
from the actual theory.
THEORY
******
One thing that we all can assume for ourselves is that the computer doesnt need a
graphical representation of the game unlike humans who need the graphical
stimulus to work and even play the game (moronic humans:)) ) anyway all that babble
actually means that the computer will never use ANY routines that are associated
with the DISPLAY. I can tell the little cogs in ur head are turning now eh? hmm
perhaps not :) well, our task is to find somewhere within the game that our 2
pointers collide, this is called a STAPLE INTERSECTION it means 2 beneficial pointers
or code sections are in the same area. You will find many of these STAPLE INTERSECTIONS
within the game but tracking them down can sometimes be tricky. Im now going to
give u an example of a STAPLE INTERSECTION just to make sure u understand what I
mean.
This is totally made up code but shows u the point Im trying to make...
Game Screen
|
.===============.
||
| (-0-) | <-- space ships.. hehe
| (-0-) |
||
||
| Progress 46%| <-- Players Build Progress, 100% = Unit is built.
'===============' ( I know that most of the time build progress
is shown in a BAR but to make it so people
understand more clearly Ive used numbers
to represent the build progress.)
Ok, so at this present time the screen is being updated with the value
46, this will be somewhere in the data section and very easy to find
with a search engine such as tsearch.
The progress value in memory is at some stage converted from data into a graphical
representation of what we see on the screen. This is where we will find our
STAPLE INTERSECTION.
mov edx, [ecx+456*4+456] <-- Move Build Progress value into edx (46)
lea eax, [ebp-130h]
push eax
push dword ptr [ebp+8]
lea eax, [ebp-234h]
push offset bb55
push edx
call 456333 <-- Convert 46 (value) into 46% ON SCREEN.
add esp, 10h
ELEMENT 2 - call 456333 <--- This gives us a place that the computer
never uses because its a SCREEN ROUTINE!
Im going to go 1 step further just in case u guys still dont get it.. below
is what will probably happen when a UNIT is built within an RTS.
COMPUTER PLAYER BUILD ROUTINE
=============================
1 Check Money Amount (make sure the computer has enough to build the unit)
2 Start Building
Ok, there are more than likely a lot more steps but this shows u the basics..
now we look at the HUMAN PLAYER.
2 Start Building
As u can see there are more steps included in the human players routine because
humans need to SEE the game (4) and humans also change their mind (6) both are
valid STAPLE INTERSECTIONS but the screen update is the cleanest and best way
of the two.
So now I hope u all at least know the REASONS why we are using STAPLE INTERSECTIONS
and how they are very beneficial when it comes to cutting the computer out of any
cheat benefits.
PRACTICAL
*********
This is the part of the show where I take HOMEWORLD 2 (our chosen target) and enlighten
u all on how to actually obtain the instant build option using a STAPLE INTERESECTION.
Once u have ur value, (ur value will be different btw.. ) then u need to
freeze all building progress with the PAUSE BUILD button.. its just on the
right of the actual progress bar, this will stop our breakpoint from picking
up and of the progression code.
Now we have this done we need to set an OPEN breakpoint on the progress value
we just searched for.. so in softice do this..
An OPEN BREAKPOINT just means that it will pick up any code that either READS or WRITES to
the
value we breakpoint.
If u have done this correctly softice should constantly break at the code below..
We know that this is indeed the onscreen display routine because if we change
the JNZ at location 51cff5 to a JMP then we get no progress bar at all on the
screen.
The code here just determines the percentage of the screen it has to fill with the color
yellow, this represents the build progress..
So now we have tracked down our STAPLE INTERSECTION that will NEVER be used by the
computer
yet it has a direct link to the values we need to change.. oh happy day!! :) We are ready to
inject a little bit of code to make an instant build for PLAYER ONLY..
So.. first thing we do is determine what we need to inject.. well, I suggest the best way to
tackle this problem is by moving 0 into the (LEFT TO BUILD) progress value which is
situated at offset EAX+0Ch, u need to be very careful though because as u may have noticed
the pointer EAX+0Ch is actually being placed into EAX which will destroy our pointer
to the value we need.. so this is where we shall jump out..
Most of the time I recreate the destroyed instructions first, but because the instruction
destroys the pointer then I had to re-create it after we have placed 0 into the build
progress value.
Once this is all done u can press F5 to let softice run the game and ur instant build will
be complete..
IMPORTANT NOTE: its very important that u always re-create the instructions u destroy when
using CODE CAVES, at worst u will crash the game and at best u will kill gfx onscreen which
I always think is an ugly option.
ADDITION: I forgot to add this in, The theory used here can be applied to any options really,
money etc.. anything that has a screen value.. try it next time u come across a game that
uses the SAME routines for health as u and the enemy.. works 100%.. thanks to SKYNET for
reminding me to add this.. :)
FINAL WORDS
-----------
Once again we find ourselves at the end of another show.. time just flies when ur reading
massive amounts of shite! :)) seriously I hope u all get something from this tutorial, I
dont spend my time writing them for nothing u know :)
******************************************************************************************
******************************************************************************************
I would just like to greet some people that support and inspire me....
NOTE!
This tutorial is _Definetly_ NOT for newbies. Best read with NOTEPAD.
Introduction
------------
Say you made a trainer with 10 or more options. The game you trained uses routine
protect against Alt+Tabbing outside the game. Say that the gamer using your train
forgot what are the trainers options, or he forgot what keys to use. He can do tw
things now. Quit the game, or try to press all the keys and see how it affects hi
Is there a solution for this kind of situation? Well, There is!
The method I will suggest in this tutorial was not invented by me. As far as I kn
it was already done in the old DOS days. That method is called Ingame Trainer Men
The purpose, is to show the trainer option menu, inside the game, when the user h
a hotkey.
What I will show in the tutorial, is how to make a trainer with one hotkey, that
pressed, will pop up a Message Box from inside my favorite target game: (pam pam
"The House of the Dead 2".
The tools I will be using are SoftICE, IDA, HIEW, and Visual C++ (not a must).
Theory
------
Basically the idea I will suggest works like that:
In case you don't know how to perform in-mem code injections, I suggest you go re
alittle about it in [SHEEP]'s tutorial, or keep reading on, as I will explain som
fundumentals of injections.
If we find a place that is getting executed ALL the time (like, in a huge loop :)
could locate a good place to patch there, and inject our code to am empty space.
question is, how do we find a place, a loop that runs all the time?
Basically, what I did was, whiile playing that game alittle, I poped SoftICE for
times, until I saw I am in the correct process (look in the bottom-right corner o
for the CLSID), in my case it is HOD2. I poped SoftICE in times that I wasn't doi
so I would see what code is executed even when I am IDLE.
After poping up in a place that looked OK, I began tracing alot. Some cases I did
manually, and some cases I did it using the T command (T 100 will trace 100 instr
After a while, I saw that some loop is being executed alot of times, so I wanted
it out. I disassembled the file with IDA, and got to that location. I am terribly
to tell you I really forgot what location it was... What I did though, was seeing
function that location was, and then seeing who calls it... for example:
This function is called from the location sub_4A41C0. So I went there. and there
I found a cool place that executed many API's. Anyway, I chose this location:
Why? Because GetMessage is a Windows API that gets executed all the time. I check
for my suspicion by simply setting a breakpoint at that location, and I saw that
I couldn't even play for one sec, because SoftICE kept popping after I pressed F1
OK, So we found a place to overwrite with our jump... now we actually need a plac
to jump to!
To summarize:
You can do 2 things in order to find a place that is getting executed all the tim
- Find a place that loops alot manually, by simply stopping the game in an IDLE
point, and trace from there. Tracing can be done manually, or it can be done
using the T command in SoftICE.
- Breakpoint on known API's that are likely to get executed all the time:
GetMessage, GetTickCount.
Windows EXE's are based on the PE (Portable Executable) file format. The PE forma
supports sectioning of the file. Every section of the file has a different job.
There are Code/Data/Resource/Import/Export/etc sections. Most sections are differ
in size, so they all must be aligned. Because of that nice feature compilers leav
us, there are often alot of 'dead' NULL bytes, that are simply wasted just to ali
the section size. There is a difference between those code caves, because these a
mapped to memory, while there may be cases you will see empty places, but they wo
be mapped into memory, thus you cannot jump to them.
1. You simply scroll through the entire EXE looking for those alignments. Once yo
see empty spaces, you check if they are indeed code caves (later on how to check)
2. In a hex editor, look for a binary string that contains nothing but 00's. It w
you to many odd places, but eventually to a cave.
3. You do the "proffesional" way. In IDA (or any other PE editor), we get some in
about the sections. We go to the beginning of the code (generally on top), and we
You see that the Virtual Address is 1000, and that the Virtual Size is C1940?
You add those up together, and you get C2940. You go to that OFFSET in the file,
will see a nice and clean code cave. :)
In order to check if this is indeed a CODE cave, and not just a dead cave, in HIE
notice if there is a dot (.) before the address of not. The address will be 4C294
see this: .004C2940, then this is code... if you see just 004C2940 then it won't
Trust me on this one, I spent a lot of hours figuring why it didn't work on some
I was working on a while ago.
What to Inject?
---------------
OK, So we know where to jump from, and where to jump to. But all of this is usele
we inject something! In this tutorial, I will show how to inject a simple Message
push Style
push Caption
push Text
push WindowHandle
call MessageBoxA
But remember, that we have overwritten an API... so we need to execute it again,
to the location we came from (actually we jump to the instruction after the API c
call GetMessage
jmp 4A596E
After that, we need to actually inject the text for MessageBox caption and text.
location 4C2970 for the caption, and 4C2980 for the actual text. The style will b
So we have this code now:
push 0
push 4C2970
push 4C2980
push 0
call MessageBoxA
call GetMessage
jmp 4A596E
But this code won't work... because we push 0 as the window handle. If we use 0 a
handle, then the MessageBox will be shown OUTSIDE the game, and sometimes cause i
crash. So how do we solve this? We need to find the window handle, and push it. B
the Window Handle is saved in a variable after the window was created. So we go b
IDA, and we track down the CreateWindowExA function. We see where it is reference
and we find this location:
So we see that the hWnd is saved in a global variable which is located inside the
memory address 7DC8AC. So now, we have to get that value, and push it, instead of
push 0
push 4C2970
push 4C2980
mov eax, [7DC8AC]
push eax
call MessageBoxA
call GetMessage
jmp 4A596E
Make a copy of hod2.exe, and name if hod2_.exe or whatever. We will be doing all
changes to this one. Open up HIEW, select HOD2_.exe, and then press F4 and go to
mode. Press F5, and type ".4A5968" (Without quotes ofcourse). Now you are in this
Press F3 (to be in EDIT mode), and then press F2 (to be in ASSEMBLE mode), and ty
jmp 4C2949 [Enter]
nop [Enter]
[Escape]
Press F9 to update.
now go to the cave (.4C2949), and assemble the code block we wanted to add (see a
For API's you cannot assemble, so you will have to leave 6 nop's for each API. ho
add an API? Simply. Do you remember that I told you that it can be executed from
in the program, and also with the same opcodes all the time? Simply go to a locat
that calls GetMessage (4A5968), and a location that calls MessageBoxA (49E148), a
the opcodes (FF 15 xx xx xx xx).
After that go to add the strings (F3 and then TAB), and simply write them. Rememb
In order to separate strings there has to be a 00 between them:
The Trainer
-----------
#include <windows.h>
#include "resource.h"
hInst = hInstance;
DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), 0, (DLGPROC)main);
return(0);
}
// My WRITE engine
HWND hwnd;
HANDLE phandle;
DWORD pid,bytesw;
quit:
return(0);
}
VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
// This is the actual thing!
{
if (GetKeyPress(VK_F4)) { // If F4 was pressed
Write(wname, 0x4C2949, opt2, OPT2); // Write The injection
Write(wname, 0x4A5968, opt1, OPT1); // Patch the call
Sleep(2000); // Wait a little (2 seconds)
Write(wname, 0x4A5968, opt1_off, OPT1); // Change back the call
}
}
LRESULT CALLBACK main(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
case WM_COMMAND:
if (wParam == ID_QUIT) ExitProcess(0x31337);
break;
default : return(FALSE);
}
return(TRUE);
}
Explanation:
What I did, was writing all the injected bytes into memory. First I wrote the inj
then I Patched the place to jump from, then waited for 2 seconds, and then patche
back again. I didn't bother to Zero out all the injection, because it won't get e
anyway.
Ending
------
Phew! That was a lot to write! I have been working 2 days on this menu + another
actually WRITING this. Looking back, it wasn't very tough, I just had to reboot a
due to blue screens and other sorts of page faults and weird exceptions.
What you have to keep in mind while doing an ingame menu, is:
There can be many problems and diffuculties that can occur. For example, what hap
if you don't find a global variable that contains the Window Handle? For that cas
can simply use FindWindow(0,"Window Name"). But what happens if you don't have Fi
imported in the EXE? You can import it like this:
Finally, my little advice, BE CREATIVE. Think of more ideas, like adding DIALOG B
many more options, or perhaps even injecting the ENTIRE trainer to the game, so y
even have to use an external program besides a memory patcher.
Attached to this package is the trainer source, and a nice pic hehe :)
Thanks:
[SHEEP]: Encouragement, and for telling me the Window Handle thing
Duelist: For telling me where to find that Window Handle thing :)
Greets:
iCARUS, Have_No_Mercy, calligula, jmp_fce4, Keyboard Junky, ddh, MacDeath, Dang,
and all the other dudes in #gamehacking which I forgot to add. Please bitch
me if I forgot :)
/\
____/__\____
\ / \ /
\/ \/
/\ /\
/__\____/__\
\ /
\/
TUT NO. 5
~~~~~~~~~~
============================I N T R O==================================
In this tut i'll show you how to make a *FULL AND TOTAL* hack on a game. I choose
Lamentation Sword (i like it very much).
=============================T O O L S U S E D======================
SoftIce :}
GameTrainer (or any other mem. finder). It must have a dump memory option!
Hex-Workshop (i prefer HIEW, but we'll need Hex-Workshop!!!)
W32Dasm (to show u a cracking approach :))
a little time to read this...
============================H A C K T Y P E==============================
PART 1:
Hacking the money, potions, gems, balls (fire and ice balls, not what u have in m
PART 2:
PART 3:
PART 4:
PART 5:
PART 6:
PART 7:
Hacking the weapons properties
PART 8:
******** With the hope that u'll learn something from this, LET'S BEGIN !!! *****
Before going any further, i must tell u one thing: the game uses DMA (and u don't
to pee your pants, trust me :] )
__________________________________________________________
PART 1: (money,potions, all u need to finish a game :)) |
(The money are stored as a DWORD) |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ok! Start the game, kill some monsters, find some money. Note the amount on a pie
paper!
Pause the game, ALT+TAB and start your mem. finder! Search for the money value. G
in the game, inc\dec your amount and search again the new value with the mem.
Ok, addr found! Now change the amount within the mem. finder to know if that is t
addr!
Now, put a breakpoint in SoftIce on that addr! (my addr was 865998, but yours wil
different, because of the DMA !)
Now, kill some monsters to find money! SoftIce popped! You should see this:
.............code code................
I think it's clear for everyone: the game stores the old value of money in edx, t
to add in eax, then add operation is performed, then updates the old value of
with the new one!
Now, let's loose some money to see what's happening... Go to a merchant and buy s
We land in the code above, where the game incs our money! But we loose some money
Loose some money again! SI popped at aaaaaaaa! F10, then type "? eax" in SI! WTF
ugly number? Oh, it's a negative one. So the add operation in this case will
afterall...
i.e: 123+(-3)=123-3=120
123+(+3)=123+3=126
Now what can we do? We can nop the add instruction, but when we find some money,
will not increase anymore, and when we buy something, the amount will not dec
well! But we don't want not to inc our money, right?
Now the technique will use it's simple: we must check for the value to see if it
or positive. If it's negative, then we will not add it on the amount. If it's
we'll add it!
Now, i wont tell u how to find the place to inject the code (read sheep's or mail
have problems). I'll just tell u what to inject:
eax=money to add/sub
edx=your amount
cmp eax,0 -> check if we loose money
jl back -> if so, then don't dec the sum and jump to the game code
add edx,eax -> if we find money, inc the sum
jmp back -> jump to the game code
BTW, the add\sub method is the same for potions,ice_balls etc ! So u don't need t
other code!
______________________________________
PART 2 (learn magic in a sec. !!!) |
(The time u need is stored as a WORD)|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now, take one of the 3 characters (i like Kusa) to a witch. Choose him a magic_sp
learn. Oh, no... He must wait some time until he will learn the spell (it's t
concentration time :)
And the higher is the level of the magic u want to learn, the bigger is the time!
This must be fixed somehow...
Pause the game while he is learning. Note the amount of time left down on a piece
Search the value with your mem.finder until u have 2 addresses. One of them is fo
screen output and one of them is the real one. U can check this by modifying
(one by one) within your mem.finder, then go back in the game to see if it's
From the above code u see this: The game dec the timer one by one until it is 0.
it's 0, then your character have learnt the spell.
All u have to do is to nop down that "jg u_must_wait" !!! If u don't execute that
instruction, then your character will INSTANTLY learn the spell !!!
_______________________________________
PART 3: (the well-known STAT-POINTS) |
(They are stored as WORD) |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Well, nothing much to say here, just the same old method: Wait until u make a "le
to gain some stat-points. Then search the quantity with your mem.finder...
You should see something like this:
..................code...........................
dec dword ptr [ecx+7f8]
..................code...........................
You know what you have to do... If you want, you can nop the instruction! In this
you will have infinity stat-points!
____________________________
PART 4: (EXPERIENCE points)|
(It's stored as DWORD) |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is best to cheat using your mem.finder! So, after finding the correct addr.,
to a huge number (u know, something like 99999999 :)). After that, back in th
each time u hit a monster, you will level-up your character!!! kooll...
__________________________________
PART 5: (the weapons durability) |
(You must dump your memory!) |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ok, so we want to find where the game changes the durability of our equipment...
some tries, i figure it out that if your sword has it's durability 20, in mem
stored as 20.
So, we must dump the memory!
After this, dec your sword durability by one, pause, ALT+TAB, and in your mem.fin
the option that search the dumped memory for changed values (in GameTrainer t
button called "Diff"). Do this until u have only one addr!
Now put a bpm (breakpoint on memory access) on that addr in SoftIce --> mine
Back to the game. Play a little (kill something) and SI should pop!
.........................code code..........................
mov eax,[esp+04] ------->here will be 1 encrypted
mov edx,[ecx+5C] ------->here will be weapon's old durability, also
sub edx,eax ------->substract 1 from the dur.
xor eax,eax ------->unimportant instruction
mov [ecx+5C],edx ------->update the new durability of the weapon, al
You will land in SI after the above instruction
.........................code code.........................
To clear this out: The game takes the durability of the weapon (let's say it's 20
it (20 will be transformed into 179, for example), then takes 1 and encrypt i
say the encryption of 1 will be 17). After this perform operation with encryp
(substracts 17 from 179, in our example) then it updates the memory address w
new encrypted value.
Simple, heh...
And because the encryption, the game don't use "dec edx", but "sub edx,eax" to su
from our dur.
You can't change the durability of your weapon within your mem.finder (because it
encrypted value ;))
All you have to do is to nop out the sub instruction that dec your weapon's dur.
_______________________________________________________
PART 6: (life & mana, where would we be without them ?|
(Again you must DUMP !!!) |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ah, the life and the mana! The essence of every RPG ! We want to freeze them, cor
Then follow me ! hehehe... :)
Dump the memory, change your life points (ask a monster to hit you :)), search th
memory for changed values! Repeat this until u have only one addr!
bpm 1E635BC w
............code....................
mov edi,eax ------>move the "damage" to edi
................code...............
mov eax,[esi+810] ------>move your life to eax
push 3C ------>unimportant
sub eax,edi ------>substract damage from life
mov DWORD PTR [ESP+28],1 ------>unimportant
mov [esi+810],eax ------>update the new life in the addr
You will land after the above instruction in SI
..................code.............
What this code does: takes the amount of damage you receive from a monster and su
it from your current life!
To become invincible, you must nop out that "sub eax,edi" that is eating your lif
..................code code....................
mov cl,[eax*4+493D96] ------>mov the cost of the spell in cl
mov eax,[esi+80C] ------>mov in eax your mana points
sub eax,ecx ------>sub the cost from your mana
mov [esi+80C],eax ------>update the new mana
You will land in SI after the above instruction
.......................code code code............
I think it's clear for everybody: The game substracts the cost of the spell u cas
your mana points!
To prevent this & to have infinity mana & to cast spell after spell upon your ene
NOP that sub instruction !!!
_________________________________
PART 7: (hacking the properties)|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlike Diablo2, that when (for example) u find an item with enhanced damage, the
enhance your damage by a random number, Lamentation Sword have fixed weapon p
i.e:
in Diablo 2 : Long Sword may have damage 13
Long Sword may have damage 15
Long Sword may have damage 17
So, this means that the game keeps this values in a file. And that file is non ot
Sword.exe (the game's .exe!).
You'll find there all the weapons' names (u can change them too!), and above the
are the properties :))
Now, for example search for Devil's Bow who has Magic+5 and Sight+3 as special pr
Found! And now search up for 5 or 3 (Magic+5 and Sight+3), but the search must be
32_bit_signed_long type! (thanks Hex-Workshop!)
________________________________________
PART 8: (Hacking using cracking skills)|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I like this game very much! Since u have 3 characters to play with at the same ti
go to kill monsters with all 3, or u can leave in town (or in other region) t
"hurt_ones", and go and play with only one char.
But here comes the tricky part: if u find a good sword with one of your warriors
to give it to any of the other 2, they must be in the same region! If not, th
u that "Not in the same region". Mmmmm... It seems to me like a bug! Let's fi
Fire up W32Dasm and disassemble the Sword.exe. Now search that message (Not in th
region). Found!
...........code..........
cmp eax,ecx
je it_seems_like_they_are_in_the_same_region
...........code...........
* Possible StringData Ref From Data Obj -> "Not in the same region"
...........code...........
That's what u should see in W32Dasm! I think u guess what u have to do, eh?
Simple: Change the je (jump if equal) to jmp (jump always), and this way u'll pre
seeing that ugly message, and u should be able to exchange the weapons an
between your characters!
==========================================F I N A L W O R D S===============
Huh, i think that this was the biggest document i ever wrote!
Hope u learnt something useful from this, and u didn't fall asleep :))
Sorin (Splinter@email.ro)
EOF
Game Hacking - Tutorial v1.0Tutorial with picture available online here
http://www.ghu.as.ro/ghtuts/omega1.htm
About:
This is the 1st real tutorial I've made the others have been small simple things just so I know what to do, in the future.
This definately isn't the last tutorial I'll make, but I just have to find time.
Well I hope this tutorial is helpful to all you GameHackers out there.
Before you say it MiCRaL I know i could have used jmp but i wrote this tutorial before you told me and have edited it just to
write this in
I've tested it with jmp and it uses the same amount of bytes so i didn't see the point in changing the tutorial
I hope to get a new version out VERY soon, with Source-Code etc.
Search Memory.
Code Inject
Use EasyWrite
Use AutoHack
Make a trainer with Trainer Maker Kit 1.51
Future:
Alot more info on Code Injection as not many people know what this is, and how to do certain things, so I'll add everything I
learn to this tutorial.
Making a trainer in VB, Delphi, ASM, and C++
One HTML page for each Section, when it gets bigger. ie. SearchMemory.html, CodeInject.html etc.
Hype
MiCRaL
Raven
Curt
Artanis
Elissaios
Famore
Raiko
Johno
Ste J
Apoc
Ckob
ddh
Needed Tools:
TSearch v1.6
Trainer Maker Kit v1.51
Minesweeper - I'm hacking XP Version so values will be different on another OS etc.
Hacking:
Start WinMine.exe, then play a new game, so the timer counts up, then minimize the WinMine.exe window (to pause the
game)
Load up TSearch, and click the big Open Process Button at the top.double click on winmine.exe
Next click the "Init New Search" (1st One), button under the open process button.
"Value:" = Time Amount
"Type:" = 1 Byte (Value shouldn't be over 255 for now.)
Then click ok.
Once TSearch has found all the addresses, go back to winmine.exe, and let the time increase, minimize again and
then click the "Search Next" (2nd One), button under the open process button.
"Value:" = New Time Amount
"Type:" = 1 Byte
Click ok, then once search is complete, you should end up with 1 address, if not just repeat, the search next part.
NOTE:
When I edited the time, I never realised It was stored in 4 bytes, because I didn't realise the time went to 999, I don't play
winmine.exe
I start memory searching for 1 Bytes, you'll have more addresses to scan but more chance of hitting the right one if under
255.
Also, the addresses I use in this tutorial MAY be different it all depends on what Version of Windows you have and
Minesweeper.
We will see the "AutoHack" Window, in the bottom text box you will see:
CREATE_PROCESS At Address
LOAD_DLL : "DLL NAME" At Address
BREAKPOINT AT : Address
Go Back to TSearch
Click "Time" (with the right button) and click "AutoHack"
Then go to winmine, increase the counter, and then minimize and go back to "AutoHack" window.
You should see a screen like the screenshot above, "1002FF5" and "0x100579C" will be different if you use a different
winmine (win98/ME etc).
Now at the bottom you'll see the "Disassembler" Tab, Click it, then click on the Code above. 1002FF5 etc (Or vice-versa)
Decrease Counter:
Change from: inc dword ptr [0x100579C] Change To: dec dword ptr [0x100579C]
TMK Code:
DECREASE: Poke 1002FF5 FF 0D 9C 57 00 01
INCREASE: Poke 1002FF5 FF 05 9C 57 00 01
I got these, by reading what it said in the AutoHack Window before editing and after, take a look and you'll see what I mean.
NOP Counter:
Now left click the 01002ff5 line, and icons on the toolbar above will be enabled.
DMA:
If you you this method on a address that is DMA, all you have to do is nop the Game Code, 01002ff5 was the game code in
this instance, the game code is the code that changes the DMA address, so for money decreasing just nop the dec command,
autohack finds.
I'll go into more detail with this in the next version. (Screenshots etc)
EasyWrite:
Description: = Decrease
Top TextBox:
offset 0x1002ff5
dec dword ptr [0x100579C]
Bottom TextBox:
offset 0x1002ff5
inc dword ptr [0x100579C]
Top TextBox:
We take the 1002ff5 from AutoHack and write "offset 0x1002ff5"
We want to decrease when checked, and the code before was inc (Increase) so we write "dec dword ptr [0x100579C]"
Bottom TextBox:
We take the 1002ff5 from AutoHack and write "offset 0x1002ff5"
We want to increase when unchecked and the origiinal code was inc (Increase) so we write "inc dword ptr [0x100579C]"
Click ok and you should see its been added to the EasyWrite box.
If the checkbox doesn't appear then you've got an error in the code, RE-CHECK.
If its fine check the box next to it, and the counter should Decrease instead of Increase, and uncheck it and it should
return to normal.
Description: = NOP
Top TextBox:
offset 0x1002ff5
hex 909090909090
Bottom TextBox:
offset 0x1002ff5
hex FF059C570001
Top TextBox:
We take the 1002ff5 from AutoHack and write "offset 0x1002ff5"
We want to patch when checked, and the code before was inc (Increase) so we write "hex 909090909090"
Bottom TextBox:
We take the 1002ff5 from AutoHack and write "offset 0x1002ff5"
We want to unpatch when unchecked and the original code was inc (Increase) so we write "hex FF059C570001" or "inc
dword ptr [0x100579C]"
Click ok and you should see its been added to the EasyWrite box.
If the checkbox doesn't appear then you've got an error in the code, RE-CHECK.
If its fine check the box next to it, and the counter should Freeze instead of Increasing, and uncheck it and it should
return to normal.
All you have to do now is make a trainer, for the codes you just found:
Quick Help on making a trainer in TMK at bottom.
TMK Code:
Poke 1002FF5 FF 0D 9C 57 00
DECREASE
01
Poke 1002FF5 FF 05 9C 57 00
INCREASE
01
Poke 1002FF5 90 90 90 90 90
PATCH
90
Poke 1002FF5 FF 05 9C 57 00
UNPATCH
01
Also:
01002ff3 compares, the address for the Time to 3E7 (HEX) / 999 (DEC) which is the max amount of time you can have.
If then time equals 999 then it jumps past the increase, to address 0x1003007 which Exits The Function.
Another address to look at is 01002FE0, it compares 0x01005164 to 0, so I checked this out, when your alive this = 1,
when your dead it = 0.
Poke this address to 0 and the timer stops, poke to one and it starts.
Decrease:
If you use this method, then you notice the counter messes up as it tries to minus 0 there's a script in there if it equals zero
then jump out but it didn't work all the time.
So if you do a bit more code injection you'll be able to get it to work right.
Offset 0x10011b5
cmp dword ptr [0x100579C],0x0
je LONG 0x01003007
dec dword ptr [0x100579C]
ret
offset 0x1002ff5
call 0x10011b5
nop
offset 0x1002ff5
inc dword ptr [0x100579C]
So:
If 0x100579C = 0 then
Get out of function
Else
Decrease counter
TMK Code:
Poke 10011B5 83 3D 9C 57 00 01 00 0F 84 45
1E
PATCH
Poke 10011C0 00 00 FF 0D 9C 57 00 01 C3
Poke 1002FF5 E8 BB E1 FF FF 90
UNPATCH Poke 1002FF5 FF 05 9C 57 00 01
Just by AutoHacking one code you MIGHT find other ways of hacking that code or other codes.
I know your proberly thinking Whoopy Doo, Its Minesweeper, I'm only using minesweeper as an example, cuz everyone has
Minesweeper, and its easy to hack, so beginners should find this tutorial easy to follow.
So we've covered Memory Searching, Using AutoHack and Writing Easy Write code.
Hopefully in the next release I will clear this file up making it easier to read, understand, etc.
Add a few more things.
I don't know if you've noticed but in the last 2 week my knowlage of Code Injection has improved Greatly.
I'm hoping to get alot more knowlage to, and I am learning ASM while hacking. FUN :D
OMEGA = Elite.
Well not really but I'm getting there, slowly but I'm definately getting there.
Please remember I do NOT have SoftIce/Driver Studio, which is why I'm using TSearch.
I want it but i can get it :(
Repeat these steps for Increase, Patch And UnPatch, and then Save the Project and Compile.
Hi there guys it's me again and this time with an tutorial on hacking Minesweeper
Needed Tools :
» Any Game (i'll use Minesweeper)
» The OMNI TRAINER v 1.0 - get in www.omnitrainer.cjb.net
» Some Coke, Fanta or Coofe (hmm... I like coke, he he he....)
» Some music , of course....like Rock or Eletronic Music :)
» Do u have a brain, right?
1. Open Minesweeper.
2. Open the Minesweeper process in Omni Trainer. You can do this by using the Pro
4. Search for the Seconds Address. Click the Search button. To find the second ad
5. Check the Address. You should make sure that the seconds address you found is
6. Set the Modify Value and the Refresh Time. Since you want to get the lowest ti
7. Personalize the Location with a Label and Info. You may want to label this loc
8. Enable the Location. Double-click the location you just created to enable it.
9. Saving your Location List. To save your newly created location list use the Lo
--------------------------------------------------------------------------------
Tutorial by [D.N.A]
eXtalia (c) 2003
contact : dna.netz@ig.com.br or dna@extalia.com
web: www.extalia
italy 19-1o-2oo3
Minesweeper Reversing
A simple exercize
written by ZaiRoN
Introduction:
Minesweeper is one of the millions M$ games and in this tutorial I will explain you how to add a new feature
on the game. The new feature will give you the ability to view where the bombs are.
Literature:
http://www.woodmann.net/fravia/menusspa.htm
http://www.woodmann.net/fravia/TracePlus_MenuPatch.html
http://www.woodmann.net/fravia/kayaker_RegmonPlus.htm
http://www.codeguru.com/mfc/comments/50642.shtml
Target:
MineSweeper (English version for WinXP/W2k)
Program description:
Don't you ever played with this game in your boring days? I can't believe you :-p
Tools:
- a debugger (Ollydbg)
- a disassembler (Ida)
- a resource editor (Resource Hacker)
- Spy++
- c and asm compiler (lcc, masm)
music: Black Sabbath - Black Sabbath
Preamble
We will show where the bombs are as a *mouse-over* effect as the cursor moves over each grid
square. We will add all the modifications inside a dll and we will write a loader to patch the
program in memory. This is not only a reversing exercize but also a programming exercize because
you will have to code a dll, work with GDI and finally write a little loader. This tutorial is a resume
(with some differences) of a project at the RCE board, you can find the thread here.
We start finding all the places where we will have to put a jump to our code; after that we will write
the code to add to the program, we will write the dll and finally a little loader.
Find the point where to add the new menu item
We should be able to pass from normal to cheat mode (and viceversa) therefore the best way is to use
a new menu item. I will add the new item inside 'Game' menu, after the 'New' item.
We can use a resource editor but remembering that we need to patch the file in memory, we have to
think in a different way. How can I add a new item into an existing menu? We can use the function
InsertMenuItem. This function will be placed into a cave with all the other modifications needed by
the program. We will see later how to use this function, for the moment you only have to know that
InsertMenuITem will be called in the initialization part of the program, exactly after the menu has
been loaded (because it needs the menu handle...).
Now, we should find the place where to insert the jump to the new cave. The program uses LoadMenu
to load the menu:
:010014B9 push 1F4h <------- lpMenuName
:010014BE push hInstance <-- hInstance
:010014C4 call ds:LoadMenuW
:010014CA push 1F5h <------- lpTableName
:010014CF mov hMenu, eax
:010014D4 push hInstance <-- hInstance
:010014DA call ds:LoadAcceleratorsW
:010014E0 mov [ebp+hAccTable], eax
:010014E3 call sub_10023DB
:010014E8 mov eax, dword_10052A4
:010014ED mov ecx, yBottom
When the menu has been loaded you can insert the new item, I decided to put a jump to the code that will
call the InsertMenuItem directly at 10014E8. I did choose this particular address only because it has the
same number of bytes of the new jump instruction...
Find the point where the program checks whether a menu item has been pressed
This task is useful because we need to add/manage the new menu item, the special mode option. If you
check the 'special mode' item, the game will show you the bomb, otherwise the game will remain the
same.
There are many ways to solve this second point.
- You can use Spy++, a little application that gives you a view of many informations about a process that is
running on your system.
Run Minesweeper and then run Spy++. You will see a list of the running processes, find Minesweeper
process and double click on it. A dialog will show you some informations about the game, one of them is
the window procedure.
- Another way to locate the window procedure is to use Ida.
This is more or less the way explained by +Spath in his tutorial. Load the file into ida and press ctrl-p; a
dialog appears. This dialog contains the functions used by the program and, we are interested in WinMain
function, the one used to define the window class. This is useful because from here you can understand
where the window procedure is. The program uses RegisterClassW function to register the window class:
ATOM RegisterClass(
CONST WNDCLASS *lpWndClass // address of structure with class data
);
and:
This structure contains the window attributes; we are interested in lpfnWndProc because it points to the
window procedure. Look at the disasm Ida gave you and take the address we were looking for:
:01001472 mov [ebp+WndClass.style], edi <----------------------- style param
:01001475 mov [ebp+WndClass.lpfnWndProc], offset sub_100180A <-- lpfnWndProc param, our
address is 100180A
:0100147C mov [ebp+WndClass.cbClsExtra], edi <------------------ cbClsExtra param
:0100147F mov [ebp+WndClass.cbWndExtra], edi <------------------ cbWndExtra param
:01001482 mov [ebp+WndClass.hInstance], ecx <------------------- hInstance param
:01001485 mov [ebp+WndClass.hIcon], eax <----------------------- hIcon param
:01001488 call ds:LoadCursorW
:0100148E push ebx ; int
:0100148F mov [ebp+WndClass.hCursor], eax <--------------------- hCursor param
:01001492 call ds:GetStockObject
:01001498 mov [ebp+WndClass.hbrBackground], eax <--------------- hbrBackground param
:0100149B lea eax, [ebp+WndClass]
:0100149E mov esi, offset AppName
:010014A3 push eax ; lpWndClass
:010014A4 mov [ebp+WndClass.lpszMenuName], edi <---------------- lpszMenuName param
:010014A7 mov [ebp+WndClass.lpszClassName], esi <--------------- lpszClassName param
:010014AA call ds:RegisterClassW <------------------------------ RegisterClassW
Ok, now that we know where the window procedure is, it's time to use a debugger, Ollydbg.
Load the program and jump to the window procedure, we need to set a breakpoint. Remembering that we
are trying to find the part of the procedure which check whether a menu item is clicked, we need to break if
and only if a menu item is clicked. When an item is clicked, a specific WM_COMMAND message is sent to
the procedure. This specific message contains the menu item identifier (the one you have clicked on) in the
loworder word of the wParam parameter.
Take a look at the first part of the window procedure:
If we want to catch the click over one of the menu item we need to set a conditional breakpoint (Shift+F2)
at 1001810. The condition I have used is:
[EBP+0Ch]==111H && [EBP+10H]==209H
where '[EBP+0Ch]==111H' checks for the WM_COMMAND message and '[EBP+10H]==209H' checks
whether the 'Beginner' menu item is been clicked (you can use your preferred menu item :-)). Run the
program and click on the chosen item, Olly breaks. Steps a little and you will surely find the place where the
program checks which menu items is been pressed:
:010018B7 MOV EAX,111
:010018BC CMP ECX,EAX <-------------------- Is WM_COMMAND received?
:010018BE JA winmine.01001B3F
:010018C4 JE winmine.010019AD <------------ We jump if a WM_COMMAND has been received
...
:010019AD MOV ECX,DWORD PTR SS:[EBP+10] <-- ecx is the wParam
:010019B0 MOVZX EAX,CX <------------------- eax is the item identifier
:010019B3 CMP EAX,20B <-------------------- Is "Expert" item clicked?
:010019B8 JG SHORT winmine.01001A30
:010019BA CMP EAX,209 <-------------------- Is "Beginner" item clicked?
:010019BF JGE SHORT winmine.010019EE
This piece of code is what we were looking for; since we will have to check whether the new menu item
has been clicked, we will change the jump at 10018C4 into a new jump. We will see later how the code will
look like.
Find the point where the program checks whether a WM_MOUSEMOVE has been received
This is necessary because from here we will jump to the dll function that shows a possible bomb. In
order to find the place where the program checks for WM_MOUSEMOVE message we will change
the conditional breakpoint; the new condition will be: [EBP+0Ch]==200H
:01001B3F MOV EAX,DWORD PTR SS:[EBP+C] <-- the received message
:01001B42 MOV ESI,200 <------------------- 200h = WM_MOUSEMOVE
:01001B47 PUSH 1
:01001B49 XOR EDI,EDI
:01001B4B CMP EAX,ESI <------------------- is WM_MOUSEMOVE received?
:01001B4D POP EBX
:01001B4E JA SHORT winmine.01001BB4
:01001B50 JE winmine.01001DD5 <----------- yes, WM_MOUSEMOVE received
Stepping a little you will see that this type of message is not so useful for the original program therefore we
will change the jump at 1001B50.
How to modify the Minesweeper process
First of all we have to find a place where we will go to insert the new code; there are many caves
inside the file, you must only choose one of them. I will add the new code starting from 10049A5h.
What does this new code is supposed to do? It adds the new item menu and then it simply calls a
function from our dll.
InsertMenuItem is not imported by the program and so we will have to use the combination of
LoadLibrary/GetProcAddress functions. To use these two functions is pretty easy.
LoadLibrary: it's the first function to use and it maps the dll module into the address space of the
calling process. The function returns a handle that can be used in GetProcAddress to get the address
of a dll function.
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName // address of the string that names the executable module
);
GetProcAddress: returns the address of the exported dll function.
FARPROC GetProcAddress(
HMODULE hModule, // handle to DLL module (the value returned by LoadLibrary)
LPCSTR lpProcName // address of the string that names the function
);
Now that you know how to call InsertMenuItem we can see how this function looks like:
BOOL WINAPI InsertMenuItem(
HMENU hMenu, // Handle to the menu in which the new menu item is inserted
UINT uItem, // Identifier or position of the menu item before which to
insert the new item
BOOL fByPosition, // If FALSE, uItem is a menu item identifier. Otherwise, it is
a menu item position
LPMENUITEMINFO lpmii // Pointer to a MENUITEMINFO structure that contains
information about the new menu item
);
and:
typedef struct tagMENUITEMINFO {
UINT cbSize; // Size of structure, in bytes
UINT fMask; // Members to retrieve or set
UINT fType; // Menu item type
UINT fState; // Menu item state
UINT wID; // Application-defined 16-bit value that identifies the menu
item
HMENU hSubMenu; // Handle to the drop-down menu or submenu associated with
the menu item
HBITMAP hbmpChecked; // Handle to the bitmap to display next to the item if it is
checked
HBITMAP hbmpUnchecked; // Handle to the bitmap to display next to the item if it is
not checked
DWORD dwItemData; // Application-defined value associated with the menu item
LPTSTR dwTypeData; // Content of the menu item
UINT cch; // Length of the menu item text
} MENUITEMINFO, FAR *LPMENUITEMINFO;
Even if there are alot of parameters, the use of this function is pretty easy.
This is the code you have to inject into the Minesweeper program:
Now, we have to modify the instructions at 10014E8, 10018C4 and at 1001B50 because they have to
jump to the new code:
DWORD CheckMenuItem(
HMENU hmenu, // handle to menu
UINT uIDCheckItem, // menu item to check or uncheck
UINT uCheck // menu item flags
);
I did write the dll in asm but no one will stop you from writing it in other languages. Here is the first
function:
; Change the status of the new item
changeItemStatus proc
.IF word ptr [ebp+10h] == 212h ; 212h is the id I used for the new item
mov ebx, 10049A2h ; byte [10049A2] stores the state of the menu item
xor byte ptr [ebx], 08h
movzx eax, byte ptr [ebx]
mov ebx, 10052BCh ; address where the menu handle is stored
invoke CheckMenuItem, dword ptr [ebx], 212h, eax
.ENDIF
ret
changeItemStatus endp
The only thing that requires an explanation is the value stored at 10049A2. This byte is:
00h if the item is unchecked
08h if the item is checked
Why not 00h and 01h? That is because I use this address for store both the state of the item and the menu
item flag.
revealCell
Before writing the function we must understand where the bombs are stored.
We need to find a way to break when a cell is clicked. Exploiting the work we have done before, I will use
another conditional breakpoint at 1001810; the idea is to break when the left mouse button is pressed
(and then released). When this button is released, a WM_LBUTTONUP (202h) message is posted and so,
the new condition will be: [ebp+0Ch]==202h
Set the new breakpoint and click on a cell; Olly breaks, steps a little until Olly will tell you that you have
found the place:
The point number 1 is necessary because the bombs can not be outside the grid while the point number 2 is
the final check. The first cell (upper left corner) starts from coordinates 0x0C,0x37 and each cell is
0x10,0x10. Now that we know this information, we are able to implement the point number 1: a simple 'if'
based on the coordinates of the point where the mouse has been pressed. How did you know the x and
the y coordinates where the mouse has been pressed? WM_MOUSEMOVE will tell you; infact:
WM_MOUSEMOVE
fwKeys = wParam; // key flags
xPos = LOWORD(lParam); // horizontal position of cursor
yPos = HIWORD(lParam); // vertical position of cursor
Here is all that you need :-D
Point number 2: first of all, we have to check whether a cell hides a bomb; this is not a problem because
we know where the program stores the grid in memory and, we will easily perform this check but... how
can I reveal a bomb under a cell? The answer is inside Graphics Device Interface (GDI) library; in this specific
case we will use GDI to display a bitmap. My new version of the game displays the image that has the
bomb on the red background (open the program with a resource editor, you will find the image I am talking
about under "Bitmap-410-1033"). You can display the image you prefer taken from the proggie or created
by you. To display this image I use these functions: GetDC, BitBlt, ReleaseDC.
GetDC: retrieves a handle of a display Device Context (DC) for the client area of the specified window.
HDC GetDC(
HWND hWnd // handle of window
);
This is the first function we have to call and it takes a single parameter. How do we know the handle of the
window? Simple, these 3 functions are used by MineSweeper and so, the best way to understand how to
use them is to bpx them and to look how they are used. This time, put a bpx on GetDC and run again the
program. Ollydbg will surely break and the only thing you have to do is to take note of the address that
contains the handle...
BitBlt: it clips an image from a source DC to a destination DC.
BOOL BitBlt(
HDC hdcDest, // handle to destination DC, the GetDC returned address
int nXDest, // x-coordinate of destination rectangle's upper-left corner
int nYDest, // y-coordinate of destination rectangle's upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
HDC hdcSrc, // handle to source device context
int nXSrc, // x-coordinate of source rectangle's upper-left corner
int nYSrc, // y-coordinate of source rectangle's upper-left corner
DWORD dwRop // raster operation code
);
Easy. As before, the best way for to understand how to use the function is to bpx it on Ollydbg. If you want
to display another image you have to change the 6° parameter: hdcSrc.
.data
oldRow db "0100499D"
oldColumn db "010049A1"
; Display the image under a cell
revealCell proc
pushad
; Is the mouse pointer inside the grid ?
.IF word ptr [ebp+14h] < 0Ch || word ptr [ebp+16h] < 37h
jmp @exitRevealCell
.endif
@exitRevealCell:
popad
ret
revealCell endp
Postamble: conclusion.
The tutorial ends here, you only have to write a loader which will load the program and add the new
functionality in memory. I will not tell how to write a simple loader, you will find all the sources
inside the attached file.
Playing with the new version of the game I have discovered a weird fact; set the special mode feature
and make the first click over a bomb. Nothing happens, the bomb disappears; is there something
wrong in our work? Eheh, no. Where the bomb has gone? (Hint: it is a specific characteristic of the
program.. :-))
Greetings and thanks.
all the UIC members. As usual, feel free to
I would like to thank all the friends at RCE messageboard and
mail me for comments, suggestions, bug reports and/or whatever you want...
ciao,
ZaiRoN
zaironcrk(at)hotmail.com
Disclaimer
All the information given are for educational purposes only.
Bie comment:
This info is taken from http://www.codeproject.com/script/Articles/list_articles.asp?userid=172641
Unknown
Introduction
Ever wanted to know what is happening in the Minesweeper game behind the scenes?
Well, I did, and I decided to investigate it. This article is the result of my research, brought here just for you.
Main Concepts
NOTE: the first part of this article involves some assembly code, if there something you don't understand it's NOT important to the goal of this article. you CAN skip it. Nevertheless, if you want to
ask me about it, you're more then welcome to mail me your question.
NOTE 2: The program was tested on Windows XP, so if you got some other system it might not work.. if you got some other system, and it did worked, comment this article with your system info
so we all could enjoy that knowledge.
Update to NOTE 2: the code is now fixed in order to work on Windows 2000 as well. thanks goes to Ryan Schreiber for finding the addresses in Win2K.
Step 1 - Investigate winmine.exe
If you're not an assembly fan, you might want to skip to the end of this step, to the conclusions..
So, in order to know better what is happening behind the scenes of Minesweeper I've started by opening the file in a debugger. My personally favorite debugger is Olly Debugger v1.08, this is a
very simple and intuitive debugger. Anyway, I've open winmine.exe in the debugger and looked a bit on the file. I've found in the Import section (a section that lists all the dll functions that are
used in the program) the following entry:
which means that the Minesweeper uses the randomize function of the MicroSoft Visual C RunTime dll, So I thought it might help me. I've search the file to find where the rand() function is being
called, I've found only one such place:
Then I've put a breakpoint on this single call and ran the program. I've discovered that every time you click the smiley a new mines map is generated. the mines map is created as follows:
1. Allocate a block of memory for the mines map and set all the memory bytes to 0x0F, which means that there is no mine in that "cell".
2. second, loop over the number of mines and for each mine:
2.1. randomize x position (1 .. width).
2.2. randomize y position (1 .. height).
2.3. set the correct cell in the memory block to 0x8F, which represents a mine in this cell.
here is the original code, I've added some remarks, and bolded the important parts:
As you can see from the code I've discovered 4 important things:
1. Reading the memory in address [0x1005334] gives me the Width of the map.
2. Reading the memory in address [0x1005338] gives me the Height of the map.
3. Reading the memory in address [0x1005330] gives me the number of mines in the map.
4. Given x,y that represents a cell in the map, in column x, row y, the address [0x1005340 + 32 * y + x] gives me the cell value.
You might wonder, what kind of solution am I talking about? Well, after discovering that all the mine information is available for me, and all I need to do is read the data from the memory I've
decided to write a small app that reads this information and present it for you. It can even draw a map of its own, with a picture of a mine wherever I find one..
So, what is to design about that? all I need to do is put the address into a pointer (yes, they exist even in C#) and read the pointed data, right? well, not exactly, the reason why this is not the
case is that the memory where this data is stored is not in my application. You see, each process has its own address space so it could not access "by accident" memory that belongs to another
program, so in order to read this data I need to find a way to read the memory of another process, in this case, its the Minesweeper process.
I've decided to write a small class library, that will receive a process and will give me the functionality of reading a memory address from this process. the reason I've decided to make it a class
library is because there is allot of cases you might want to use it so why develop it again and again? That way, you could easily take the class and use it in your own application, and you are free
to do so. An example for where this class can help is if you write a debugger. All the debuggers I know have the ability to read memory of the debugged application..
So, how do we read another process memory? the answer resides in an API called ReadProcessMemory. this API actually let you read a process memory at a specific address. Only before you do it
you must open the process in a special read mode and when you finish you must close the process handle, to avoid resource leaks. The following operations are performed with the help of two
more API called OpenProcess and CloseHandle.
In order to use API's with C# you must use the P/Invoke, meaning you need to declare the API you're going to use, which is basically quite simple, but you need to do it in the .NET way, which is
not that simple sometimes.. I've found the API declarations in the MSDN:
HANDLE OpenProcess(
DWORD dwDesiredAccess, // access flag
BOOL bInheritHandle, // handle inheritance option
DWORD dwProcessId // process identifier
);
BOOL ReadProcessMemory(
HANDLE hProcess, // handle to the process
LPCVOID lpBaseAddress, // base of memory area
LPVOID lpBuffer, // data buffer
SIZE_T nSize, // number of bytes to read
SIZE_T * lpNumberOfBytesRead // number of bytes read
);
BOOL CloseHandle(
HANDLE hObject // handle to object
);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
Int32 bInheritHandle,
UInt32 dwProcessId
);
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[In, Out] byte[] buffer,
UInt32 size,
out IntPtr lpNumberOfBytesRead
);
If you want to know more information on the types conversions between c++ and c#, I suggest you searched msdn.microsoft.com for the topics: "Marshaling Data with Platform Invoke". Basically,
if you put there what is logically true, it will work. sometimes, a bit tuning is requested.
After I have these functions declared, all I need to do is wrap them with a simple class and use it. I've put the declarations in a separate class called ProcessMemoryReaderApi, only to be more
organized. The main utility class is called ProcessMemoryReader. This class has a property named ReadProcess, this property is from the type System.Diagnostics.Process, this is where you
put the process you want to read its memory.
The class has a method which opens the process in the read memory mode:
{
m_hProcess = ProcessMemoryReaderApi.OpenProcess(
ProcessMemoryReaderApi.PROCESS_VM_READ, 1,
(uint)m_ReadProcess.Id);
The PROCESS_VM_READ constant tell the system to open the process in read mode, and the m_ReadProcess.Id states what process do I want to open.
The most important method in the class is the one that reads the memory from the process:
IntPtr ptrBytesReaded;
ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess,MemoryAddress,buffer,
bytesToRead,out ptrBytesReaded);
bytesReaded = ptrBytesReaded.ToInt32();
return buffer;
This function declares a byte array in the requested size and read the memory with the API. Simple as that.
{
int iRetValue;
iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
if (iRetValue == 0)
throw new Exception("CloseHandle failed");
}
Step 3 - Using the class
Well, here comes the fun part. Using the class in order to read Minesweeper memory and reveal the map. In order to use the class you must first instantiate it:
ProcessMemoryReaderLib.ProcessMemoryReader pReader
= new ProcessMemoryReaderLib.ProcessMemoryReader();
then, you need to set the process you want to read its memory, here is an example of how to get the Minesweeper progress, once it is loaded, and set it as the ReadProcess property:
System.Diagnostics.Process[] myProcesses
= System.Diagnostics.Process.GetProcessesByName("winmine");
pReader.ReadProcess = myProcesses[0];
and all we need to do now is Open the process, read the memory, and close it when we finish. Again, here is an example of how its been done. Here I read the memory address that represent the
Width of the map.
pReader.OpenProcess();
int iWidth;
byte[] memory;
memory = pReader.ReadProcessMemory((IntPtr)0x1005334,1,out bytesReaded);
iWidth = memory[0];
pReader.CloseHandle();
that simple!
In conclusion I present you the full code that reveals the map of mines. Don't forget, all the memory places I'm accessing are places found in the first section of this article..
ProcessMemoryReaderLib.ProcessMemoryReader pReader
= new ProcessMemoryReaderLib.ProcessMemoryReader();
System.Diagnostics.Process[] myProcesses
= System.Diagnostics.Process.GetProcessesByName("winmine");
int bytesReaded;
int iWidth, iHeight, iMines;
int iIsMine;
int iCellAddress;
byte[] memory;
int x,y;
for (y=0 ; y<iHeight ; y++)
for (x=0 ; x<iWidth ; x++)
{
ButtonArray[x,y] = new System.Windows.Forms.Button();
ButtonArray[x,y].Location = new System.Drawing.Point(20 + x*16, 70 + y*16);
ButtonArray[x,y].Name = "";
ButtonArray[x,y].Size = new System.Drawing.Size(16,16);
if (iIsMine == 0x8f)
ButtonArray[x,y].Image = ((System.Drawing.Bitmap)
(resources.GetObject("button1.Image")));
this.Controls.Add(ButtonArray[x,y]);
}
I- Table of contents:
I- Table of contents :)
II- Thanks
III- Needed Tools
IV- Basic about Game Hacking
V- Finding Address with GameHack (GH)
MiCRaL
Shaikh Adeel
Tsongkie
Vivien Abner
MacDeath ťť Thanks for fixing errors with my english...
Start Monopoly Tycoon and select a new game. Look for the money value, ALT+TAB and start GameHack 2.0.
Click the first icon to select Monopoly Tycoon.
The same for the value 3, 4, etc. You'll need to test all address, because only one is the real address. This game
use DMA.
Get others tutorials about it.
ťť Tutorial by [D.N.A] ŤŤ
tekz (c) 2002
do not use without permission our plz
contact : dna.netz@ig.com.br
Using Game Trainer to hack Monopoly Tyccon
I- Table of contents:
I- Table of contents :)
II- Thanks
III- Needed Tools
IV- Basic about Game Hacking
V- Finding Address with GameTrainer (GT)
MiCRaL
Shaikh Adeel
Tsongkie
Vivien Abner
MacDeath ťť Thanks for fixing errors with my english...
Run game Monopoly Tycoon first, and then open up the GameTrainer program.
Look for a Process combo box, and select "mc.exe" from the list. Look at the image below.
Wait a few seconds. Then you will hear a small beep and GameTrainer will report that several thousand addresses
were found. This is
way too much! I have found 47 addresses.
Now, go back to the game and build any item. Look for the new value and back to the GT. Type the new value
and click Sieve.
Wait a bit and you should find only 4 addresses now. That is the address you need! Double click on the address to
add it to the Target
List. Now you have control over this address. You can double click on the Value field to change its value. Try it!
You need to test all
addresses, because only one is the "real address". This game uses DMA. Get others tutorial about it"
ťť Tutorial by [D.N.A] ŤŤ
tekz (c) 2002
do not use without permission our plz
contact : dna.netz@ig.com.br
Using TSearch 1.4a to hack Monopoly Tycoon
I- Table of contents:
I- Table of contents :)
II- Thanks
III- Needed Tools
IV- Basic about Game Hacking
VII- Finding Address with TSearch (TS1.4a)
MiCRaL
Shaikh Adeel
Tsongkie
Vivien Abner
MacDeath ťť Thanks for fixing errors with my english...
Start Monopoly Tycoon and select a new game... Look for the money value, ALT+TAB and start TSearch 1.4a
You have two options to select Monopoly Tycoon:
First option
f
Click the first icon to select Monopoly Tycoon.
Second option
Its faster for you to use the "Select process list" little screen.
Now, you need select MC.exe (exe of Monopoly Tycoon)
Then start a new search:
ť Tutorial by [D.N.A] ŤŤ
tekz (c) 2002
do not use without permission our plz
contact : dna.netz@ig.com.br
In-Game Menu:
-------------
Written by Omega
Game:
-----
Mortal Combat 4 *Rip* (12-13meg on kazaa)
Explanation:
------------
In-Game menu's are good for if you have a game with alt-tab protection
or if you have alot of hotkeys, and lazy users.
as i stated above GetMessage And GetTickCount are 2 of a few API calls that are a
and this game, uses GetMessage, so i'm just gonna get straight to it.
We need to replace line 004C52D8 with our jump to our codecave. i'll do that in a
for now.
push Style
push Caption
push Text
push WindowHandle
call MessageBoxA
So we need to put that into the game as well as the GetMessage we replaced.
I chose:
"0x4D1b90" For The Caption
"0x4D1b9f" For The Text
"0x4D1c1f" For The Injected Code.
push 0
push 4D1b90
push 4D1b9f
push 0
// MessageBoxA
call [4D2214]
// GetMessageA
call [4d21c8]
jmp 004C52D8
But because were pushing 0 as the WindowHandle then this won't work.
and the messagebox will be displayed outside of the game, and could crash the gam
we need to find a way of getting the games window handle.
Thankfully the game stores the WindowHandle in memory when it window is created (
So go back to W32Dasm Click "Imported Functions" Again
Then find "USER32.CreateWindowExA" double click it.
So we need to add:
push 0
push 4D1b90
push 4D1b9f
mov eax, [00F9F7C0]
push eax
// MessageBoxA
call [4D2214]
// GetMessageA
call [4d21c8]
jmp 004C52D8
Key:
====
ASC = Write Text
Hex = Write Hex
Hex 0a = New Line
Hex 0a0a = 2 New lines
Hex 00 = End Of Message
Top Window:
===========
offset 0x4D1b90
asc "Title"
offset 0x4D1b9f
asc "InGame Menu"
hex 0a
asc "========="
hex 0a
asc "Created by Omega"
hex 00
offset 0x4D1c1f
push 0
push 4D1b90
push 4D1b9f
mov eax, [00F9F7C0]
push eax
//MessageBoxA
call [4D2214]
//GetMessageA
call [4D21C8]
jmp 4c52de
Bottom Window:
==============
offset 0x4c52d8
call [0x4D21C8]
We don't need to remove our injected code as it won't be called.
Now all you need to do it make it poke all the bytes, then wait a few seconds the
Because we replaced GetMessage, and it gets called near enough all the time the g
I found the code cave, by Using TSearch's Hex Editor, and searching fora lot of
you'll come to alot of places, but eventually you'll find a cave, just load into
This is just oneway of injecting stuff you can inject dll's, trainers, etc etc.
Thanks:
Orr: For his amazing tutorial helping me to write this one.
Quake2 wallhack tutorial - cppdude
This fairly advanced tutorial is going to teach you how to make a wallhack for Qu
Ok lets go. Look in you Quake2 dir. Youll find a ref_gl.dll dll file. This file i
Our wallhack will have 2 modes. The first will be a wireframe mode, where we will
DrawMode(Lines)
Drawworld()
DrawMode(Fill)
return //to game code
Pretty easy that. DrawMode will force all drawwing after that call to be done wit
Ok now you understand the theory of our first wallhack mode, lets put it into pra
The address of the string ref is being pushed as a parameter to a function. What
r_drawworld 0
The function then returns a pointer to a variable. Functions return values by sav
Great. Youve now found the function that draws the world. You can see that the po
We have now found out where the drawworld function is called. Hooray! We can now
This is where we start using TSearch; to make asm scripts. Read the TSearch help
We now need to make a call to the DrawMode function. The OpenGL api we will use f
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
So now we need to make a call to the function glPolygonMode, and we need to find
Here the address of the string ref "glPolygonMode" is being pushed as a function
The address is saved in two places. Do a search for one of these addresses and yo
You now know how to call glPolygonMode. Soon you can add it to your TSearch asm s
Now we need to push GL_FRONT_AND_BACK which is defined as 0x0408. Then you call g
Now that all following polygons are drawn in line mode, we can call drawworld. We
Great. We now have our code section defined. We now need to make a call to it, by
Disaster!!! Quake2 now looks a mess. Every frame that Quake2 draws is being drawn
glClear(GL_COLOR_BUFFER_BIT);
but Quake2 already has a cvar to do this so i would rather hack that. The Quake2
You can see that 0x4100 is being pushed. If this is used as the paramater to glCl
So now your TSearch asm script will now look like this:
If you run this you will have a fully working wallhack for Quake2. If you want to
You are probably thinking: how can i remove that gay pink as the clear color? Joh
for a nice calm blue. The first 3 params are RGB, and the 4th is an alpha value w
I cant be bothered to explain exactly how i do the second wallhack mode, because
glDisable(GL_DEPTH_TEST);
drawentities();
glEnable(GL_DEPTH_TEST);
return;
GL_DEPTH_TEST is defined as 0x0B71. One other thing you should know, you must dra
:10008EB2 E889F9FFFF call 10008840
:10008EB7 E874F8FFFF call 10008730
:10008EBC E80FFCFFFF call 10008AD0
:10008EC1 E82A330000 call 1000C1F0
:10008EC6 E8B5310000 call 1000C080//drawworld
:10008ECB E8A0F2FFFF call 10008170//drawentities
:10008ED0 E83BAFFFFF call 10003E10
:10008ED5 E8D6F5FFFF call 100084B0
:10008EDA E811250000 call 1000B3F0
:10008EDF E82CFFFFFF call 10008E10
Drawentities is also called there. When i made my depth test hack I made that dra
That sums up my Quake2 wallhack tutorial. The methods here can be applied to any
You may be wondering why i made this tutorial using Quake2 instead of Quake3. Wel
Also, i like to get the bytes generated by TSearch and put them into a C++ progra
This fairly advanced tutorial is going to teach you how to make a wallhack for Qu
Ok lets go. Look in you Quake3 dir. Youll find a quake3.exe file. Unlike quake 3,
Our wallhack will have 2 modes. The first will be a wireframe mode, where we will
DrawMode(Lines)
Drawworld()
DrawMode(Fill)
return //to game code
Pretty easy that. DrawMode will force all drawwing after that call to be done wit
Ok now you understand the theory of our first wallhack mode, lets put it into pra
The address of the string ref is being pushed as a parameter to a function. What
r_drawworld 0
The function then returns a pointer to a variable. Functions return values by sav
Great. You've now found the function that draws the world. All three of them this
...
...
We have now found out where the drawworld function is called. Hooray! We can now
This is where we start using TSearch; to make asm scripts. Read the TSearch help
We now need to make a call to the DrawMode function. The OpenGL api we will use f
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
So now we need to make a call to the function glPolygonMode, and we need to find
Here the address of the string ref "glPolygonMode" is being pushed as a function
The address is saved in a couple places. Do a search for one of these addresses a
You now know how to call glPolygonMode. Soon you can add it to your TSearch asm s
Now we need to push GL_FRONT_AND_BACK which is defined as 0x0408. Then you call g
Now that all following polygons are drawn in line mode, we can call drawworld. We
Great. We now have our code section defined. We now need to make a call to it, by
So we add a call to our code section in our asm script so that it now looks like
Disaster!!! Quake2 now looks a mess. Every frame that Quake2 draws is being drawn
glClear(GL_COLOR_BUFFER_BIT);
but Quake3 already has a cvar to do this so i would rather hack that. The Quake3
...
Search for where that pointer (007CA198) is being referenced like you did before
:0045A1C9 FF15A4E17B00 call dword ptr [007BE1A4] ;[007BE1A4
:0045A1CF 8B0D98A17C00 mov ecx, dword ptr [007CA198] ;[007CA198
:0045A1D5 8B4120 mov eax, dword ptr [ecx+20]
:0045A1D8 85C0 test eax, eax
:0045A1DA 7422 je 0045A1FE
:0045A1DC 680000803F push 3F800000 ;float val
:0045A1E1 680000003F push 3F000000 ;float val
:0045A1E6 6A00 push 00000000 ;float val
:0045A1E8 680000803F push 3F800000 ;float val
:0045A1ED FF1500E27B00 call dword ptr [007BE200] ;[007BE200
:0045A1F3 6800410000 push 00004100
:0045A1F8 FF15CCE07B00 call dword ptr [007BE0CC] ;[007BE0CC
...
...
You can see that 0x4100 is being pushed. If this is used as the paramater to glCl
offset 0045A1DA
//je 0045A1FE
hex 9090
offset 0045A726
//je 0045A74A
hex 9090
offset 0045A8B4
//je 0045A8D7
hex 9090
If you run this you will have a fully working wallhack for Quake3. If you want to
You are probably thinking: how can i remove that gay pink as the clear color? Joh
glClearColor(0.0f, 0.5f, 0.75f, 1.0f);
If you noticed earlier at offset :0045A1ED :0045A739 :0045A8C6 these are all call
offset 45a728
hex 9090909090
hex 9090909090
hex 9090
hex 9090909090
hex 909090909090
offset 45a1dc
hex 9090909090
hex 9090909090
hex 9090
hex 9090909090
hex 909090909090
offset 45a8b6
hex 9090909090
hex 9090909090
hex 90
hex 9090909090
hex 909090909090
for a nice gray. The first 3 params are RGB, and the 4th is an alpha value which
push 3f800000
push 3F000000
push 3F000000
push 3F000000
//call glClearColor values are set to light gray
call dword ptr [007BE200]
//call drawworld
call 466d90
offset 0045A1DA
//je 0045A1FE
hex 9090
offset 0045A726
//je 0045A74A
hex 9090
offset 0045A8B4
//je 0045A8D7
hex 9090
offset 45a1dc
hex 9090909090
hex 9090909090
hex 9090
hex 9090909090
hex 909090909090
offset 45a8b6
hex 9090909090
hex 9090909090
hex 90
hex 9090909090
hex 909090909090
That sums up my Quake3 wallhack tutorial. The methods here can be applied to any
Start RCT.
Now you should be in ur park "DO NOT BUILD ANYTHING!" and have " 0 " guests right
Get back in the game,Open your park so guest can visite it,let some guests in 3 e
Get back to Tsearch search for 3 ( or the value of guest u let come in to the par
Now you should have ONE address if you have done this right.
Double click on it,then on the window the the right you should see it,double clic
Written By X-Undead
I'll make a .html format of it next time with Pictures and more text,was just to
Later/
UnDeaD
X² Tutorials
This tutorial assumes you have softice installed and a basic knowledge
of it.
5. Alt-tab to windows.
11. Return to the game and spend some money, I chose landscape
and plant trees. (note the amount of money you have after spending)
20. Go into the game and spend some more money noting how much
you have left after spending. (I chose trees again)
22. Go into gamehack and see which value matches your money.
(mine is 59997)
23. That means that the top value is the real one so click the bottom
value (click on description) and delete it.
24. Now write down the real value. (mine was 02ABB6D4 but yours
will be different, it changes each time you play the game, this is known
as dynamic memory)
26. <ctrl-d> to pop into softice. (also type "code on" to enable code)
27. Type "bpm 02abb6d4 w" and hit enter, this sets a breakpoint on
your address and it will break upon any write.
31. Since the game is subtracting money we look for a "SUB" above
the code softice landed on.
32. The code in green is the "SUB" command we are looking for.
33. Double click the green code in softice, that sets a breakpoint at
that address. (if any problems, type in "bpx 0132895d")
34. Type "bl" and hit enter. (this lists all current breakpoints)
38. Type "a" and hit enter, type "nop" enter, "nop" enter, "nop"
enter and hit <ctrl-d> to exit softice. (if any problems you can
manually nop the address by typing "a 0132895d" and then the nops.)
(the reason you nop 3 times is this, the code is 2B4508 so you nop
once per 2 digits, 6 divided by 2 is 3)
39. <ctrl-d> to enter softice and type "bc *" to clear all breakpoints.
41. Now you can create a trainer that nops address 0132895D 3 times,
or 90 90 90 which is nop in machine language.
42. Enjoy...
Written by Logician
Proud member of X²
TUT NO. 4
~~~~~~~~~~
OK. In the following, i'll teach (in case u don't know) how to hack Solitaire! Be
not that simple, and u can't do almost anything with a mem finder!
To hack Solitaire you need some experience! It isn't a hack that you go for trapp
when it dec the timer! It uses some Windows fuc*ing .dlls to do it's job (i t
it's useless to change the memory because the .dlls are changing\using it ins
game and if u do that ==> program crash (kernel or solitaire or your mem. fin
I tried with a mem finder, but found nothing! Maybe u will be more lucky !! ;}
To avoid this i recommend u another method (a cracking approach). Yes, this metho
more used when crack !
Go and grab W32Dasm if u haven't done it by now (u can use any other disassembler
is the best! ). Make a copy of Solitaire and disassemble-it !
But first i must tell u this : games like Solitaire uses the user32.dll's SetTime
(to manage the time-elapsing). So our task is to look in the Solitaire.exe fo
function. That's why u need a disassembler!
Now above the SetTimer there are some pushes. Those are needed for the function t
properly. Check the SetTimer function's parameters below:
The SetTimer function creates a timer with the specified time-out value.
UINT SetTimer(
Parameters
hWnd
Identifies the window to be associated with the timer. This window must be owned
calling thread. If this parameter is NULL, no window is associated with the t
the nIDEvent parameter is ignored.
nIDEvent
Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this paramet
ignored.
uElapse
lpTimerFunc
Points to the function to be notified when the time-out value elapses. For more i
about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application qu
hwnd member of the message's MSG structure contains the value of the hWnd par
============================end cut===================================
But the pushes are being pushed backwards! So, first on the stack is pushed the l
then uElapse followed by nIDEvent and hWnd!
So at this point we know that we must get the "uElapse" value. The pushes are:
in solitaire: | in general:
|
push word ptr [01F0] | pTimerFunc
push 029A00FA | uElapse
push dx | nIDEvent
push word ptr [01F2] | hWnd
So, the "push 029A00FA" is the elapsing time! I don't know how the game processes
to make a delay of ~1sec. I modify this number typing some random numbers (e.
029A0000 instead of 029A00FA) and the time flew very fast!
So, to make the timer run very slow, u need to change the "push 029A00FA" to "pus
How to do that? SIMPLE!
Grab any hex-editor, go to the push's offset, and modify the beast! (u can wiew t
offset in W32Dasm, by putting the gray line over the "push 029A00FA", and loo
bottom of W32Dasm's window. There should be 950 in the Sol.exe that i include
.zip)
Now, that we are done with this, let's make a full "hack", by trapping the code t
pts when undo\restart_poket. But u know how to do that ! No? WTF...
Sorin ( Splinter@email.ro ).
Tutorial: Starcraft Screen Messages
Author: Drakken
Date: 4/24/03
Site: http://www.GameThreat.com
Game: Starcraft/Broodwar version 1.10
_____________________________________
Intro:
In this tutorial I'm going to show you a way to send client side messages to the
_____________________________________
Memory Searcher/Editor - I use Winhack. It's decent and easy to use but it is sha
W32Dasm - This is a disassembler. You can also use IDA which is more advanced but
You should be able to find these tools pretty easily on the net. Search on google
Some knowledge of assembly will really be helpful but not totally necessary. Hope
_____________________________________
Let's begin:
Start up starcraft and load a game. Do not start a single player campaign game be
First we want to find where starcraft stores the text that is displayed on screen
Open the text box and type "Drakken is my hero" and press enter. hehe ;). Now ope
Now go through and find all eleven offsets for the screen text. Write a different
Now we've got all eleven offsets. (there's actually a couple more but don't worry
We will have to set a breakpoint in softice on one of the offsets to find where s
BPM 650CA8
Press enter to set the breakpoint. Then press ctrl-D to exit softice. Softice wil
Now let's look at the disassembly so we can see what's going on at 46B825. Open W
When it's done you can click disassembler and save the disassembly to a project f
Now click Goto, then Goto Code Location. In the code offset box enter the offset
ASM Code:
:0046B812 Call dword ptr [004E61A0]
:0046B818 mov edi, eax
:0046B81A xor esi, esi
Comments:
:0046B812 calls GetTickCount (result ends up in eax)
:0046B818 moves the tick count from eax to edi for use below
:0046B81A clears esi
You may still be confused by all that. I'll try to sum it up. First it calls GetT
Now we know that it's using GetTickCount to check the message timer. So we also k
Message - Timer
650CA8 - 6517BC
650D82 - 6517C0
650E5C - 6517C4
650F36 - 6517C8
651010 - 6517CC
6510EA - 6517D0
6511C4 - 6517D4
65129E - 6517D8
651378 - 6517DC
651452 - 6517E0
65152C - 6517E4
Now that you know the timers for each message offset you can write a timer value
6517BC 0F 0F 0F 0F
650CA8 44 72 61 6B 6B 65 6E 20 72 75 6C 65 73 21 00
Neat eh? But there are two problems. That message will stay on screen for a reall
To solve the timer problem, in your program make a call to GetTickCount. To deter
Now let's figure out how to tell which message offset is the bottom one. Look bac
Now look down just below these offsets and you'll see another offset sticking out
Hrm what could this be? Let's take a look. First notice that it's pointing to a d
_____________________________________
Summary:
Now to put all this info to good use in your program. First you want to use ReadP
Update:
Use these hex bytes in your messages to add colors.
0x02 default White/dull blue
0x03 Yellow
0x04 Bright White
0x05 Grey
0x06 Red
0x07 Green
_____________________________________
Conclusion:
Remember that these are client side messages only. No one else will see them but
I'm sure some of you are going to want to go and make an ally detector program ri
I hope you learned something new from this tutorial. If not, at least you know ho
Feel free to post this tutorial on your own site as long as it remains unmodified
_____________________________________
Drakken
©GameThreat.com 2003
Hacking StarCraft with Cheatzzz...
Needed Tools :
» StarCraft v1.09
» TSearch 1.6 (the new version)
» Music again, of course....I listen to Patience/November Rain (Guns 'n
Roses)
» Get them at TekZ 8193 (tekz8193.com)
2. Open the SC process in TS. You can do this by using the Open Process
menu. Select StarCraft in "Select Process" window.
3. Start new game...I like Protoss :)...Pause the game and go to TS.
5. Unpause game (hehehe) and press [ENTER] to type the cheat: I use "modify
the phase variance" (its ability to build anything). Pause again and go TS.
6. Now use "Search next", select "Has changed" (Search), and "1 Byte"
(Type)
7. It comes up with a lot of them. Repeat the steps 5 and 6 again and again
....until u get 3 or 4 of them.
9. Go back to SC and disable all cheats. Go to TS and test all values, and then
go back to game and see if it works....:)
P.S.: A lot of games use diferent addresses to "write a cheat", but SC uses one
address for cheats....example: my address for the cheat is "52568D" (1Byte).
When this cheat (only the modify the phase variance cheat) is enabled, my
value is 32. When I use the "war aint what it used to be" (Disables Fog of
War. Only this cheat is on), my value is 63....but when I enable the 2 cheats,
my value is: 96....
Cya guys...
* Thx to JoeIsMy Name *
* and MacDeath *
Tutorial by [D.N.A]
The East KidZ © 2002
Contact: dna.netz@ig.com.br or dna@tsongkie.com
web: www.vngamecenter.com
Tutorial: Making a Starcraft Name Spoofer
Author: Dragon484
Date: 9/0/03
Site: http://www.GameThreat.com
Game: Startcraft/Broodwar
(This tutorial was modeled around drakkens
Startcraft screen messages tutorial)
___________________________________________
Intro:
Making a Name Spoofer for starcraft is
acutally very simple, if your having
trouble getting started then use this
tutorial and learn something.
___________________________________________
Tools:
A Memory editor, i use tsearch.
Starcraft Broodwar, updated to version 1.10
___________________________________________
___________________________________________
Colors:
Adding colors is always fun but it gives
your self and others a temp ban from bnet.
Anyway adding colors is very easy once you
have found the spoofer offset. All you need
to do is changethe first byte of your name
to a color code.
Example:
Memory Ascii
44 72 61 67 6F 6E 34 38 34 Dragon484
*Now Change the first byte to a color code"
03 44 72 61 67 6F 6E 34 38 34 .Dragon484
___________________________________________
Other Sc Tutorials:
Softice for beginngers - Drakken
Single player mineral hack tutorial - lordlardo
**code injection - Dma to static Address - drakken
Starcraft Screen Messages - Drakken
(www.gamethreat.com-> fourms->downloads->tutorials)
___________________________________________
-Dragon484
(This Tutorial was orginally posted @ www.gamethreat.com)
HACKING STARCRAFT(BROODWAR)
Well, I will spend a little time to teach you how to hack Starcraft.
Yes, that's right. Instant build lets you build structures & units
IMMEDIATELY...
Tools needed:
~~~~~~~~~~~~~
-SoftIce
-Mem. finder (i use TSearch for this example)
-a little time to listen :)
Level:
~~~~~~
-Advanced
Let's BEGIN
~~~~~~~~~~~
Ok, Fire up BroodWar & enter a single player game. Choose to play custom
and not campaigns... I choosed map challenger & I played with zergs - but
this doesn't matter...
Now, since we wanna make INSTANT BUILD hack, we want to build something
(to see how it modifies the memory). & to build, we need minerals. Just type
[ENTER] Show me the money [ENTER] in SC, to have the cash :)
After that, put your "probe" to build something... After the probe started to
build, pause SC (hit F10), ALT+TAB, enter TSearch and search for "unknown val
in Starcraft's memory. After TSearch finished it's job, enter in SC, unpause
the game for a sec or 2. The building hit-points will increase. Pause the gam
again, and in TSearch choose the option "has decreased" (thnx Groza for
your tut). This means that we're searching the values that have decreased.
If we don't find anything this way, next time we'll search the values that
have increased. Get the point? But i assure you that "has decreased" is for
Starcraft :). After TSearch finish it's job, go back in the game, unpause for
a sec or 2 (to inc the hit-points of the building), then in TSearch choose ag
"has decreased". Repeat these steps until you will find about 6-7 addresses i
TSearch. Now we must find the correct one by taking each of them (IN ORDER) a
modify it, then back in the game to see what happend. I'll make your job easi
and i'll tell you the address. It's the first one (in TSearch) that starts wi
634XXX (mine was 6342C4 - i'm using SC version 1.12, yours could be different
So, we got the address (i found this address by putting 0 into it. Since SC dec.
the timer until you building is finished, 0 will probably be the finish of ou
construction). DON'T PUT 0 (YET) AT THAT ADDRESS BECAUSE WE CAN'T TRAP IT WIT
WHEN IT'S BEING DECREASED !!!
In SoftIce type:
bpm the_address w (the_address=found address)
After you can see, the time remaining is decreased one by one...
Let's put a breakpoint (bpx) on the ret instruction for later use.
So, let's make our PC an easier life and put a 0 in eax :) To do so, find a code
then overwrite the "mov [ecx+ac],ax" instruction with "jump code_cave".
In the code cave: "xor eax,eax","mov [ecx+ac],ax","jmp back" to write 0 in our ad
NOTE: If you don't know what code cave is, read some more tuts, then come back! :
This tut is not for Newbies!!!
Voila... Hey, the structure is build, but it's hit-points remained the same!
That's because we modified only the state of the building in the building
process. When we had set the time_remaining to 0, the game thought that it's
hit-points were also increased to maximum (the building is ready WHEN it's
hit-points are maximum - in case you're not attacked :).
That's why i told u to put a bpx on the ret. To see what's happening next!
SI should break at the ret. Trace with F8 until you see a comparation like jle,
jl,jge,jg. Game uses those often to compare the current_building_hit_points w
building_is_finished_hit_points.
After trace, you should come to this piece of code (this is inside a call, that's
why you had to trace with F8)
........code.....code.............
XXX:XXXXXX MOV ECX,[ESI+8] ->mov in ecx the current_hit_points *encrypted*
XXX:XXXXXX MOV EAX,[ESI+64] ->mov in eax a hit_point *encrypted*
XXX:XXXXXX ADD ECX,EAX ->increase building hit_points
XXX:XXXXXX MOV [ESI+8],ECX ->update an address
XXX:XXXXXX MOV EAX,[EAX*4+6A9BA8] ->mov in eax the_maximum_building_HP *encrypted
XXX:XXXXXX CMP ECX,EAX ->IS building finished?
XXX:XXXXXX JLE building_not_ready ->if no, then jump
XXX:XXXXXX MOV [ESI+8],EAX ->if yes, put in address the maximum_HP *encrypted*
.............code.......code......
It's easy to figure out what you should do... NOP the jle instruction to make the
always update the addr with the maximum_HP...
Also, notice that this hack will make your units INVULNERABLE because the game us
same routine to manage units' health. Another notice is that YOU HAVE to jump
when i showed you the first piece of code (and not just xor eax,eax, update a
otherwise the game crashes when "operation cwal" cheat is on!
FINAL WORDS:
~~~~~~~~~~~~
It seems that we shoot 2 rabbits from one shot (instant-build & invulnerability).
And the instant_build hack works FASTER than the game's cheat code.
Sorin ( Splinter@email.ro ).
eof
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|_|_|_|_|_| |_|_|_|_|_| |_|_ _|_| |_|_|_|_|_|
|_| |_| |_| |_|_|_|_|_| |_|
|_| |_| |_| |_| |_| |_| |_|
|_| _ _ _ |_|_ _ _|_| |_| |_| |_|_|_|
|_| |_|_|_| |_|_|_|_|_| |_| |_| |_|
|_| |_| |_| |_| |_| |_| |_|
|_|_ _ _|_| |_| |_| |_| |_| |_|_ _ _ _
|_|_|_|_|_| |_| |_| |_| |_| |_|_|_|_|_|
H H AAAAAA CCCCCC K K I N N GGGGGG
H H A A C K K I NN N G
HHHHHH AAAAAA C KK I N N N G GGG
H H A A C K K I N N N G G
H H A A C K K I N NN G G
H H A A CCCCCC K K I N N GGGGGG
Target : StarCraft-BroodWar
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Level : Intermediate(-Advanced)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LET'S START
~~~~~~~~~~~
Back to work again, eh ? After a few days of playing CS (man, I LOVE this game...
I decided to "hack" BroodWar... No, not the minerals, but the cheat codes !
If you had read my previous tut (about Worms2), you should know what I'm trying t
do... If you didn't (you naughty boy!), then I'll explain once more...
So, we want to intercept StarCraft when it reads the cheat_codes. (Windows progra
often use GetDlgItemText(A) or GetWindowText(A) to read the text inside an
edit_box. But we don't have such thing (edit_box) in StarCraft :( .
Then maybe we can catch a call to Kernel's HMEMCPY. This HMEMCPY is another way
to see where a program reads text inside an edit_box (and not only!). The
applications doesn't call this function, but Windows works with it when
something goes to memory (i.e. when you type something in NOTEPAD).
Also, Delphi programs doesn't call GetDlgItemText(A) or GetWindowText(A) to
read the text inside edit_boxes...
(Delphi progies are often debugged with a bpx on HMEMCPY :) ).
Got the idea ?
Now, let's try this on StraCraft. Enter the game, and in SoftIce type:
bpx hmemcpy
As my good_old pal ParaBytes told me : "The games have their own HMEMCPY" !
But how ? Here's the explanation : Games have their own functions to read the tex
that you type in. That function is PROBABLY hidden in a .DLL file of the gam
It can be, of course, inside the .exe, but in most of the cases, IT'S IN A .
And our target uses a function inside STORM.DLL to do it's "dirty" job...
Why storm ? Oh, come on ! We all know how Blizzard works, right ?
BTW : in storm.dll is the CD-check security_scheme as well, but we don't wan
that ! We payed for our StarCraft copy, right ? ;)
- make SoftIce load the exports from Storm.dll (use SoftIce's loader. You can
them durind the SoftIce-load <when you start your PC> , or dinamicaly, at r
Use SoftIce's Symbol Loader ! )
- put a bpx on all functions exported by Storm.dll. Then delete the unnecessa
i.e. : If you put a bpx on "func1", and SoftIce pops up when you move your
then delete that bpx on "func1". Because we need the function used t
read the text we type in, not the function that moves your probe !
Get the idea ? :)))
To do this the good way, do the following : put a bpx on the first 1
functions. Play a little. If SI pops, delete the bpx on that functio
that SI popped on. If SI don't break, try to type a fake_password.
If SI pops, than that function could be the right one. If SI didn't
pop when you entered the fake cheat, then delete all bpx on all func
and put some new bpx on the next 10 functions ! Repeat the steps abo
If you finished checking all functions and SI didn't pop when you ty
a fake_cheat in, then YOU DID SOMETHING WRONG OR THAT .DLL ISN'T THE
WE NEED !
OK, OK ! I tell you the function, you lazy jackass (uuuuh, what does "jackass" me
anyway ?) :)
It's "ORD_1F5" function inside storm.dll. So bpx this function like this :
bpx storm!ord_1f5
Now, disable this breakpoint, and in the game type a fake_password ! Enable now t
breakpoint. And you should be in SI again. That's because the game wants to
the typed text even if you haven't pressed [ENTER] to send it to the game.
It's like this : When the "enter_password" part have the FOCUS (i.e. : you w
type in a cheat_code), then BroodWar keeps calling ord_1f5.
Here you must be fast and press [ENTER] for cheat_validation inside the game...
In other words : You must press [ENTER] (to let game read what you've entere
cheat) inside BroodWar between the pops of SI !
Example :
________________________
| |
| Game Screen |
| |
| |
|Message:FAKE CHEAT |
|________________________|
After you wrote "FAKE CHEAT", enable the breakpoint on ord_1f5 ! You'll see that
will pop very often. You must press [ENTER] in the game between SI's pops to
the game that you have finish writing the "cheat_code".
If you did this correctly, SI should pop at the beginning of ord_1f5. Press F12 a
should be here :
Now that we have found where our string is stored, we put a bpm to see where the
is accessing it ... So when you are on "mov [esp+10], eax" type in SI :
bpm ecx
Press F5 to exit SI, and SI pops immediately with this piece of code :
After you can see, that code calculates the length of the entered_text :
repnz scasb will search the entered_text (edi) for the NULL terminati
(esi) while ecx<>0. Ecx=ffffffff the first time, then it will be decr
if NULL char isn't reached. Then ecx is negated and dec-ed to obtain
string_length.
407962 : movsx eax, [ebx+esi] -> place in eax string chars one by one <--
push eax
call 4c5090 -> if that char is uppercased, then make it
add esp, 4
mov [esi], al -> save lowercased char back to string
dec ebp -> ebp=length_string
jnz 407962 -> if that wasn't the last char, jump to nex
So BroodWar searches our entered string to check for uppercased letters. If it fi
then it lowercases them...
Trace down the code... You will see how your entered_string is ENCRYPTED. Then yo
see this :
After you can see, the game compares our entered_string with all cheat_codes one
If there was a match, then activate the respective cheat (i.e. : invulnerab
they didn't match, then compare our_string with the next cheat_code. And so
until there is a match or there's no more cheat_code to be compared with.
So that's how BroodWar works... It takes our string, encrypts it and compares it
encrypted cheat_codes...
Well, we could also decrypt them, but that was too hard for me to reverse, write
explain (and for you to understand). :((((((
FINAL WORDS
~~~~~~~~~~~
Looks like my job here is done... I wish you all the good things !
BTW: If you like a game, then first finish it without any cheats/memory_hacking..
you won't feel it's FEELING ! After you finished it many times and it's play
be boring, then HACK it until your eyes will be as big as a potato ! hehehe.
CHEERS & GREETS (order doesn't matter, chaos is the problem :) hehehe )
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sorin ( Splinter@email.ro ).
2003
eof
Game-Hacking Tutorial
Target : StarCraft-BroodWar
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tools Needed :
~~~~~~~~~~~~~~
- SoftIce
- A memory finder (GameTrainer, TSearch, ArtMoney -> you decide)
- Some programming skills ('cause we're gonna make a "unit detector" trainer)
Level : Intermediate(-Advanced)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
INTRO
~~~~~
I'm preparing for winter holidays, and I haven't so much time to write :(((
But in my very rare internet_surfings I found a tut about Screen Msg in StarCraft
written by Drakken (Cheers!). It's indeed a good one, but that isn't our
subject for today. Our subject is how to make a unit-detector for StarCraft (
the end of his tut, Drakken mentioned about this kind of hack, so that gave
me the idea to write down this one. So, thanks Drakken for the idea :) )...
Eh, looks like we have set our objective, so let's "don't just play... HACK !"
IMPORTANT NOTE : I'm hacking StarCraft v1.04, so if you have a diff. version,
the offsets are different. Don't worry, 'cause the instruction
may be the same. (and forgive my laziness, cause I'm using
v1.04 when there is v1.10 on the web... -> I'm in a hurry ;) )
Let's Begin
~~~~~~~~~~~
Fire up StarCraft, enter a custom game and play with 7 computers. Choose "PROTOSS
as your race, and for the computers, choose "PROTOSS", too.
Before we continue, I must tell u something : let the computers play a little whi
you are doing nothing. That's because we don't want them to have the same num
of units (probes) that we have. Let them play as they like ;).
PS : turn the map cheat on ("black sheep wall").
Now, while you're in game, count the number of your probes (should be 4). Write i
(or keep it in your mind :) ), and then pause StarCraft (F10). Now ALT+TAB an
up your mem. finder (I use TSearch). Select StarCraft as a process, then sear
the number of your probes (type_of_search=DWORD ... Yeah, StarCraft stores th
unit_numbers as a DWORD). Then go back in the game and modify the number of y
probes (you can either build another probe or kill one). Then pause again SC,
go back in mem. finder, and search_next for the new number of probes. Repeat
steps until you'll have only a few addresses (3 or 4 addies). Now modify the
stored AT these addies (one at a time) within the mem. finder and see how aff
Now, replace the value (6) held by first address (aaaaaa) with a new one (7) - in
your mem. finder. Go back in the game and build one probe. Return to the mem.
and look at the value of that addie (aaaaaa). If it's 8 (7+1 - you had 7 prob
you build another one in the game), then it's probably the address we are loo
If the value isn't 8, then delete this address (aaaaaa) and do the same with
one. If this isn't the right one, delete it and skip to the next one... Get t
Following this technique I found my address. It's 504A84. (yours could be differe
What to do next ? Well, the classic method : let's put a breakpoint on this addre
the help of our beloved SoftIce :
bpm 504A84
(be sure you are in StarCraft memory when you put breakpoints. To check this look
right corner in SoftIce. If you are not in SC memory, go back in the game, un
and enter again in SoftIce until you're in SC mem. )
Ok... we have set the trap... This bpm means : I command SoftIce to pop whenever
address (504A84) is being read/written.
Exit SoftIce and go back in the game. Build a probe. When it's ready, SoftIce sho
with the following code:
What is this piece of code doing here ? Mmmm... I have no ideea :((((
Exit SoftIce, an let's build something else in the game... Let's say a pylon (hop
enough money :) ). IF SI pops and your pylon isn't build yet, ignore that pop
That's because the same routine is used for computer players, too. (the compu
build or lost a unit).
When your pylon is build, SI pops where we put our breakpoint :
Exit SoftIce and let the computers play a little... When their units number chang
should pop again:
( The above code is what I saw when the red_colored computer lost a zealot )
( The above code is what I saw when the yellow_colored computer build a citadel_o
Registers are: eax=48; ecx=1; esi=48
( The above code is what I saw when the yellow_colored computer build a carrier )
( The above code is what I saw when the purple_colored computer build a carrier )
After you can see, the game uses the SAME routine to upate the number of units fo
and your computer_opponents. If you looked carefuly the registers, you saw th
I) ECX could hold only 2 values : FFFFFFFF (-1) when a unit was killed
1 when a unit was build
II) ESI & EAX held different numbers when DIFFERENT units had been build or kil
i.e. : when a carrier had been builed, ESI & EAX held 48
when a pylon had been builed, ESI & EAX held 9C
when a probe had been builed, ESI & EAX held 40
III) And another change was at instruction "and eax, FF", which changed eax:
i.e. : when purple_colored computer build something, eax held 7
when yellow_colored computer build something, eax held 3
when I build something, eax held 2
when red_colored computer build something, eax held 5
So, with this information, we determined EXACTLY what that piece of code does:
Registers are: eax=coded_byte_for_units; ecx=1 or -1; esi=eax=coded_byte_for_un
Here's some more information for you guys that didn't understood : when a player
builds/looses a unit (or structure), the game uses his number (player's numbe
4,5,6,7,8) and the coded_byte for that unit to reach the effective number of
unit and perform operations on it (inc if he builds the unit / dec if he loos
unit).
SOME REMARKS : eax that holds player number, can hold this values:
0=player 1
1=player 2
2=player 3
..........
7=player 8
So, when 2 is in eax, we know it's NOT about player 2 BUT player 3 !
I was telling you about some "coded_byte_for_units"... This means that every unit
specific byte (stored in ESI register) !
i.e. :
carrier=48
pylon =9C
probe =40
zealot =41
Look around the address of your probes... Don't you see something suspicious ? Ye
The game stores the number of units_type (probes, marines) for each player li
504A7C : 04 00 00 00 0B 00 00 00 02 00 00 00 1C 00 00 00
504A8C : 10 00 00 00 15 00 00 00 0E 00 00 00 12 00 00 00
504AAC : 01 00 00 00 03 00 00 00 00 00 00 00 01 00 00 00
504ABC : 09 00 00 00 22 00 00 00 07 00 00 00 04 00 00 00
So, the units number is stored as a DWORD, and the unit numbers are stored one af
another for each player (starting from player 1 and ending with player 8)
NOTE : you could figure this out with some math, too ( having the players number
unit_coded_byte... you know, with the above piece of asm code... ;) )
Now, like a hard-working-lamer that I am, I'll give you the list of all units & s
for TERRANS, ZERGS and PROTOSS with their respective coded_byte... ( I deserv
beer ! :)))) )
TERRAN
coded_byte | unit
~~~~~~~~~~~~~~~~~~
0 = Marine
1 = Ghost
2 = Vulture
3 = Goliath
5 = Siege Tank (Tank mode)
7 = SCV
8 = Vraith
9 = Science Vessel
B = Dropship
C = Battlecruiser
D = Spider Mine
E = Nuclear Lounch
1E = Siege Tank (Siege Mode)
20 = Firebat
21 = Vision (casted from Scanner Sweep)
22 = Medic
3A = Valkyrie
6A = Command Center
6B = Comsat Station
6C = Nuclear Silo
6D = Suply Depot
6E = Rafinery
6F = Barracks
70 = Academy
71 = Factory
72 = Starport
73 = Control Tower
74 = Science Facility
75 = Covert Ops
76 = Physics Lab
78 = Machine Shop
7A = Engineering Bay
7C = Turret
7D = Bunker
ZERG
coded_byte | unit
~~~~~~~~~~~~~~~~~~
23 = Larva
25 = Zergling
26 = Hidralisk
27 = Ultralisk
28 = Broodling
29 = Drone
2A = Overlord
2B = Mutalisk
2C = Guardian
2D = Queen
2E = Defiler
2F = Scourge
32 = Infested Terran
3E = Devourer
67 = Lurker
82 = Infested Command Center
83 = Hatchery
84 = Lair
85 = Hive
86 = Nydus Canal
87 = Hydralisk Den
88 = Defiler Mound
89 = Greater Spire
8A = Queen's Nest
8B = Evolution Chamber
8C = Ultralisk Cavern
8D = Spire
8E = Spawning Pool
8F = Creep Colony
90 = Spore Colony
92 = Sunken Colony
95 = Extractor
PROTOSS
coded_byte | unit
~~~~~~~~~~~~~~~~~~
3C = Corsair
3D = Dark Templar
3F = Dark Archon
40 = Probe
41 = Zealot
42 = Dragoon
43 = High Templar
44 = Archon
45 = Shuttle
46 = Scout
47 = Arbiter
48 = Carrier
49 = Interceptor
53 = Reaver
54 = Observer
55 = Scarab
9A = Nexus
9B = Robotics Facility
9C = Pylon
9D = Assimilator
9F = Observatory
A0 = Gateway
A2 = Photon Cannon
A3 = Citadel of Adun
A4 = Cybernetics Core
A5 = Templar Archives
A6 = Forge
A7 = Stargate
A9 = Fleet Beacon
AA = Arbiter Tribunal
AB = Robotics Support Bay
AC = Shield Battery
NEUTRAL
coded_byte | unit
~~~~~~~~~~~~~~~~~~
5F = Ragnasaur
B2 = Mineral Field
BC = Unoccupied Vespene Geyser
( the player number for neutral is B )
Yeah, actualy there are more neutral units, but this list is by far ENOUGH !
How did I get this list ? Simple : I managed to play alone a game (with every rac
time), then I set that bpx on "mov eax, [esp+14]" instruction, then I build e
structure & unit that race have, looking at ESI register... And to tell you t
it was very UNcool, especialy when there are 7-8 electricity failures in your
neighbordhood... :(((((((((
OK, OK..... Now let's think a bit on what can we do with these informations...
DO NOT DO THIS :
The first thing I did was the code-injection... I jump from the "mov eax, [esp+14
instruction to a code cave. Then, in that code-cave I wrote a unit filter...
You know, player checks, unit checks, and many-many more features... But sudd
I realized that if the trainer was started after the players build-up their c
(for example), the trainer wasn't able to read the carriers number ( because
that the trainer wrote in that code-cave is called ONLY if a carrier is build
- we jump there ONLY from that routine that starts with "mov eax, [esp+14]").
DO THIS !!!! :
Then I came up with the correct idea : Why to inject code when we can read the un
numbers with some simple math calculations... More over, StarCraft don't use
that storing...
Let's see how the game reaches the address of probes, for example :
lea edx, [esi*2+esi] (esi is the coded byte for probes, in this case esi=40)
lea ebp, [edx*4+eax] (edx from above; eax is the player's number i.e.: 0,1,.
mov edx, [ebp*4+503E7C] (ebp from above; 503E7C is a static address;
here edx gets the effective number of probes for pl
Now for that you can either choose the player you want to spy on, or make a cycle
goes through all 8 players. You decide ! I'll show you both ways :)
mov player_iteration, 0
.while player_iteration <= 7
mov eax, player_iteration
mov esi, 48h
lea edx, [esi*2+esi]
lea ebp, [edx*4+eax]
lea edx, [ebp*4+503e7ch]
Invoke ReadProcessMemory, phandle, edx, addr carrier_numba, 4, NULL
mov eax, numba
mov ecx, player_iteration
mov unit_buffer[ecx], eax
inc player_iteration
.endw
FINAL WORDS
~~~~~~~~~~~
Ough! Another *great* :) tut finished... And it was a lot of typing... But I thin
worth it !
And I think this kind of hack should work without any problem in Multiplayer game
:)))))))
Sorin ( Splinter@email.ro ).
2003
eof
Bie comment:
This info is taken from http://www.gamehacking.com forum. The info didn't mention the patch is for which version of Starcraft. Omega have
explaining the format of the info in 3 categories, Offset, Original and Patch.
Informer: JohnTheBaptist
Email: Unknown
Homepage: Unknown
none
The Public Offsets. Originally found by the Korean guy. These will let you maphack in a multiplayer game, yeah. You don't "hack" them though,
Bie comment:
Below is some more info Eedok. Eedok can be contact thru http://www.gamehacking.com forum.
we can try to translate those offsets up there to asm and see what they get changed to, maybe that'll help us out, cept I can't find a program
offset 0x46C517
je 0x46C521
offset 0x46C531
offset 0x4105CF
test al,cl
offset 0x4C4589
je 0x4C467F
offset 0x4C4FA0
je 0x4C5093
offset 0x46E6F7
je 0x46E72B
offset 0x46E702
jne 0x46E726
offset 0x46D2FE
je 0x46D311
offset 0x46D300
offset 0x46D308
offset 0x46D30F
jmp 0x46D317
offset 0x46E47E
je 0x46E4B2
offset 0x46E489
jne 0x46E4AD
offset 0x46E81E
je 0x46E852
offset 0x46E829
jne 0x46E84D
try to figure out what to change to make them work..(hint:use the TMK button and compare with public offsets)
Sorin Question:
i tried to do changed/not changed but i have found 1 addr that if i modify, nothing will happen
Eedok Answer:
try searching 2 byte instead of 4, or maybe it's 1 byte I can't remember but I think it's 2 bytes and the on value is 0F and the off value is
1F(convert these out of hex to get them to work) plus changing these only changes 1 little square.. maybe the one you're modifying is off the
map..
Bie comment:
JohnTheBaptist also explain how to find the hack, but did not say if this method is for offline or online games but Eedok said it would. I let the
instruction in it original state as JohnTheBaptist post it in the gamehacking.com forum. User who read the instruction below must have already
know to use memory searcher example Tsearch or Artmoney. 'Black Sheep Wall' mean to be type in Starcraft chat screen while playing the
game.
This info is taken from http://www.angelfire.com/games5/storagebin/ . The info is for Starcraft v1.10
Email: Unknown
Homepage: Unknown
none
This page is dedicated to the hacks that are not possible for the current version of Starcraft, 1.10. I will attempt to explain to you why these
hacks are impossible, and hopefully teach you a bit about how Starcraft works.
The Basics
The way Starcraft's online mode works is like this. When you start a new game of Starcraft, the map file determines how many
minerals/gas/units you have. It initializes these values for each player. After this point, whenever a player does something (tells a unit to move,
attack, makes a new unit) only the commands are sent to each computer. This way every computer knows exactly what's happening on each
other computer. There are periodic checks for changes (I believe it's every 174 milliseconds, but I could be wrong) to check to see if something
has changed unexpectedly. If it has, the computer(s) that detected the anomoly breaks their connection(s) with you, ending your game of
Starcraft. This is how the disconnect hack works, and is often referred to as a desync.
Resource Hacks
Now let's examine all the possible methods of making a mineral hack, and I'll explain why none of them will work. As stated earlier, from the
start of the game, each computer knows how many minerals each other computer has.
Trying to change the value that you start with will cause an immediate desync because the other computers still think you have a different
amount.
If you attempt to change how much units/buildings cost, you will get desynced when you build something. Your computer sends the command
that you are building a unit/structure at a certain location, then it subtracts the amount of mineras/gas it cost from your total. When the other
computers recieve the command, they in turn subtract the cost of the unit/structure from the running total kept on their computer. Since your
change to the cost of the unit/structure did not affect their computer in any way, the values go out of sync and you get dropped.
Changing the code that subtracts the amount from your resources to add it instead (which is quite possible to do) will cause a desync when you
spend any resources. Once again, the other computers register a normal change and your computer has an abnormal change.
Changing to code that determines if you have enough resources to spend to always think you do will cause a desync when you spend your
resources past 0. When you attempt to spend your resources past 0, two things happen. The value rolls back all the way to 4,294,967,296 and
starts counting down. The other computers then detect that you didn't have enough resources to perform the selected action and break the
Attempting to change the number of minerals an SCV/Drone/Probe is carrying also desyncs because these values are monitored as well.
There have been other proposed mineral hack ideas, but I can't think of them off the top of my head. I'll add to the list and explain why they
don't work over time. If you wish to argue this with me, feel free to contact me at the forums at www.gamethreat.com, just prepare to be
Energy Hack
This hack is impossible for the same reasons a mineral hack is impossible. Each other computer knows how much energy each of your units has,
changing that value will cause you to desync. I have seen people ask if you could make it regenerate faster, the answer is no. The other
computers have their own regeneration speeds, and if yours regenerates faster, it will cause the values to be unmatched and you will desync.
Upgrade Hack
A hack that allowed you to upgrade farther than level three was possible in previous versions of Starcraft and Warcraft II, however this is no
longer possible. Now, each computer monitors what level your upgrades are at. If at any time the value is greater than three, you get
desynced.
Fastbuild Hack
This hack is rarely asked about, but I thought I'd add it anyway. When a map file is read from to initialize a game, the build speeds are also
initialized, leaving the possibility to change those build speeds and thus gain an advantage over your opponents. This is not possible however.
Since the other computers know what speed things should be built at, attempting to build something at a greater rate will cause a desync
because your computer only sent the command to build the structure with X unit at coordinates x,y. When production does not match up (yes,
the other computers keep track of production percentages too), you get desynced. Simply changing your production speed will not cause a
There is no way in which to see the messages sent to other players. These packets are sent directly to the other computers, and your computer
At the moment those are the only hacks I can think of that are asked about fequently. As more hacks are proposed, I will continue to add them
to this page.
See Also:
Game Training Techniques - Tutorial 5
The Sims: Dead Listing
Step 1:
Load sims.exe in WinDasm and wait for it to disassemble the file. When it
is open go to the STRING REFERENCES, which is the second to last
button on the tool bar, and start browsing.
SIDE NOTE: As I've talked about before any address that has brackets
around it is pointing to the value inside of that memory address. The read
out is usually something like this:
mov ecx, dword ptr [0060747c].
The previous instruction moves the value inside 0060747c and puts it in
ecx.
One of the first string references I found by scrolling through the list was:
hunger decrement ratio. Well since I can read, this looks like this reference
is talking about a SET value at which your hunger bar decreases. Double
click on "hunger decrement ratio" in the String Reference Window, it will
jump to:
If you look in the value in those addresses you will see that they are some
crazy high number, that is the decrement ratio at which you starve. If you
change the first value to zero then you will never starve. If you change that
value to a higher number you will starve faster.
Sometimes you have to test which value does what, its probably best to set
both of them to zero. In the case with other values (contained in the file
below) its best to test them out yourself.
The only other one I tested was 'money for new family', with this you have
to set the second value from 20,000 (default) to whatever you want your $
to be. The first memory address is garbage, and THEN (after you set the
new value) you have to create a new family.
All the addresses and names of stats for version 1.0 are in this FILE and the
addresses and stats for version 1.1 are in this FILE. Change them at your
own risk, I included everything I saw, but only certain things are worth
changing like the hunger decrement ratio.
Conclusion:
I assume the values were read into memory from a file when the game
started up (all that garbage scrolling at the botton of the screen on start up),
and stored in memory and never again verified with the original files. Its
always a good idea to check out the game with WinDasm first.
^chaos^
Tools:
Memory Searcher I suggest T-search but any will do.
Softice – A definite needed tool for any true game hacker.
The Sims v1.1 for the practical
Now just to make this a little bit easier before the practical. I’ll explain exactly how code injection
works. First you must find a code cave. A place in the game where we can write our own code we
then jump from the game code which is affecting say health to our codecave where we have written
our own code we then jump from here back to the game code. This is just totally made up code from
softice but should give you a slight idea of what we want to do.
-Game Code-
0010:558975 5F2014 Sub EAX,30 We Jump out here to our code
0011:558978 5078 Mov EAX,[ESI+30] We nop this address
0012:558980 50 Add EBX,EAX We jump back here
-Code Cave-
0055 Add EAX,30 This is just made up code this is our code cave.
0056 Mov EAX,[ESI+30]
0078 Jmp 558980 We Then jump back to our game code.
Also there is one thing you will need to know a little bit about asm to fully understand this tutorial. So
don’t mail me if your having problems understanding this tutorial if you don’t know shit about asm.
Now for this example I will be using The Sims. We are going to hack the money value which uses
DMA, address changes every level or any time we restart the game Also changing the static address
won’t do anything also nopping the address won’t do shit. So we are going to use code injection to
hack this game.
So write this address down on a piece of paper which we will use later in the tutorial.
Now we must find our money address. So open your memory searcher and search for the amount of
money you have. Go back to the game decrease your money go back to your memory searcher and
search for the decreased value. After doing this a couple of times you should get it. I got 180BECA
now changing this or nopping it won’t do anything to the actual amount of money on your screen
because all this address does is read the amount of money you’ve got.
Now we must place a breakpoint on this is SI so back to the game and press ctrl+d then in SI type
BPMD 180BECA W
After doing this go to the game and loose a bit of money and SI should pop up with something that
looks like this:-
447F80 This is the pointer we want to edit ECX+50 being our amount of money which is placed into
eax and then further down in the code EAX is placed into our on screen display. So this is where we
want to make our jump. So in SI type
a 447f80 Enter
jmp 10ADF Enter
nop Enter
and then enter again to drop out of assembly mode. Now it should look like this
Now I haven’t included the op codes because their not needed just yet. Now by editing address
447F80 to jump to our code cave after doing this it fucks up the game code but if we right a single nop
to the address underneath it will even it out.
And then type the following and pressing enter after each line
Then hit enter twice to drop out of assembly mode. Now to explain a bit more on what we have just
done.
Now exit SI and buy or sell something and bingo!!! We’ve done it our money is now 9999999
simoleons.
Now to put this into a trainer you just poke the address where you made your gateway with the op
codes and then the first address of your code cave with all their op codes.
To display the op codes type code on. After doing this you should have some extra numbers in the
code window these are called op codes.
Example
Gateway
448789 1B 5F 8E Jmp to code cave
CODE CAVE
10ABF 1A F1 45 88
10AC3 58 99 88 77
10AC7 45 9E 55 88 JUMP BACK
Poke 448789 1B 5F 8E
Poke 10ABF 1A F1 45 88 58 99 88 77 45 9E 55 88
Shinero_uk@yahoo.co.uk
Greetz Fly out to Sheep Tsongkie, Vulmer, Futal, Micral, Raven, Digital Vigilante, CES Devious and
all extalia members.
Well Enjoy
Tutorial by Shinero
HACKING THE SIMS : HOT DATE TUTORIAL
Hi there ppl it's me i'm back again and this time with an exclusive tutorial
on hacking The Sims Hot Date ! Some of you might have noticed that there
aren't many hacks for the sims out there apart from the money and
personalities hacks but it's not that hard at all. So to all of you who is
wondering how i made my ultimate sims trainer, here's the essay !
Ok i assume that you don't know any assembly so i will explain it as simple
as i could. All addies that is put inside a bracket i.e [00655000] is a
memory address. The difference between [00655000] and 00655000 can
be shown in this example :
Look at the highlighted line. Basically it's an interesting addie and you
should check it out.
Other stuff
This is just an example of how values in the sims can be hacked. You
should look around a bit, there are many interesting string references that
you can play with. Some examples : "energy span", "wake hours", "comfort
decrement active", etc. Check them out yourself.
contact : micral@phreaker.net
Tutorial On Getting ALL WEAPONS in Tomb Raider II
( By Shaikh Adeel )
Web : http://www.vngamecenter.com/
About :
Hi All …….. I was playing Tomb Raider 2 some time ago. After playing a little, I
So that is why I decided to make my own that really worked. And I did….. now Im
This game uses the most different and interesting process of finding all guns …….
U can get that by reading tutorials on different Memory Finders …. Which u can fi
Audience : Game hackers who have been hacking for some time ..... This tutorial
What U Need :
3) Tomb Raider II J
Back Ground :
Well we will use the cheat codes for getting the weapon
take one step forward (hold down "shift" while pressing up arrow), then take one
in code, Instead, we shall search for change in offsets for guns. Coz this game
Lets Get Those Damn Guns :
1. Open up T-Search.
2. Start Tomb Raider II. Start a new game. At this time Lara Croft has the simp
4. Now from here, put in the Cheat Code so that ur Lara has all weapons.
5. Save the game here, but under the previous saved game. <--- This is Saved Ga
9. Press the Big magnifying glass ( Start Search ). It searches for some time an
10. Now go into TR2. Load the Saved Game # 2 in which Lara has all the weapons.
12. This time press the smaller Magnifying Glass. Select Type = 2 Bytes and selec
13. Go back into TR2. Load the Saved Game # 1 which has lesser weapons.
15. Repeat steps no. 9-12 .... But press the small magnifying glass only ...... U
Now the addresses dont lessen .... U keep on doing steps 9-12 but u keep getting
16. Trial And Error Method : Load the Save Game # 2 ( wid all weapons ). Min the
U might be lucky if some of the weapons have changed ..... like .... in place of
17. Check the addresses u had frozen for the address that changed the weapon in t
18. Repeat step # 17 until u get 5 values which change the weapons in the invento
19. But the problem is that the weapons only change in place of some other weapon
Theory :
Now time for some theory ...... I mean ... Before getting u to get All Weapons I
That means there r only 6 Slots for items. When Cheat is On, there r 11 items, so
20. Now if u look at the address in the Left hand portion of Tsearch ... where al
21. Unfreeze all the values, if u have frozen any. Load game # 2. U have all weap
23. U have found 6 addresses up till now. Freeze them at their current values now
24. Go in the game and load Game # 1. Check the inventory. U will have all weapon
EXPLANATION :
In case u dont know what we have dun uptil now ...... Here is the Explanation. Wh
there r 11 slots ...... so the thing at number 6 lot night go to slot # 11 when t
because the weapons have increased but there r not enough slots 2 put them into.
25. Check TSearch ....... Check the values at which u get all guns.
26. To check the addies. In TMK poke these addresses wid their respective values
the Slots number is changed to 11 and the respective slot of the items is also ch
NOTE :
U r welcome to ask questions and give critic's view on this tutorial so that I ca
|
· ·-------=+=---· ·
ÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ÜÜÜÜÜÜÜ|
Û²²²²²²²²²²²Û±± Û²²²²²²²²²²²Û±± Û²²²²²²²²²²²²²²Û±± ÛÛÛÛÛÛÛ±±
Û²²²ÛÛÛÛÛ²²²Û±±°° Û²²ÛÛÛÛÛÛÛ²²Û±±°° ßßßßßßßÛ²²²²²²Û±±°° ±±±±±±±±±°°
Û²²²²²²²²²²²Û±±°° Û²²²²²²²²²²²Û±±°° Û²²²²²²Û±±°° °°°°°°°°°°°
ÛßßßßßßßßßßßßÛ±±°° ÛßßßßßßßÛßßßß±±°° Û²²²²²²Û±±°° ÜÜÜÜÜÜÜ
Û²²²²²²²²²²²²Û±±°° Û²²²²²²²²Û±±°° Û²²²²²²Û±±°° Û²²²²²Û±±
Û²²²ÛÛÛÛÛÛ²²²Û±±°° Û²²²Û²²²²²Û±±°° Û²²²²²²Û±±°° Û²²²²²Û±±°°
Û²²²ßßßßßß²²²Û±±°° Û²²²ÛÛÛ²²²²Û±±°° Û²²²²²²ßßßßßßÛ±± Û²²²²²Û±±°°
Û²²²²²²²²²²²²Û±±°° Û²²²ÛÛÛÛ²²²²Û±±°° Û²²²²²²²²²²²²²Û±±°° Û²²²²²Û±±°°
ßßßßßßßßßßßßßß±±°° ßßßßßßßßßßßßß±±°° ßßßßßßßßßßßßßßßß±±°° ßßßßßßß±±°°
±±±±±±±±±±±±±±±±°° ±±±±±±±±±±±±±±±°° ±±±±±±±±±±±±±±±±±±°° ±±±±±±±±±°°
°°°°°°°°°°°°°°°°°° °°°°°°°°°°°°°°°°° °°°°°°°°°°°°°°°°°°°° °°°°°°°°°°°
Well after a week or two or maybe more of doing nothing just standing in front of
looking at the screen and drinking i have decided to write another tutorial on co
I hope you liked my first one :). But in that i have told you how to do the stand
injection method which is boring. In this tutorial i'm going to show you how to i
functions. Well as my first tutorial of this kind i'm going to show you how to in
Message Box. In my next tutorials i'll show you some more stuff (if i have time t
tutorials because the school year has just began. So lets start our little tutori
Tsongkie's Code Cave Tool for searching a code cave and we will inject our Messag
mean we will inject the messagebox into Tsongkie's Code Cave Tool. Wait u'll see
TOOLS NEEDED
************
LESSON START
************
The MessageBox function creates, displays, and operates a message box. The messag
an application-defined message and title, plus any combination of predefined icon
buttons.
int MessageBox(
hWnd
Identifies the owner window of the message box to be created. If this parameter i
the message box has no owner window.
lpText
lpCaption
Points to a null-terminated string used for the dialog box title. If this paramet
the default title Error is used.
uType
*NOTE: Unlike other programming languages in ASM parameters are pushed into the s
In ASM you have to push the caption first, then the main text, followed by the wi
and then the call the MessageBoxA.
Ok now open W32Dsm89 and disassemble Tsongkie's Code Cave Tool. After the Disasse
click on the StrnRef button on the toolbar. Now double click on the string in the
says "Tsongkie's Code Cave Tool v1.0". I have this code:
* Possible StringData Ref from Data Obj ->"About Tsongkie's Code Cave Tool"
|
:00401089 6849304000 push 00403049 <- pushes the location of the c
* Possible StringData Ref from Data Obj ->"Tsongkie's Code Cave Tool v1.0"
|
:0040108E 6869604000 push 00403069 <- pushes the location of the m
:00401093 FF3558324000 push dword ptr [00403258] <- push the WndHandl
offset 00401089
//jmp to our code cave
jmp 0040DC17
offset 0040DC17
//Recreate all the stuff
//push the caption of the msgbox
push 00403049
//push the main text of the msgbox
push 00403069
//push the window handle
push dword ptr [00403258]
//call the MessageBoxA API
call 004011FC
//jmp back after the call or the program will crash
jmp 0040109E
Now if you run Tsongkie's Code Cave Tool and enable the script and then press the
it will display you the standard Message "Tsongkie's Code Cave Tool ....". It mea
injection is succesfull and everything is fine.
Now the other part - our strings (the caption, main text). I have marked the new
|NEW| .
//|NEW| Our Text //I couldn't think of anything good for the text so let it be "
offset 0040DCBB
asc "Hello !"
hex 00
offset 00401089
//jmp to our code cave
jmp 0040DC17
offset 0040DC17
//Recreate all the stuff
//|NEW| Change the original caption "About Tsongkie's Code .." to our "brzi's CI
push 0040DCA7
//|NEW| Chande the original text "Tsongkie's Code Cave..." to our simple "Hello !
push 0040DCBB
Well that's it for now, i hope you understood how this thing works so you may try
something by your self. Until next time CYA.
GREETS:
*******
Stoner,Tsongkie,Omega,Micral,EEDOK,InvadeR,Bie,VBTrainer and everybody else that
@@@@@@@ @@@@@@@ @@@@@@@@ @@@@@
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@
@@! @@@ @@! @@@ @@@ @@!!@
!@! @!@ !@! @!@ @!@ !@ @!
@!@!!@! @!@!!@! !!@! @@@!!
!!@!@!!! !!@!@! !!@ !!!!!
!!: !!! !!: :!! !!!::!!! !!::!
:!: !:! :!: !:! !:!:!::! :!:!!
:!!:::!! :: ::: ::!: :::!
::!!:!! : : : : ::
:::
:
TABLE OF CONTENTS
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
1. Introduction
2. Tools Needed
3. API Explanation
4. The Injection
5. Final Words
6. Greets
2.TOOLS NEEDED
**************
3. API EXPLANATION
******************
As i sad well use ShellExecute Api for this tutorial. The explanation is a
little long but it's very good. Here it is ..
The ShellExecute function opens or prints a specified file. The file can be
an executable file or a document file. See
HINSTANCE ShellExecute(
hwnd
Specifies a parent window. This window receives any message boxes that an
application produces. For example, an application may report an error by
producing a message box.
lpOperation
String Meaning
"open" The function opens the file specified by lpFile. The file can be
an executable file or a document file.
"print" The function prints the file specified by lpFile. The file
should be a document file. If the file is an executable file, the function
opens the file, as if "open" had been specified.
The lpOperation parameter can be NULL. In that case, the function opens the
file specified by lpFile.
lpFile
lpParameters
lpDirectory
nShowCmd
If lpFile specifies an executable file, nShowCmd specifies how the
application is to be shown when it is opened. This parameter can be one of
the following values:
Value Meaning
Return Value
If the function succeeds, the return value is the instance handle of the
application that was run, or the handle of a dynamic data exchange (DDE)
server application.
If the function fails, the return value is an error value that is less than
or equal to 32. The following table lists these error values:
Value Meaning
0 The operating system is out of memory or resources.
ERROR_FILE_NOT_FOUND The specified file was not found.
ERROR_PATH_NOT_FOUND The specified path was not found.
ERROR_BAD_FORMAT The .EXE file is invalid (non-Win32 .EXE or error in .EXE
image).
SE_ERR_ACCESSDENIED Windows 95 only: The operating system denied access
to the specified file.
SE_ERR_ASSOCINCOMPLETE The filename association is incomplete or invalid.
SE_ERR_DDEBUSY The DDE transaction could not be completed because other
DDE transactions were being processed.
SE_ERR_DDEFAIL The DDE transaction failed.
SE_ERR_DDETIMEOUT The DDE transaction could not be completed because the
request timed out.
SE_ERR_DLLNOTFOUND Windows 95 only: The specified dynamic-link library
was not found.
SE_ERR_FNF Windows 95 only: The specified file was not found.
SE_ERR_NOASSOC There is no application associated with the given filename
extension.
SE_ERR_OOM Windows 95 only: There was not enough memory to complete the
operation.
SE_ERR_PNF Windows 95 only: The specified path was not found.
SE_ERR_SHARE A sharing violation occurred.
4. THE INJECTION
****************
First let's explore Tsongkie's Code Cave Tool a little. If you run it you
will see that it has:
1. A logo -> This does nothing
2. A listbox -> Display Code Cave's found in the specified process
3. An EditBox -> You type the Window Name here
4. And three buttons:
* Search -> Searches and opens a process with the Wnd Name given
* Help -> Runs the Readme.txt file <- this btn is useful for this tut
* About -> Displays information about who coded the program
So if you press the help button it will open the Readme.txt which can be
found in the program directory or if the file does not exist it will open
your Windows Readme File. Now we will inject the ShellExecute function so
it will open another file or executable. Let's make a little MSGBOX program
that we will use for opening. The first example is in mASM and the second in
Visual Basic. You can use any program you like, this is just an example.
.386
.model flat, stdcall
option casemap: none
include \masm32\windows.inc
include \masm32\user32.inc
include \masm32\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
MsgText db "Brzi's Code Injection Tut #3",0
MsgCap db "Info",0
.code
start:
invoke MessageBox,NULL,addr MsgText,addr MsgCap,MB_OK
invoke ExitProcess,NULL
end start
Sub Main()
MsgBox "Brzi's Code Injection Tut #3", "Info", vbOkOnly
End Sub
Compile it.
Ok now let's disassemble the file with W32Dsm89. Click on the ImpFn button
on the toolbar and then double click on the ShellExecuteA function.
I have this code:
:0040106A 6A03 push 00000003 <- whether file is show when open
:0040106C 6A00 push 00000000 <- pointer to string that specifi
:0040106E 6A00 push 00000000 <- pointer to string that specifi
So now we know everything that we need so run TSearch and open EasyWrite.
I found some code caves so you don't have to bother to search for them.
//call ShellExecute
Call 0040120E
//jump back
jmp 0040107E
Our Code:
push 00000003
push 00000000
push 00000000
push 0040125C
push 0040126C
push 00000000
Call 0040120E
jmp 0040107E
jmp 0040127C
push .....
..........
Well add a hotkey to the script and try it. It opened our program!
Interesting stuff eh.. Or you can replace the MsgBox.exe with TCCT and that
way when you press the help button it will open Tcct.exe.
Until next time cya... Take care :)
5.FINAL WORDS
*************
Always when you do code injection, always poke your code first then the main
code because the game/program will crash in some cases and it is save and
better. And i need a favor - will somebody make me a good ascii logo cuz
mine sucks - please!. For any suggestions/questions, crittics are welcome
mail me at brzi@devious.tsongkie.com
And one other thing.. I think that these tutorials can help you how to learn
to code in ASM ->Tasm. This is how the code will look in TASM way. Just the
function. I'm not saying that i know how to code in TASM, but i know how to
do some stuff so..
push 3
push 0
push 0
push 0040125C
push 0040126C
push 0
Call ShellExecute
->brzi
6.GREETS
********
Well here is another tutorial. This time about GameHack 2.0. It is a very useful game hacking tool with the
ADVANCED search option which is used for searching unknown values. Like energy bars. We will hack the health
in Beans Trainer Tester, Level-1. And We shall also hack the Money and Lives.
Essay
This is the first level of the tester, and thus it is the easiest. This is a very simple
and yet common type of "protection". The addresses are in static memory, means that they
do not change from time to time. The address will be the same address each time you load
the game. Static Memory is pretty good for us game hackers, because a trainer can easily
be coded. If it was a dynamic memory type of trainer, a process patcher or a loader would
have been required in order to complete the task.
You should have gotten 2 addresses. If you got more than 2 then Un-pause the tester
and wait for the money to be changed. Then click on the "Next Search" button, and do
the same, only with the new value.
2. If you did everything right, you should have 2 addresses left: 40C1D4 and 40C1D8.
One of the two addresses is a false address, that is in charge of the screen display
of the value. Move the 2 addresses to the lower list, and Poke one of them. When I
say POKE, I mean - change the value of the address. How to Poke? Simply click on the
address and change its value to something bigger than 1,000,000. After you have poked
the first address (40C1D4), un-pause the tester and see if the value in the money box
is changed. Did it? Nope.
3. Do the same with the second address. Did the value change? It did. Good, we found
the correct address for the money. In order to "Freeze" the address (meaning that the
value will not change), only click on the little box besides the address' name. if a
green smiley appeard than you did it right.
1. Look at the Health bar. Whenever it reaches the end, the life amount decrease.
In order to successfully hack the Lives, we first have to hack the Health Bar. Pause
the Tester and go to GameHack. In Search options, search with the "Advanced" option.
Unpause the tester, and let the Health decrease alittle bit. After that, click on the
search again button and with these options:
Search: Decrease
Type: 2 Bytes
Do the same until you got these addresses left: 0040C1D0 and 0052001C. Again, one of
them is "fake". Do the same as step 2 in above to know which one isn't fake.
2. Set the value of the health bar to 0 and freeze it. Now the Lives will decrease
really fast. If you want, you can restart this level in order to have 5 lives. Pause
the tester. Let's say that you have 4 lives now, do this search:
Un-pause the tester, and let the lives go down by one, and the pause it again. Do the
same search again, until you have only one address left: 0040C1D2. Poke it to a value
higher than 10, and freeze it, and then un-freeze the Health.
3. Click on "Test", and if you did everything correct, you will get a "Congratulations"
message.
Final Words
The aim of this short tutorial was to introduce the newbies of game hacking into this
world, by the use of a very common training example. The main idea behind this was the
"offset search" method. You search alot of times, and each time the number of correct
addresses decreases, until you find the correct one. As for the number of bytes. If you
are wondering how did I know the correct amount of bytes to seek, well, all I can tell
you is that I did it out of Trial N' Error, and tried all the possibilites until I
had reached to the correct one - a pretty messy job.
Orr
OrrAghion@hotmail.com
=======
Level 2
=======
Programs needed:
Game Trainer
Trainer Goals:
=====
Money
=====
You need to decide on what type you're going to search. Let's say your current mo
So the money is $100000 and the game is paused. So start a search and type 10000
What's that? Found 0? Too bad, it happens sometimes with games. So what next? Wel
=====
Lives
=====
Let's say that you have 5 lives. It's a small number so you use Byte. So change t
Hmm, 0 addresses found. Sometimes, values that are shown are actually different,
======
Health
======
The health is an unknown value so you'll be using the advanced search method agai
I got 2 codes so you might as well add both of them, but don't freeze them yet be
Click on Test and you should've completed level 2 successfully. If any of the cod
Written by ROWE.
The target: Beans' Trainer Tester 1.1
Difficulty Level: 3
Programs needed:
Game Trainer
Trainer Goals:
Freeze Timer
Freeze Money at $1234.56
Freeze Lives at 10
Freeze health over 90%
=====
Timer
=====
I'm persuming that you've read the other tutorials first. So to save you time, yo
=====
Money
=====
Restart the game but pause it straight away. Let's say your money is $5000.00. Be
=====
Lives
=====
Again, the bytes have been reversed. So start the game. You start with 5 lives, s
======
Health
======
You have to be slightly careful with this because the health is sectioned into 3
It's not over yet though. There is another address to find, the one which control
Written by ROWE
The target: Beans' Trainer Tester 1.1
Difficulty Level: 4
Tools needed
------------
Softice
INFO
After been asked to do the tut for lvl4 also here i am again ;)
I`ll try and make it as easy to follow as possible but this lvl
is a bit trickier cause it uses floating pointers and registers
to store the values so we`ll c how it ends up.
The Crack/Patch
---------------
First of all you have to have winice loaded.
Then start tester.exe and go to lvl4 and press pause.
Now you can just try to search for all possible combinations for the money
byte,word,dword,float double,asci,asciz. But to save you some time :).. don`t bot
doing that cause we can find all the rutines by just finding the address for the
This might sounds a bit strange to some but what i`m going to do in this tutorial
that i`ll search for the timer address and then break on the timer increase(float
Then trace through a bit of code and then put some new code into the program. The
why we`re going to trace from the timeraddy is that it`ll save us...well you alot
and when you have read this tutorial then you might come up with some other idéa
patch/crack lvl4.
Well enough talking now and let`s get on with the real deal ;)
Let the timer go up to 1, search for 1(float, i used gametrainer), then un-pause
for the next value and continue until you only got 1 addy (it should be 0040D08C)
Now put a breakpoint on memory access on that address (bpm 0040D08C w).
Un-pause and bang..softice comes up then you should land here.
The first thing we`re going to do is to make the money stay at 1234.
So if we trace until we get to this code snippet
These to first rows compares your present health with the health that the present
has to reach before gaining one life. erhmm that sounded a bit strange so i`ll tr
explain it a bit more.
Lets say you have A=10 and B=100 and when A==B you gain a life.
So the FCOMP basically checks if A==B and if so you gain one life and then
the health is resetted and it starts over again. And if A==B a flag is set (AH to
Ok so now we know where the lifes increase so to make this crack/patch as easy as
possible i wont insert any new code. Just alter the excisting a tiny bit ;).
Now one problem with this is that you will have to wait for the life to go one ro
that it reaches the xor code and we get our Life=1.
Feel free to send me a mail if you have comments or questions about the tutorial
just send it to xdariuzx@hotmail.com
This tutorial is dedicated to all newbies and/or anyone who just thought that thi
tutorial would help them out...
Well bye for know..maybe i`ll come back with some more tuts...who knows ;) !!!
-----------
© 2001 DudE
-----------
Advanced Game Training Techniques
The Trainer Tester 1.0 coded by Beans
LEVEL 5
NOTE: If you have trouble getting Softice to pop when trying to BPM
on the values in Tester.exe do the following:
1.) First make sure that you remove the semicolons (;) from winice.dat in
your SI install folder under the exports section, so it looks like this:
EXP=c:\windows\system\kernel32.dll
EXP=c:\windows\system\user32.dll
EXP=c:\windows\system\gdi32.dll
2.) You need to only do this once if you haven't done this before. Now
reboot. This now will let you BPX (break point on execution) on all
Windows API.
3.) Go into SI with control+d and type: BPX hmemcpy, now in Tester.exe
select a level and hit the TEST button. SI to pop (You will notice in the
right hand bottom corner it will tell you that it is in tester.exe). From this
point on you can set any BPM that you have, and the exit SI.
Difficulty Level 5:
THE TIMER:
The timer value is stored in a 2 byte word, and it increases. It is stored in
memory the same way you see it, so if you see 13, search for 13. Pause
Trainer Tester. Once you have the right address, pop into SI and type BPX
hmemcpy, now exit SI. Unpause the Trainer Tester and let the timer value
increase, SI should pop due to HMEMCPY. Do a bc *, this will clear all
break points, now do a BPM on the address of the timer that you got, for me
it was 00664BEA. Below is what SI poped on (yellow is the line SI is
currently highlighted on, we all know that it is the line ABOVE the highlight
that wrote something into our address):
The requirement is to freeze the timer, so if we NOP (hex:90) the inc ecx
(hex:41) in 00401d5d, that will make the timer value never increase.
THE HEALTH BAR:
The health bar is stored in a 4 byte dword, and it decreases. There are two
values, one is the real one (dynamic), and the other is the one screen
display. Pause Trainer Tester. Pop into SI, set a BPX hmemcpy and exit SI.
Unpause Trainer Tester, SI should pop due to hmemcpy. Do a BC *. BPM
on the real address, for me it was 66ea01. Exit SI. Wow, SI popped on the
following:
:00401d98 48 dec eax ;in SI type: ? eax, you will see your value
:00401d9c 8901 mov [ecx],eax ;? ecx results in the dynamic address.
:00401d9c eb39 jmp 39093939 ; i forgot to write this down, its some jmp
To freeze the health meter, NOP (hex:90) the dec eax (48) instruction.
^chaos^
Essay
I think that basic Assembly language is required in this task. I will, however, g
background on the commands i will use in this tutorial (skip this if you know asm
MOV:
Used to copy data from register to register.
Example:
Mov AX, 12h ;copy 12h into AX
Mov AX, BX ;copy the value inside BX to AX
INC:
Used to increase the value of the register in 1.
it is similar to the ++ command in OOP languages.
Example:
INC DL ;if DL was 1, then now it is 2
DEC:
Used to decrease the value of the register in 1.
Similar to the -- command in OOP languages.
Example:
DEC DL ;if DL was 2, then now it is 1
1. Load the program and select level 6. Open GameHack and select the process "Tra
Pause the program and search in GameHack with the option: Search: ADVANCED. Click
2. Unpause the program, let health meter decrease alittle, and then click on "Nex
with this option: Search: Decrease.
3. Do this few times until you get 2 same values which are less than 100. One of
is incorrect. In order to know which value is correct try to change each one at t
and the one the changes the health meter is the correct one. Delete the other val
of no use.
4. Now the address I got is 67177F, which is probably NOT the same as yours, sinc
dynamic value. Click "Pause" in the program, and type CTRL+D to get into SoftICE.
breakpoint over "hmemcpy" (bpx hmemcpy) and then exit by typing "X".
5. Unpause the program, and SoftICE will break. Clear all breakpoints (BC *), and
breakpoint on memory access over the value you found in GameHack (bpm yourvalue),
get out of SoftICE.
6. The application will break, and you should see something like this:
In case you don't see the following code snippt, try pressing F11 few times until
7. If you read the beginning then you should probably know what to do. All you ha
change the DEC instruction into an INC instruction at the 00402433 memory locatio
In SoftICE type "A 402433", Enter, "INC EAX", Enter, Esc.
If you did all the above like I did, then you probably seen that the lives are'nt
Last Words
I only learnt about dynamic memory address yesterday, and had a success in this o
operate SoftICE and becase I have Assembly knowledge. If you want to succeed in t
to learn ASM. It is interesting and fun, because otherwise, you have nothing to d
Signing off,
Orr
The target: Beans' Trainer Tester 1.1
Difficulty Level: 7
Tools needed
------------
Softice only .. :P
INFO
Well after the topic on beans tester i decided to make a little tutorial on it..
so here it is.. It should be quite easy to follow i hope.. ;)
The Crack/Patch
---------------
First of all you have to have winice loaded..what a surprise huh ..oh well
Then start tester.exe and go to lvl7 and press pause.
Now search for the money value(DWORD, you should only get one hit)
And then go into softice and do an bpm on that value (bpm xxxxxxxx w)
now exit softice and press the un-pause button and bang you should be right back
you should land on this code snippet..
016F:00402B85 90 NOP
016F:00402B86 90 NOP
016F:00402B87 90 NOP
016F:00402B88 90 NOP
016F:00402B89 90 NOP
016F:00402B8A 90 NOP
016F:00402B8B 90 NOP
016F:00402B8C 90 NOP
016F:00402B8D 90 NOP
016F:00402B8E 90 NOP
016F:00402B8F 90 NOP
016F:00402B90 8B442404 MOV EAX,[ESP+04]
016F:00402B94 8B4C2408 MOV ECX,[ESP+08]
016F:00402B98 0108 ADD [EAX],ECX
016F:00402B9A C3 RET
016F:00402B9B 90 NOP
016F:00402B9C 90 NOP
016F:00402B9D 90 NOP
016F:00402B9E 90 NOP
016F:00402B9F 90 NOP
ain`t 100% sure that the addresses are the same but that doesn`t matter as you sh
now hhmm you c that the code ADD [EAX],ECX must be the code that does something h
your value/s... so your first try might be just to nope this function and then th
on this function (you would have noticed that the timer doesn`t increase if you n
so what we have to do here is take a look at what the registers look like when th
NOTE
EAX=0066D9CB EBX=00000000 ECX=00000001 EDX=00000001 ESI=0040D2D4
EDI=00000007 EBP=0064FC50 ESP=0064FB40 EIP=00402B9A o d I s z a P c
CS=016F DS=0177 SS=0177 ES=0177 FS=111F GS=0000
ok so what do we have here...hhmm ..c the ECX,, !! and remember ADD [EAX],ECX the
that that value ECX holds increases the timer so what we have to do know is this.
ok so know you c that i have put that cmp there and if ECX=1 jump to 00402b85
if not return (cause we do not wan`t the money to increase now do we ;)
then we just put the code ADD [EAX],ECX in the address we jump to and then retu
And now just press test and tada the timer increases but the money stands still j
as we wanted it.. ;)
with this crack the life does not decrease any longer either cause ECX holds -1 w
decreasing the lifes so if the tester would want the life decrease to work you wo
to make another compare to -1 .. but that wasn`t needed here so who cares really
here under are som usefull jumps that can be good to know about ..
Now my greetingz :)
Greetz to: everyone on the gamehacking forum i guess..
This tutorial is dedicated to all newbies and/or anyone who just thought that thi
tutorial would help them out...
-----------
© 2001 DudE
-----------
Razali Rambli a.k.a Bie Solution For
DEViOUS Trainme Level 1
Download at http://devious.tsongkie.com
******************************************************************************
My Trainer for DEViOUS Trainme Level 1
Hotkeys
=======
Requirement
===========
Both Full Bar = OK
50000 Money = OK
10 Life = OK
No NOP = YES, I use only mov & jmp
EXTRA = When click test, original message change to
******************************************************************************
This tutorial will show you how to use Tsearch & all it feature
example Calculator, Autohack [Assemble, Register] & explanation
about reading assembly code in game & defeating DMA.
Tools Use
=========
TSearch
We Begin!
-------------------------------------------------------------------------------
Money
-------------------------------------------------------------------------------
Search 4 bytes
Found only 1 address
example C7F010, your could be dif because this is dma value
use autohack & we get here
explanation
----------
mov eax,0x5 <--- put value 5 into register eax
sub [esi+0x4],eax <--- subtract value inside dma with 5,
in this case, the value is money
solution
--------
change value at 004011d6 from 5 to 50000
use Calculator
in Dec, type 50000
now click Hex & value turn to C350
so on autohack, right click on 004011d6 & assemble
type this
the result
-----------
004011D6 B850C30000 mov eax,0xC350
004011db 894604 mov [esi+0x4],eax
Poke 4011D6 B8 50 C3 00 00 89 46 04
-------------------------------------------------------------------------------
First Bar
-------------------------------------------------------------------------------
Remember money opcode? yes this
explanation
-----------
mov eax,0x5 <--- put value 5 into register eax
sub [esi+0x8],eax <--- subtract value inside dma with 5,
in this case, the value is top bar
solution
--------
change value at 4011de from 5 to 100
use Calculator
in Dec, type 100
now click Hex & value turn to 64
so on autohack, right click on 004011de & assemble
type this
the result
-----------
004011DE B864000000 mov eax,0x64
004011E3 894608 mov [esi+0x8],eax
Poke 4011DE B8 64 00 00 00 89 46 08
-------------------------------------------------------------------------------
Life
-------------------------------------------------------------------------------
For life, you can search using the money method, but that method, even a little
kid can do that, we use the better way. that is to understand the game code.
just like we did for First Bar value.
First solution
----------
so now, we dont want the jump at 4011eb
the simple method is just nop the jump
but the trainme requirement specificly said no noping
so what we can do?
easy, we use jump
we destroy unuse code at
jmp 4011ed
Second solution
-----------
this step is necessary because we have to get more than 10 life, but we only have
5 life. so using the same method as money value & top bar value, we change
into this
Poke 4011E9 EB 02
Poke 401217 B8 0A 00 00 00 00 89 46 0C
-------------------------------------------------------------------------------
Second Bar
-------------------------------------------------------------------------------
The final requirement. we put what we have learn before for testing
Solution
--------
simple enough
change to
Poke 40121f B8 64 00 00 00 89 46 10
-------------------------------------------------------------------------------
THE END
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
FOR ADVANCED USER
-------------------------------------------------------------------------------
In other word, more simple & easy to understand for advanced user
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Money >
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; First Bar >
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Life >
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Reset to 10
;-----------
;004011E9 EB02 jmp 0x04011ED
;00401217 B80A000000 mov eax,0xA
;0040121c 0089460C mov [esi+0xC],eax
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Second Bar >
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Reset to 100
;------------
;0040121f B864000000 mov eax,0x64
;00401224 894610 mov [esi+0x10],eax
-------------------------------------------------------------------------------
Trainer Maker Kit
-------------------------------------------------------------------------------
For newbie who want to try this inside Trainer Maker Kit, below is the code
Poke 4011D6 B8 50 C3 00 00 89 46 04 B8 64 00 00 00 89 46 08
Poke 4011E9 EB 02
Poke 401217 B8 0A 00 00 00 00 89 46 0C B8 64 00 00 00 89 46 10
-------------------------
I hope this will help you
Razali Rambli aka Bie
http://bie.cjb.net
razali_bie@hotmail.com
I'm gonna try to do my best to explain this...
1. open up tsearch...
2. open up ghme1lvl1.exe
3. press the "pause" buton in the GTM program
4. click on open process in Tsearch and choose GHME1LVL1.exe
5. goto the menu Autohack and choose enabled debugger in tsearch
6. now we have to do a memory search for the life bars
7. do a new search
8. choose unknown search and click on OK
9. click on pause in the GTM level1 program
10. wait until the progress bar on the bottom decrease..
12. click on search next
13. choose "has decrease" and 1 byte for the type
14. repeat 10 and 11 until you get the results
15. you should get the address two address 530044 and 76F01C
16. right double click on the addresses
17. right click on both address and choose autohack
18. goto to the autohack menu and choose autohack window
19. press pause and make sure the bar is running
20. press pause agian to make it stop
21. go back to the auto hack window and you should see 401224 sub [esi+0x10], eax
22. look at the botton of the Autohack window for dissembler and click on it
23. go back on the top and click on 401224 sub [esi+0x10], eax]
24. now go to the window that has 00401224 294610 sub [esi+0x10], eax] and right
25. choose backwords in the menu scroll down until you see
00401217 b801000000 mov eax, 0x1 </===set how much it will subtract
0040121c 29460C sub [esi+0xC], eax
0040121f b801000000 mov eax, 0x1 </===set how much it will subtract
26. right click on 00401217 b801000000 mov eax, 0x1 and choose Assemble from the
27. change mov eax,0x1 to mov eax, 0x0
28. right click on 0040121f b801000000 mov eax, 0x1 and choose Assemble from the
29. change mov eax,0x1 to mov eax, 0x0
30. now you must do this from the other bar
49. right click on 004011db b805000000 mov eax, 0x5 and choose Assemble from the
50. change mov eax,0x5 to mov eax, 0x0
51. right click on 004011db b805000000 mov eax, 0x5 and choose Assemble from the
52. change mov eax,0x5 to mov eax, 0x0
53. now we need to figure out so open W32DSM98 and load ghme1lvl1.exe
54. ok the money starts with 5000 which is 1388 in hex
55. now go to search menu and choose find text
56. type 1388
57. you should get 004012FC B888130000 mov eax, 00001388
58. 004012FC is the mov eax instruction so 004012FD is the value
59. go back to tsearch and click on the paper to add a new cheat
60. type 004012FD and choose 4 byte and click on OK
61. Change the change the 5000 to 50000
62. go back to the top in W32DSM98
55. now go to search menu and choose find text
56. type 00000005
57. click on find next 3 times in till you get 0040130c B805000000 mov eax, 00000
59. go back to tsearch and click on the paper to add a new cheat
60. type 0040130D and choose 1 byte and click on OK
61. change the value from 5 to 10
62. now goto back GTM level 1 program and click on restart then click on test
-piccahoe
How to beat GTM Level 1 in 5 or less minutes.
---------------------------------------------
What you'll need:
Windasm
Open up Win32Dasm and look at the string references, you may notice an interestin
-[INTRODUCTION]-
I wrote this tutorial per request from Swatto.
It's my first atempt at writeing one so don't expect too much
It does contain some spoilers..so if you're just looking for clues, be aware.
When I used debuggers such as OllyDbg or W32Dasm later on, an error related to NT
would occur when setting any breakpoint causeing the TrainMe to crash. (ERROR_INV
I haven't investigated as to why this happens.
So I dont know wether it's related to bad programming or done on purpose.
There might(in fact I expect there to be) be typos. So no garanties :p
-[LET'S BEGIN...]-
We could go about finding the required memory address's in the most common way.
By useing TSearch fireashot-search-fireashot-search method..
But that's no fun and it will potentionally give you less results.
If you got the benefit of access to a debugger, you could do a breakpoint on 'Get
But since I don't, I opened the file in IDA and got a reference to it from the im
(You actually could use TSearch for this, but it's kind of the hard way to do it.
I traced until I got the one involved with the button '1' (change to pistol)
After a little more traceing I landed here..
.text:0040141F mov al, ds:byte_405629 ;Pistol Ammo
.text:00401424 movzx ax, al
.text:00401428 push ax ; uValue
.text:0040142A push 8B9h ; DialogID inside .rsrc s
.text:0040142F push [ebp+hWndParent] ; hDlg
.text:00401432 call SetDlgItemInt
I made a mental note of the intruction "mov al, byte ptr [0x405629]". Then I saw
SetDlgItemInt call. This told me that it would update some dialogitem on the scre
I opened the TrainMe in ResHacker and looked up the dialogID being pushed.(push 0
By useing ResHacker as a reference I worked out that 0x405629, had to be a pointe
and since this happens when you push the '1'button..
It's ergo the address for pistol ammo. The word 'deduction' comes to mind.
Same method again. This made me conclude it was the pointer for pistol damage.
Same method yet again. It turned out to be the pointer for the pistols maxammo.
SniperRifle----------------------------------------------------------------------
.text:00401559 mov al, ds:byte_405481 ; Sniper Ammo
.text:00401571 push offset 0x40531F ; lpString pointer to "s
.text:00401587 mov al, ds:byte_40560F ; Sniper Damage
.text:004015A3 mov al, ds:byte_40562E ; SniperRifle MaxAmmo
.text:004015BB mov byte ptr[0x405326], 0FCh ; FCh=Sniper
In order to find a way to freeze the weapons ammo, we have two options.. Either
we could continue traceing the code useing the method above.. or we could use
TSearch and set a breakpoint on the address's. I originaly did do the trace, but
setting a breakpoint is much more efficient. So we do just that and TSearch
gives us the following address's.
What it basicaly does is to first check if we have 100 grenades. Then if we do,
compares it against the value from ghu.tmp. You're not allowed to crack the
protection, and thats why I suggested that patching the code is the only way to
go. Since your value will be checked against ghu.tmp anyway.
To find the address for grenades I used the same method as before (GetAsyncKeySta
Now here's the interesting part of the trainme. Inside the "anti-cheater" sub it
first reads a value from a file(c:\windows\ghu.tmp), then compares it to our
grenade value. Then if AOK it writes our decremented value of grenades back into
the file. Then sets certain memory address's involved with the scheme to zero.
So no matter what you poke into 0x405611 the software will know you have cheated
the correct value from ghu.tmp. The only solutions to overcome this protection,
which I can think of, is to patch the code.
2)Code a "loader" which would patch the initial values for grenades to 100
poke 0x40561B 64h ; This would only be helpfull when you start the TrainMe
poke 0x405611 64h ; Not a solution really
//Patch some code inside the grenades "anti-cheat" sub, so it writes our value t
offset 0x401EDC
call @CODECAVE
//Poke correct value into memory, equal to the value written to ghu.tmp
offset 0x405611
hex 64
<<<<<<<<<<<<<<<<<<<<<EasyWriteScript:END>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
After you have done this, you have press 'T' while the trainme has focus in order
Then the our new value for grenades will be written to file too. This will make o
-[THE SOLVE]-
<<<<<<<<<<<<<<<<<<<<<EasyWriteScript:BEGIN>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Make Pistol Ammo 240
offset 0x405629
hex F0
//Setup CODECAVE
offset 0xCODECAVE
@CODECAVE:
mov byte ptr [0x404120],0x64
ret
After you've done this you've got to change weapons?(shouldn't be nessesary?) and
screen updates and write our new grenades value to ghu.tmp.
An alternative solution to the grenades part of our hack,
would be to create a timer (patching code, redirected to our codecave).
Which, when elapsed, would write our value to ghu.tmp and poke the grenade pointe
(and weapons ammo too if you want).
End of line----------------------------------------------------------------------
.text:00401C0A mov eax, 1 ;We have processed all events, En
.text:00401C0F pop edx
.text:00401C10 leave
.text:00401C11 retn 10h
SniperRifle Sub------------------------------------------------------------------
.text:004016F7 cmp al, 0FCh ;Is it the sniper?
.text:004016F9 jnz TrowGrenade ;If not then jump to ThrowGre
.text:004016FF cmp ds:dword_405670, 1 ;Did the timer elapse?
.text:00401706 jnz TrowGrenade ;If it hasn't then jump
.text:0040170C mov ds:dword_405670, 0 ;If the timer did elaps
We could patch location 0x401C0A to call our codecave, it has just enough bytes f
<<<<<<<<<<<<<<<<<<<<<EasyWriteScript:BEGIN>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Setup codecave
offset 0xCODECAVE ; Find a large enough codecave
@CODECAVE:
cmp [@BOOL],0x1 ; Is the timerset?
je @TimerSet ; if it is then jump
push 0 ; lpTimerFunc
push 1F40h ; Interval
push 0xCF ; nIDEvent
push [ebp+0x8] ; hWnd
Call [0x004030A4] ; Call SetTimer
mov [@uIDEvent], eax
@TimerSet:
cmp [ebp+0x10], 0xCF ; Is it our uniqeTimerId?
jnz @notOurtimer ; if it isn't our timer, then continue onto next
push ebp
mov ebp, esp
cmp byte ptr 0x405625, 0xCB
jnz @OPEN
push 0 ; hTemplateFile
push 80h ; dwFlagsAndAttributes
push 4 ; dwCreationDisposition
push 0 ; lpSecurityAttributes, make this 3h for Read+Write acc
push 3 ; dwShareMode
push 0C0000000h ; dwDesiredAccess
push 0x40406C ; lpFileName
Call [0x40303C] ; Call CreateFileA
@OPEN:
push 0 ; dwMoveMethod
push 0 ; lpDistanceToMoveHigh
push 0 ; lDistanceToMove
push 0x40410A ; hFile
Call 0x40201E ; Call SetFilePointer
push [ebp+0x8]
push 0 ; lpOverlapped
push [0x404106] ; lpNumberOfBytesWritten
push 1 ; nNumberOfBytesToWrite
push [@Grenades] ; lpBuffer, what to write
push 0x40410A ; hFile
Call 0x402024 ; Call WriteFile
mov al, byte ptr [@Grenades]; move grenades into register
mov byte ptr [0x405611],al ; poke grenades into memory
But we want the option to change FireRate to "Fast" and "Very Slow" too.
The solution is to find yet another codecave, and put the strings there (remember
Now you only have to change the address's being pushed, to reflect the correct st
The MachineGun lacks a timer which makes it harder to do a ReloadTime hack.
A workaround is to create this timer like we did in the alternate grenade solutio
You also need to create the missing code for the MachineGun, so it will check for
-[LAST WORDS]-
This is what I can remember for now. I hope this tutorial helped you in some way.
That it gave you some new ideas and you've learned something from it.
If something is unclear, I made a mistake somewhere, I use an expression incorrec
or if you've got suggestions on how to further improve this tutorial..
You can find the contact information at the bottom.
-[GREETINGS]-
Archead, Legba, Wyerm, TIC, Zyrtech
..to the people at the www.gamehacking.com forum.
..and everyone else i know :)
>>>>>>>>>>>>>>>>>>>>>>>>>
|CopyRight© GlomYar |
|http://glomyar.cjb.net|
|mail:glomyar@c2i.net |
<<<<<<<<<<<<<<<<<<<<<<<<<
[Target: Extalia Trainme 1.0 coded by MiCRaL]
[URL: http://www.s-i-n.com/chaos/exttrainme.exe]
[Objective: Hax0ring timers + Code Injection]
[PREFACE]
Well it seems that everyone and their mother has a tutorial on code injection, ex
In this tutorial I will show you how to defeat TIMERS in a way in which you are p
have not thought of.
[TOOLS]
WinDasm 8.9
TSearch / Softice
The SetTimer function creates a timer with the specified time-out value.
Syntax
Parameters
hWnd
[in] Handle to the window to be associated with the timer. This window must
be owned by the calling thread. If this parameter is NULL, no window is
associated with the timer and the nIDEvent parameter is ignored.
nIDEvent
[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL,
this parameter is ignored. If the hWnd parameter is not NULL and the window
specified by hWnd already has a timer with the value nIDEvent, then the
existing timer is replaced by the new timer. When SetTimer replaces a timer,
the timer is reset. Therefore, a message will be sent after the current
time-out value elapses, but the previously set time-out value is ignored.
uElapse
[in] Specifies the time-out value, in milliseconds.
lpTimerFunc
[in] Pointer to the function to be notified when the time-out value elapses. Fo
information about the function, see TimerProc. If lpTimerFunc is NULL, the system
a WM_TIMER message to the application queue. The hwnd member of the message
structure contains the value of the hWnd parameter.
Syntax
Parameters
hWnd
[in] Handle to the window associated with the specified timer. This value
must be the same as the hWnd value passed to the SetTimer function that
created the timer.
uIDEvent
[in] Specifies the timer to be destroyed. If the window handle passed to
SetTimer is valid, this parameter must be the same as the nIDEvent value
passed to SetTimer. If the application calls SetTimer with hWnd set to
NULL, this parameter must be the timer identifier returned by SetTimer.
Syntax
hWnd
[in] Handle to the owner window of the message box to be created. If this paramet
is NULL, the message box has no owner window.
lpText
[in] Pointer to a null-terminated string that contains the message to be display
lpCaption
[in] Pointer to a null-terminated string that contains the dialog b
title. If this parameter is NULL, the default title Error is use
uType
[in] Specifies the contents and behavior of the dialog box. This paramet
can be a combination of flags from the following groups of flag
wLanguageId
[in] Reserved.
[PART I]
The first thing that we must do is examine MiCRaL's train me program. If
you run exttrainme.exe, you will see that it consists of 4 things:
the dialog :the main window that holds the other objects
a progress bar :this represents the value we want to hack
exit button :this exits the program
info button :this pops up a message box that tells us what
we must do
In most cases you would find the value which is increased by the timer and
put a BPM on it, then you would NOP the instructions that modify the value.
Thats fine and dandy, everyone knows how to do it and its boring. The timer
changes the value of the variable every time that the timer increments.
Here I will teach you another method, we will inject the KillTimer() function
into the program to stop the timer. We will do this by injecting code into
the program that is called by the INFO button. So how does one go about this?
Well I will tell you, but first let me side track for a second to describe
how calling MessageBoxA works.
The HWND is the windows handle, it tells who owns the window that is ab
be created. Then we have the main text that is to be displayed, you coul
a variable here rather then a string. Next is the caption that goes at the
the message box. Next are the icon and what buttons are to be placed on the messa
One method is to open up WinDasm, click on the IMPORTS, and locate USER32.Mes
double clicking on it will lead you to the part of the code where the MessageBoxA
is called. The other method is to BPX MessageBoxA in softice, both will lead y
same place.
So when we click on the INFO button, it eventually makes it to this routine whe
followed by the main text, then the windows handle, and finally it calls th
chose to JMP to my routine from :004011DE because a) its 5 bytes, same as a
a MessageBox to the user telling him that the timer is enabled / disabled, but I
5 extra bytes of code by pushing the caption information again in my routines. I
EASY SCRIPT to do my code injection since its nice and friendly.
REMEMBER THAT UNLIKE OTHER PROGRAMMING LANGUAGES, PARAMETERS IN ASM ARE PUSHE
IN ASM YOU HAVE TO PUSH THE CAPTION FIRST, FOLLOWED BY THE MAIN TEXT, FOLLOWED
THEN THE CALL TO MESSAGEBOXA. Although in our case we are not going to push the c
in the original code to save some bytes later.
offset 40142c
//Lets recreate all the stuff for now
//push the main text of the message
push 00403029
//push the windows handle
push [ebp+08]
//call MessageBoxA
Call 004013DE
//Jump back to AFTER the call to MessageBoxA since we already called it
//if we didn't the program would crash since it would have no parameters
//pushed anymore
jmp 004011EB
If we run the program and turn on the Easy Script, we see that if we press the IN
work normally. Congratulations, you have injected code into the program that redi
then we recreated the pushing of the main text and the handle and then the cal
Great. Next lets store some strings in memory so we can call them later when we
the timer was enabled or it was disabled.
offset 40148a
asc "disabled"
hex 00
//hex 00 is a null terminator needed for all strings
offset 401493
asc "enabled"
hex 00
Okay. Before we proceed I must teach you how the SetTimer() and the KillTimer() f
to better understand as to what you are looking for.
..
Now find the KillTimer function in the trainme.exe
..
Okay well now at this point of the tutorial we are going to add that KillTimer Ro
that we created earlier. I added *NEW* to all the lines that are new this time ar
offset 40142c
//Lets recreate all the stuff for now
//push the main text of the message
//*NEW* we change the text from MiCRaL's original text to our "disabled" text. *N
push 40148A
//push the windows handle
push [ebp+08]
//call MessageBoxA
Call 004013DE
Okay if you want, you are done. If you click on the INFO button it will display a
you click OK the timer will be stopped, so the progress bar will not change any
that the timer affected.
[PART II]
In this part we will add a variable that tells us if the timer is enabled or disa
enable or disable the timer. I have chosen an empty byte at 4014b1 to be my IsTim
offset 40148a
asc "disabled"
hex 00
offset 401493
asc "enabled"
hex 00
offset 004011DE
//this is the location of our new function, its just a
//bunch of 00's that i found so i could over write it
jmp 40142c
offset 40142c
//Lets recreate all the stuff for now
So now what we need to do is add a CMP that will compare the value in our IsTimer
I have marked all new lines with *NEW*
offset 40142c
//*NEW* check if timer is off
cmp byte [4014b1], 01
//*NEW* jump to our function holding the SetTimer Function
je 401462
[CONCLUSION]
Well thats it, now when you click on INFO it will tell alternate between enabled
We could have also jumped to the ORIGNAL SetTimer and KillTimer in code, but ther
was followed by an exit from the program - the program would quit. So its best th
enjoyed this little code injection tutorial and now you will be able to defeat
This inclues the ones that are so clever as change values rapidly but do not incl
Also if you do not feel like injecting all of this code, it is possible to slow d
SetTimer which is below:
Since the timer is usually initialized right when the dialog loads, you would hav
or you could just whip out your trust hex editor and modify it from there so that
P.S.
If you are writing a trainme, there is ABSOLUTLEY NO REASON to pack it. It just m
know how to unpack it and rebuild the PE header to have a working exe. If your
be no reason to hide it with lame anti-debugging techniques/packing it. Leave tha
^chaos^
idxchaos@hotmail.com
www.s-i-n.com/chaos/trainerology.htm
<~~greets~~>
[sheep], MiCRaL, Archmage, MrNOP, Visual Perfection, MiraMax, cppdude.
the people of #gamehacking on efnet
_._____
\ | ____
| | |____|
| |______ ________ _ _______ | \_
| ._ \ ._ \_._ /__|\| |
| |/ / |/ | / | |
_ __| | /_ | | | |_ __ _
__ _ _______________| |____________|_______________
____________________ | | _brzi_________________________
__ |_ | __
|___________________ \____| ___________________________|
--------------
[Introduction]
--------------
The reason that i'm writting this tutorial is to help all of those n00b's who ar
get in DEViOUS and in general, how to defeat timers (in a more advanced way). Sin
in they need to defeat EEDOK's HackMe. I haven't seen anyone of them to do that,
help for them. We all like to help these guys who are trying to learn something..
Well yeah until the start to ask too stupid questions like: "What's SoftICE and w
debugger?".. But there's forgivness for everything :)))
Anywayz, this tutorials assumes that u have at least basic knowledge of ASM and u
a simple code injection, since we are going to beat timers with code injection. I
that u should check my previous code injection tutorials and [sheep]'s tutorials.
a good understanding of how things work. Ok, since we're ready let's start...
------------------------------
[Tools and Where to Find Them]
------------------------------
[EEDOK's HackMe]-[http://devious.tsongkie.com]
[TSearch 1.6]-[http://www.gamehacking.com]
[W32Dasm 8.9]-[http://www.gamehacking.com]
[API Reference]-[http://www.win32asm.cjb.net]
-------------------
[Windows API Calls]
-------------------
The KillTimer function destroys the specified timer. The system searches the mess
any pending WM_TIMER messages associated with the timer and removes them.
BOOL KillTimer(
hWnd
Identifies the window associated with the specified timer. This value must be the
hWnd value passed to the SetTimer function that created the timer.
uIDEvent
The SetTimer function creates a timer with the specified time-out value.
UINT SetTimer(
hwnd
Identifies the window to be associated with the timer. If this parameter is NULL,
associated with the timer and the idTimer parameter is ignored.
idTimer
Specifies a nonzero timer identifier. If the hwnd parameter is NULL, this paramet
uTimeout
tmprc
Points to the function to be notified when the time-out value elapses. For more i
about the function, see the TimerProc callback function.
If tmprc is NULL, the system posts a WM_TIMER message to the application queue. T
of the message's MSG structure contains the value of the hwnd parameter.
--------------
[Lesson Start]
--------------
Open W32Dasm 8.9 and Disassemble EEDOK's HackME and click on ImpFnc button on th
From the list double click on user32.SetTimer function. I have this code..
..............
..............
..............
..............
..............
..............
..............
..............
* Possible StringData Ref from Data Obj ->"Hack this bitch as many ways as "
->"you can."
|
:00401585 68EC304000 push 004030EC <- pushes the msgbox text
:0040158A FF7508 push [ebp+08] <- pushes the window handle (hWnd
So, we sad that when the "Instructions" button is clicked, the usual MsgBox will
and our KillTimer code will be executed. So we must jump from somewhere to our co
Ofcourse we will jump from the msgbox caption to our code cave :)
Open up TSearch and start EasyWrite...
//call MessageBox
call 00401938
//push the timer id - the id of the timer that is created so we can destroy that
push 00000008
//Call KillTimer
Call 00401920
//Jump back - remmember the "<==We will jump back here <==" offset
jmp 00401592
//Now we replace the main code with a jmp function that will jump to our code cav
//Remember we jmp from the msgbox caption
offset 00401580
Ok, now add a hotkey to the script and try it out.. Does it work?? NO!!!!! Yeah
confused me too.. But i found the solution.. What's the problem here...
When the parameters of the SetTimer and MessageBox are pushed the window handle
pushed is "push [ebp+08]", but this is not the same for the KillTimer function..
that i just replaced the window handle that is pushed before the call to the Kill
"push dword ptr [00403168]" to "push [ebp+08]" the same for SetTimer and MessageB
result is: "WORKS!!!!". So here the final TSearch script:
//call MessageBox
call 00401938
//push the timer id - the id of the timer that is created so we can destroy that
push 00000008
//Call KillTimer
Call 00401920
//Jump back - remmember the "<==We will jump back here <==" offset
jmp 00401592
//Now we replace the main code with a jmp function that will jump to our code cav
//Remember we jmp from the msgbox caption
offset 00401580
-------------
[Final Words]
-------------
I don't know what to say, i just hope u learned something from this because it is
Also i would recomend the tutorial from ^chaos^, he has a good tutorial on timers
tutorials on other subjects. http://www.s-i-n.com/chaos is the link to his site.
For more tutorials visit my site. Thank u for reading this tutorial.
Now turn off ur PC and goto bed. U deserve a little sleep :)
--------
[Greets]
--------
‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡
‡Dedicated to ..:Omega:.. - MISS YA BRO‡
‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡‡
****************************************
‡ Tools Needed ‡
‡--------------------------------------‡
‡ SoftIce ‡
‡--------------------------------------‡
‡ Memory Searcher ‡
‡--------------------------------------‡
‡ A PIECE OF PAPER ‡
****************************************
****************************************
‡Links To The Tools ‡
‡--------------------------------------‡
‡SoftIce - I am giving you the latest ‡
‡version of SI - ver. 4.5 ‡
‡www.newhua.com/down/si405w9x.zip ‡
‡Serial #: 4001-2345FB-BF ‡
‡--------------------------------------‡
‡Memory searcher - your choice ‡
‡www.gamehacking.com ‡
‡--------------------------------------‡
****************************************
‡ Lesson Start ‡
****************
ONE: Well if you learn Code Injection you can give yourself a bigger rank
in the gamehacking community,but.. the main reason is that if you know
how to do Code Injection and you have enough ASM knowledge the there is
nothing that can stop you from doing something BAD!! to the game - ofcourse
this is limited by your knowledge of the game and your knowledge of the ASM Langu
TWO: Your are playing your game, ok, you have found your ... lets say health
address... You NOP that address and you have an infinite health.
But you pass the level or you go on the next stage and it doesnt work anymore.
You say: WHAT THE HELL!? Well HELLO !!!! This is DMA!!! It causes your memory
addresses to change everytime you run/restart the game or when you change the
level/stage/map. Well this is fucking annoying, you can stop it by finding the
instruction that decreases your health and by NOP-ing it but what if you want
something more, what if you want something BAD! to the game. Well that can be
accomplished with Code Injection. All you need is included in the Tools and
you have to be willing to learn.
IF KNOWLEDGE IS CRIME, THEN MAY GOD HELP ME. - Remember this sentence.
*NOTE: This is my opinion.
Code ...
00401384 A390D04100 mov [0x41D090],eax <-move the value of eax into ON SCREEN v
00401389 C644241100 mov byte ptr [esp+0x11],0x0 <- SI pops here
00401385 E86D0D0000 call 0x00402100
........ ........ ...............
‡How to find a Code Cave using Tsongkie' Code Cave Tool, SoftIce‡
*****************************************************************
The Easy way is Tsongkie's Code Cave Tool:
Start TCCT.
Type the window name of the program/game. In our case type prog test.
Press on Search.
TCCT will find a lots of addresses and display them in the Result Box.
But we wont select any address from this, we will use that old SI way
and then select an address.
---------------------------
The SoftIce way:
In SI type:
TASK
You should see this:
--------------------
---------------------------------------------------------------------------------
NOW Type:
MAP32 Programme test <- here you type the name of the game eg. GTA2
You should see this:
--------------------
Now lets check the address that is in the .rsrc line (00427000)
In SI type:
U 00427000 - Press Enter
Now you will be at code location 00427000.
Scroll the window up by pressing Ctrl+Up key and you'll see lots of
addresses like this:
In SI type:
a 00401384 <enter>
Type jmp 00426f80
Press Esc or Enter
Now we type:
u 00401384 <enter>
to
MOV [EDI],AX
MOV EAX,[EDI+14]
MOV ECX,[EAX+50]
Now after we write our jump without the NOP to even the code the code will
look like this:
And when our code is executed and jmp back to the game loop the game/program
will crash . But if we write NOP to even the code it should be like this:
In SI we type:
u 00426f80 <enter> - this will bring you to the address
a 00426f80 <enter>
type MOV EAX,064h <enter>
type MOV [0041d090],EAX <enter>
type JMP 00401389 <enter>
Press Esc or Enter
u 00426f80
00426F80 B864000000 MOV EAX,00000064 <- now eax has the value of 100 Dec - 64 H
00426F85 66A390D04100 MOV [0041D090],AX <- mov the value of eax into ON SCREEN v
00426F80 E9F9A3FdFF JMP 00401389 <- jmp back to the game code
Now lets check if our Code Injection works. First clear the break points
in SI type bc * <enter> and exit by pressing Ctrl+D. Look at the program.
What !? The value is the same, but wait the program increases the value
everytime you press the button.So press the button few times and you will
see what happens. The value will be 101 cuz the program add one to the value.
If the program crashes then you have wrote something wrong. Check if you have
wrote everything like i told ya.If yes then congratulations you have made
your first Code Injection.
Write the opcodes on a piece of paper. We need the opcodes for later when
we will poke this address with the trainer.
You see that code injection is easy, you just need to practice and everything
will be just fine.Remeber that i told you that you can do some BAD things
with Code Injection.
And finaly this tutorial is over. THANKS GOD for that. Now i can get to my
normal life again. IS THERE IS ONE :)
‡Greets:‡
*********
To Sheep for releasing his wonderfull tutorials - check them out www.sheeprec.cjb
To All Members of the DEViOUS Team and everybody that i know.
How to create a trainer for energy bars using GameHack and Master Cheater
I'm using Virtua Fighter to demonstrate how the creation works but I think it can
First of all you should start Virtua Fighter, then ALT-TAB to your desktop and lo
Now select the process you wanna cheat (in that case 'Virtua Fighter PC') by clic
Done ? Allright, let's continue.
Get back to the game (I think you know how to do that...). It's much easier to fi
Once inside the game ALT-TAB (or CTRL-F12) to GameHack. Press that binoculars- bu
Click on OK and return to your game.
As the second player hit player 1 one time and go back to GameHack.
Click on 'Next search andsearch for a 'decreased' value now. GameHack finds a lot
It can be that a lot of adresses are left at the end, so use the 'Trial-and-error
I think those negative values are complete bulls**t, so (in my case) 008E3710 is
Try to enter '255' as the value and go back to the game. Whew, the energy bar loo
Type in '200' and get back to VF. Allright ... everything's normal and click on t
Try to hit player 1 in the game ... the energy fills up everytime he's hit.
STAY INSIDE OF THE GAME, IT WILL MAKE THE PROCESS HANDLE EASIER LATER !! Umm ...
Enter that C8 (Beware ! This is for Virtua Fighter ! This value may not work on o
The program creates a file called vfenergy.mct in its directory which is importan
The BUTTONS TITLE should be 'Energy P1' so that the end user knows what'll happen
Type TMBUILD into the input field and choose the options that will fulfill your n
Start it, minimise it, press CTRL-T inside the game, freeze your energy bar and t
And don't forget: 'The world is a beautiful book, for those who can read it.'
Target : Worms 2
~~~~~~~~~~~~~~~~
Level : Beginner(-Intermediate)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LET'S START
~~~~~~~~~~~
OK. The purpose of our hack is to find the passwords for all levels of the
game...
So, open the password window, type in a bogus string, hit OK. The game didn't
do anything. It's time to find out its secrets...
We observed that Worms 2 uses a dialog/window where we could type the password.
Open SoftIce (CTRL+D). Let's try to bpx on Windows' API GetWindowTextA and
GetDlgItemTextA. These API are often used by programs for getting the data
inside edit_boxes. So in SoftIce type :
bpx getwindowtexta
bpx getdlgitemtexta
Tip : That "a" in the end of those API stands for 32-bit code. On 16 bit code,
you don't need that "a".
Exit SoftIce (CTRL+D or F5 or type X and hit [ENTER]). Return now in the game's
menu, and go again to the password window. This time, type in the edit-box
your name, for example, or a familiar word. Press OK.
From above code, we observe this : After API was called, something SUSPICIOUS
is moved in ecx. So, when you're on "push FF" in SoftIce, type
d ecx
Oh, no ! We don't see anything good for us... HEY, but wait a sec ! Look at the
first 4 bytes displayed in SoftIce's display_window! They are :
9C 58 4A 01
Mmmmm... Maybe it's a pointer to something... Let's find out ! Type this:
d 014A589C
You see, we inversed the bytes from right to left. That's how the computers deals
with them...
And in display_window we see the string you typed in the password-box ! It's a le
You can also type :
d *ecx
That "*" in front of ecx tells SoftIce that it's about a pointer, so display the
memory that is NOT in ecx's address, BUT in address pointed by the first 4 byt
stored in ecx! In both ways, you'll get the same result : your string !
Yeah, but what can we do with this ? SIMPLE : since we know where it stored our
string, we set a breakpoint to see when the game compares our string with the
levels' passwords ! To do this, type (in SoftIce, of course) :
bpm *ecx
OR
Tip : "bpm" is a breakpoint on memory access. It tells SoftIce to pop when that p
of memory is beeing read from or write to.
If you are in kernel32's code, press F5 until you will be in Worms2 code!
We are in Worms' code. Good! We see something like this :
.........code...code......
........code..code....
Now, We landed on "inc edi" instruction, so press CTRL+UP to see the above code.
We know that esi points to the real passwords, and edi to our string. All we
have to do is :
d esi-1
(We dec esi because it has been inc-ed at address 49BBA2 - check above! )
We see the password for first level, that is "ONCEUPONA" !
This breakpoint will tell SoftIce to pop when breakpoint is reached and to displa
the memory pointed by esi. (esi was the register for correct password, remembe
All you have to do right now is to sit back in your chair and press F5, then writ
down the password, press F5, write down the password... Got the ideea ?
Very GOOD !
FINAL WORDS AND REMARKS
~~~~~~~~~~~~~~~~~~~~~~~
I start writting this tut when I had a contradiction with the people in GameHacki
forum... I told them that cracking and gamehacking are like 2 brothers, but th
didn't listen... I hope this tut will PUSH in their minds that, and they never
POP it !!!
CHEERS AND GREETS (order doesn't matter)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Groza (BEST publisher :) - I'm still waiting that tut on C&C map_hack :) )
- Snaky (te-am cam copiat putin! hehehe... Ne vedem la un suc :))))
- T-RaiNeR (cum mai e cu facultatea ?)
- ParaBytes (my cracking teacher - a BIG THANKS)
- All in GameHacking's forum (what to say... you are incredible :)
- All GHU members (Suntem de belea, eh ?)
- JUVENTUS AND ALL JUVE FANS & PLAYERS (you make me happy when I'm sad. I love JU
- All crackers in the world ! (you opened a beautiful book for us)
- YOU
romanian:
*******************************
* Salutari celor din Romania! *
*******************************
Sorin ( Splinter@email.ro ).
2003
eof
OllyDbg Tutorial
Tools Needed :
~~~~~~~~~~~~~~
INTRO
~~~~~
Lately, more and more people asked me to marry them and to write some Olly tuts.
I see no connection between these 2, but here goes :
- I don't use OllyDbg in gamehacking;
- I am married with Yogi Bear (or Scooby Doo, I don't remember exactly :(
But you know those words : "The newbie is always right". So, I decided to write s
Olly stuff. But like I said, Olly isn't so good in gh like SoftIce, so I'll s
you how to use it in other 'domains', too. Also, some people spamed me and ma
head huge with Olly requests. Here you are, mo' fo's ! Hope you'll like it !
Let's Begin
~~~~~~~~~~~
Let's take a look at Olly's main window, first. To do that, chose a program and o
it inside Olly. I've chosen Mortal Kombat 4. Here's what I've got :
You have 4 BIG windows :
- The Disassembler Window. Here you can see program's code in asm language, a
can comment every line of code.
- The Registers Window. The home of eax, ebx, edi etc. The flags are here, to
like SoftIce's top 'window'.
- The Dump Window. Here you can view/edit in hex or ascii the memory of the p
you want to debug. You can see here what you can see in SotIce after 'd
- The Stack Window - not important to what we'll do.
Also there's something below the Disassembler window : The Tip Window. It's not i
but I call it that way :). When you are at a code line (with the debugging),
you details about that code line. If you're on "mov eax, dword ptr [123]" for
shows you what number is stored at [123]. And many more helpful hints.
Well, that's the 'overview'. You'll learn more while we're debugging some targets
a kind of "learning through doing".
- Cracking Mortal Kombat 4 (no cd crack) - This is the starting point (READ!)
- Cracking Nightmare Creatures (no cd crack) - Practice what you've already l
- Hacking Mortal Kombat 4 (hitter takes damage) - Olly in gamehacking
CHEERS & GREETS (order doesn't matter)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2004
eof
You know how to find health addr. in MK, right ? If not, then maybe this tut
is not for you... (have you heard of mem. finders ? - read some other
beginner tuts, then come back !).
I've found the health addr. (I'm a good boy :) ). They are :
53865C - the health of Player1
535EAC - the health of Player2
Since we want a "hitter takes damage" hack, we need the health addr.
Now... Load MK in Olly, then let it run (F9). Start a 2 player game, and
play a little (hit with both chars.). After this, set in Olly a mem.
breakpoint on player 2's health address. You should now how to do this
from MK no-cd tut. (CTRL+G in Dump Window, insert the health addr., then
select it's first 2 bytes (a word) and right-click on them, then choose
"Breakpoint"->"Memory, on write"). And after this, hit player 2 with
player 1. Olly should pop here :
What is all this crap ? Where are the ASM instructions ? We know this code
is to be executed, but we don't see the instructions !
Well, Olly is not a perfect program. When the target is loaded into Olly,
an analyze of code is started (to give the user useful hints and comments).
And Olly's display is based on the analyze. So our problem could be this
analyze that Olly had some problems with it. Let's remove the analyze to
see if this is the problem. To remove this analyze right-click in
Disassembler Window, then choose "Analysis"->"Remove analysis", like in
the pict. :
Theory : If you find your wanted addr. NOT being a dynamic addr. and the
game access it with the help of pointers, then the line(s) of
code that's messing with your addr. is used in other actions
by the game, too. Also, if so, the flags/registers are the answer.
I know it sounds logic, but it may help you find some other things done by
the game, things that you might forget to look at...
So, in our example, the same routine is used to decrease the health of both
players. But from where does the game now it's about playerX and not
playerY ? It gotta check something, right ? And this 'something' have
to be executed above the code-line that's modifying the health.
And again I traced and debug until I wrote all that comment.
I've found out that "cmp eax, ecx" at 48E00B is the decision instruction.
If eax=ecx, then player2 hit. Else, player1 hit.
But you want to see it for yourself, right ? OK... Let's set a breakpoint
at 48E00B. But this time a CONDITIONAL breakpoint. Here's how it's done :
(but first remove that mem. breakpoint on player2 health ! you should
know how to remove it from MK no-cd tut !)
Nothing easier : to set a conditional breakpoint at a code-line, you
click it, then right-click it and choose "Breakpoint"->"Conditional".
(or click on it and press SHIFT+F2). After this, a dialog will appear
asking for the condition (conditional breakpoints act like this :
if the condition is met, tell Olly to pop ! hehe :) ). The dialog
is like in the pict :
We'll set the condition to "pop if eax = ecx". In the dialog you must write
"eax == ecx", without any 'if' or something. Also take notice that you
must use assembly code ("==" for equal). After you did this, press OK.
The address on which you've set a conditional breakpoint got 'pink'. Here's
a pict :
And now, let's test to see if I was right about that "eax=ecx if player 2 hit".
Go back in the game and hit with player2. (when I say hit with playerX,
I mean hit with playerX playerY, and not hit with playerX the air). Olly
should pop. Let's look at the registers :
F9 to run the game and hit with player1 this time. WHAT ? Olly don't pop ?
Hit again ! Still no popping ? That's because even if the game executes
that cmp instruction, Olly don't pop 'cause the condition is not met (eax
is NOT equal to ecx). So I was right !!! Eax=ecx ONLY when player 2 hits !
If you still don't believe me, let's remove the conditional breakpoint (with F2)
and put an execution breakpoint in it's place. The execution breakpoint have
no condition, and will tell Olly to pop EVERY time the game executes the
respective instruction (the one on which we've set the breakpoint).
An execution breakpoint is set with the F2. The addr. should get 'red', right ?
Ok. Now back in the game and hit with player1. Olly should pop. Let's look
at the registers :
Now, we'll try to do the "hitter takes damage" hack. For this we'll need a code-c
where we'll put our instructions. To find a code-cave, we must know how and
where is mapped the game's memory. And to find this out, we just press
ALT+M in Olly. Here's what we've got :
Usually we search for a code-cave (lots of 00s) at the end of the .data section.
In our example, end_of_.data = beginning_of_.rsrc = F9F000 address. We'll loo
for our code-cave just above F9F000. I think F9EE70 is a good place.
Now, set focus to the Disassembler Window, press CTRL+G (go to), and enter 0F9EE7
our code-cave address. (must start with 0 or Olly finds it invalid). Here's
what you should find :
See ? Lots of 00s. Now return to 48E00B (with CTRL+G, of course). We're going to
jump from 48E00B to 0F9EE70. At F9EE70 we'll inject our code, then we'll jump
back to an addr. below 48E00B. Here's the plan :
Ok. CTRL+G and go back to 0F9EE70. Double-click that line and assemble this code
jmp 0f9ee70
And now all you have to do is to play ! (remove first all breakpoints you could
have).
Happy ?
Of course you could have done this hack by changing the 'je' at 48e018 into
'jne', without all this code-injection that practically do the same thing,
but you work 'harder'. BUT since this is a Olly tut, I wanted to show you
the code-cave hacking with Olly :) Satisfied ? ;)))
http://www.ghu.as.ro/
OllyDbg visual crash course - for gamehackingBy: EEDOK
Mr_eedok@hotmail.com
First off you would want to open Ollydbg before opening the game, then open the game through
Ollydbg like so:
Once Ollydbg is opened you would hit the C (which is outlined with orange and has an arrow
pointing towards it) to bring up the main CPU screen, which would look something like this:
Once at this point you would want to hit F9 until the game you are playing is running normally, and
whip out your favorite memory searcher to find the address which you want to set a breakpoint on.
Once you have found the address you wish to hack in your memory searcher you would alt+tab back
to Ollydbg and click on the CPU - main thread window and hit Ctrl+G, a window such as this would
pop up:
In the combo box of the window that comes up(where it says 41D090 in the example) is where you
would want to put the address on which you would want to set a breakpoint on. Upon entering your
address, it should take you to your address under the dump(bottom left side of CPU - main thread
window), from here you would right click your address to bring up this menu:
The 2 different breakpoints are as follows:
Memory, on access - Makes the program break whenever the address is read.
Memory, on write - Makes the program break when the address is written to (Tsearch Default).
Shouts to:
Devious: Stonerifik, Tsongkie, Omega, Synbios, Micral, Mini^Me, brzi, Invader, Sn0w
Web sites:
Devious
Mine
################################################
# [Artmoney Explained by InvadeR ] part 1 #
################################################
# #
################## #
#[ Info About Tutorial ]# #
################## #
#This tutorial is designed to explainArtmoney and what it can#
#do and how it works to beginners. #
################################################
# Contents of part 1: #
#Buttons explained, Searches explained. #
#################################
##############
[ Select Process ]
##############
This is the first thing you do when memory scanning. You want to select the proce
you are going to memory scan.
########
[ Buttons ]
########
After you have chosen the process/program you are going to memory scan you can op
window and choose how you want to search. The options for searching and what they
as follows:
--#[Search]#--
-Exact Value is for when you know the exact number you are searching for.
####
-Sequence Of Values is for when you are searching for a group of address's that c
what you are looking for but you don't know which has it.
####
-Range is for when you know the general area of the number but you don't know exa
where it is.
####
-Unknown Value is for when you have no clue what your value is or your just searc
anything.
####
-Coded Value is for when the value is unknown and likely coded unusually.
####
--#[Value]#--
Is of course where you enter the value you are searching for unless you have sele
an Unknown or Coded search.
--#[Type]#--
This is where you choose what type of search your are preforming.
####
-Custom is where you can define all the points of the search criteria.
####
-Integer is what your going to use fo ra typical Decimal(Number) search.
####
-Float is used for values between -1.2E-38 and 3.4E38.
####
-Text is for when you are searching for ASCII/Text(Letters or Words),
####
After you have completed you first search and are ready to search again you use S
It will narrow down the results of the last search to a lesser number.
--#[Search]#--
-Exact Value is for when you know the exact number you are searching for.
####
-Sequence Of Values is for when you are searching for a group of address's that c
what you are looking for but you don't know which has it.
####
-Range is for when you know the general area of the number but you don't know exa
where it is.
####
-Unknown Value is for when you have no clue what your value is or your just searc
anything.
####
-Coded Value is for when the value is unknown and likely coded unusually.
####
--#[Value]#--
If you have chosen Unknown or Coded value you will not have to enter a value, oth
you enter the value depending on the chosen Search type.
-For an Exact Value you enter the exact number you are searching for.
####
-For a Sequence Of Values search you enter the sequences of numbers you are searc
for.
####
-For a Range search you enter the lowest number you think what you are searching
could be and the highest number that you think it could be.
####
-For Unknown Value search you choose one of the following for your Value:
--Was Changed - The number has changed since you last searched.
--Was Not Changed - The number is the same since the last search.
--Was Increased - The number has gone up since last search.
--Was Decreased - The number has gone down since last search.
--Was Increased By - You know exactally what it has increased by, but not to what
it has increased to.
--Was Decreased By - You know exactally what it has decreased by but not to what
it has decreased to.
####
-For a Coded search you choose one of the following for your value:
--Was Changed - The coded number has changed since you last searched.
--Was Not Changed - The coded number is the same since the last search.
####
--#[Type]#--
This is where you choose what type of search your are preforming.
####
-Custom is where you can define all the points of the search criteria.
####
-Integer is what your going to use fo ra typical Decimal(Number) search.
####
-Float is used for values between -1.2E-38 and 3.4E38.
####
-Text is for when you are searching for ASCII/Text(Letters or Words),
####
The options window is used to edit options within Artmoney and to change
how things work on it. Below is a list of tabs and what operations you can edit:
--#[General]#--
-Show Process is where you define what type of processes to show, here's what eac
####
--ALL is every process running on the system, even those that are hidden from vie
####
--Visible are those that you can see on the main screen or in the task bar.
####
--With Windows are programs running within windows.
####
-Game Type is where you define what type of game you are playing, here's what eac
####
--ALL will search as if the game is Win16/32 or Dos.
####
--AUTO will detect what type of game you are playing and change the search to mat
####
--Win32 will set search settings to search like the game is Win32.
####
--Win16 will set search settings to search like the game is Win16.
####
-Search In Address Range will allow you to specify from what address to what addr
wish to search through for the info you are looking for.(Example: You know that b
update the address was 478ED4 but that it has changed, so you can specify to sear
470000 and 480000.)
-Economize Disk Space is used to keep the about of memory you use down, for peopl
slower computers and don't want this to crash it.
-Undo/Redo Sieving will allow you to undo/redo searches after you have already pr
-Scan Priority will allow you to set how sensitive the scan is. The higher you se
(meaning it will mostlikely find more results) it will be.
--#[Additional]#--
-Byte's order will the define how the bytes are displayed. They are fairly self e
-Integer View will allow you how to view bytes. Either Signed or UnSigned.
-Refresh Time defines how often Artmoney refreshes the values of the address's.
-Freeze Time defines how fast Artmoney keeps the address's value frozen where it
-Show Addresses defines how many addresses will show up in the search box.
-Decimal Format defines how many decimals it will display. (Example: If set to 2
like this 23.00, if set to 3 it will display like this 23.000)
-Hexidecimal view will allow you to view all values in the hexidecimal format ins
--#[Personal]#--
This tab allows you to enter infomation about yourself and some comments.
--#[Interface]#--
-Language allows you to choose, thats right, you guessed it, what language everyt
Which I don't believe has been setup on most versions, so it's basically useless.
-Charset is where you define what the text on Artmoney looks like.
-Main Font is where you define the Font you wish to use on the main program.
-Table Font is where you define the Font you wish to use on the tables.
-Main Background Color is where you define the background color for the hole prog
-Input Background Color is where you define the background color for the input bo
-Button Color is where you define what color the front of the buttons are.
-Elipse Buttons will convert all Square and Graphical buttons into Eliptical butt
--#[Hotkeys]#--
-Hotkeys Is Enabled is of course where you define if the hotkeys are on or off.
-Popup Hotkey is where you define what hotkey will make Artmoney the window In-Fo
-Select Current Process is where you define what hotkey will select the current p
that is In-Focus(the window you are viewing) as the process you are going to memo
scan.
-Freeze/Unfreeze is where you define what hotkey will Freeze/Unfreeze the current
you have selected in the cheats list(where addresses are sent after moved from se
-Set Value is where you you define what hotkey will Set the value in the Input Bo
of the current address you have selected.
-Add To The Value is where you define what hotkey will Add the value in the Input
value of the current address you have selected.
You can set the Hotkey for Freeze/Unfreeze,Set Value, and Add To The Value by cli
to the left of them where it displays the hotkey and then pressing the key you wi
hotkey and once you have the one you wish displayed in the box press ok to set it
### [ Help Button ]###
Help will give you some information about Artmoney. You can recieve more help by
to the Artmoney folder and going to the Help folder and it has help files with mo
and pictures about Artmoney and some of its Operations.
About gives information about the maker of Artmoney and the such.
Not really any help here needed..but what the flick. :)
Benchmark will test your system's speed and then display it on the chart against
the other systems.
Clear will clear the entirecheats list box of addresses and everything.
Load will load a saved cheat list table(.amt) from the Artmoney Tables directory
Will save all of the addresses and values and any comments in the cheats list
box into a .amt(Artmoney Table) for later use.
Is where you will input any information about the current table of addresses and
that are to be saved.
################################
DEVIOUS - http://devious.tsongkie.com
TCB - www.tcb-hacks.com
CES - www.gamehacking.com
CC - www.cheat-core.com
################################
Greetz fly out to all DEVIOUS & TCB
################################
Date: 7th Of July, 2003
################################
Best viewed in Arial, Regular, 9
Using SoftICE for Game Training
Author: Orr
Preface
-------
Most of the game trainers out there relax when they figure out that the
game they have been training is not using DMA (Dynamic Memory Allocation), in ord
to store the values it needs for the gameplay. Once they are sure it is Static
(that is, the address never changes), they go on and code their trainer. In this
tutorial I will show how to use SoftICE in order to create a trainer, even if the
address is static. I usually can't care less if the game is 'static' or 'dynamic'
I use SoftICE, and I have more control over the game.
Pre-Requisits:
- Basic Knowledge of Game Hacking (using a memory seeker).
- Basic Knowledge of Assembly commands (I will review some).
- Basic Knowledge of SoftICE.
The target game for this tutorial is "The House of the Dead 2". I chose it becaus
it is using Static Memory Allocation, and because it is quite easy game for begin
There are 2 main items in this game; The Bullets, and the Life. The second is a b
more tough than the first one, so I will teach how to hack the both of them here.
Bullets
-------
Start playing alittle, and you will notice then you have 6 bullets. Shoot them al
up and you get this nasty message "RELOAD". Basically you reload with the right m
button. In the first "House of the Dead" game there was an auto-reload option, bu
they 'forgot' to add it in this version... playing without auto-reload is harder.
uhm, I say we should ReCREATE this option, and show the coders of the game how to
it properly! hahaha! ok. I will calm down now.
Open up your favorite memory seeker, and search for the value "6" (make sure that
indeed you have 6 bullets). After the search is done, shoot away one bullet, and
search for 5 now. Perform this usual drill until you have ONE memory address.
It should be 009A3EFC. If you will poke any value you want to this address, it WI
affect the bullet number, but we want to freeze it don't we?
Get back into the game, and load SoftICE (Control+D). Now we will set a Breakpoin
on Memory Address (BPM). When you set a BPM, SoftICE will break whenever the memo
address that we specified was ACCESSED. For example:
Why do we need to specify sizes? Well, I usally don't specify size, BUT it may ge
useful. Say we have the address 111, and it holds our money, which is in many cas
a big value. If this value is a DWORD (4 bytes), then the address will be 'spread
on 4 bytes, that is: 111, 112, 113, 114. So if we BPMD (BPM Dword) on 111, it wil
detect any access to one of the four addresses specified.
We also have BPM Permissions:
R - Break if the address was READ
W - Break if something was WRITTEN into the address
RW - Break if both Read and Write access happend on the address.
X - Break if the address was executed (Eqivalent to BPX)
So let's figure out what we need. We don't know whether this address is B/W/D so
will use plain BPM, BUT, we know that we need WRITE permission (whenever this add
gets updated with the correct value), so enter this command in SoftICE:
BPM 9A3EFC W
Get out of SoftICE (Control+D) again, and shoot another time. SoftICE should now
and you should see this code:
So, from observing the code, we see that the number of bullets is DECresed by one
and then it is being written again to the address.
So, what can we do in order to freeze the bullets? Remember that neat little comm
called NOP? We can replace that DEC with NOP! This way, whenever the processor wi
reach this line, he will simply move to the next command, without decreasing anyt
We see that the memory LOCATION of the DEC EAX is in 00414AC3. So, in order to pa
it, simply type in SoftICE the following command:
A 414AC3 <ENTER>
NOP <ENTER>
<ESCAPE>
You will see that the DEC changes into a NOP, and that 48 is changed into 90. Tho
are the HEXADECIMAL Representations of the instructions and those are called OPCO
I think that it is a short name for OPeration-Codes.
Clear all your Breakpoints (BC *), and get back into the game (Control+D). Shoot
bullets, and you will that it doesn't decrease anymore! Nice eh?
By the way, I always like to seek other solutions to the same problem, so lets se
we can find any other ways to patch the game, so it will freeze the bullets.
After the number of bullets was decreased, we see this command:
00414AC4 66 89 46 1C mov word ptr [esi+1C], ax
This is the actual instruction that writes the value back into the address. as yo
see, it is 4 opcodes long (which means it is 4 bytes long), so we can replace tho
four opcodes with 4 NOPs. Also, a nice idea would be to write a fixed value into
address. What do you mean fixed value? What if we will replace that line of code
this line of code:
mov BYTE ptr [esi+1C], 6
^^^^ ^
It will always write the value 6 into the bullet address, no matter what operatio
were performed on it!
There are many nice solutions available! Be creative... just study the flow of th
code, and you will see how many possibilities you have in store.
Life
----
OK, I won't explain this thing again, so just find the value of life the way we
found the value of bullets. If you did everything alright, you should have found
the address 9A3EE8. Now, Poke some value into it (say, 8), and get back to the
game. Nothing happens. The poking did not affect the value of lives... why?
In order to find out, we must set a breakpoint again, and study the code... so
the breakpoint should be:
BPM 9A3EE8 W
So, from examining the code, we can see that the address that the actual memory
address that holds the value of the life is [ESI+6].
In SoftICE, do this:
? ESI+8 <ENTER>
And you will get this:
009A3EE8 0010108648 "š>è"
ESI+8 is the address that we found! So, let's see what's inside ESI+6:
D ESI+6 <ENTER>
you will see this, in the data window:
OK, I figured it out... The game takes the value in 9A3EE6, and then puts
it again inside 9A3EE8. So in order to find the decrementing routine, we
should set a BPM on 9A3EE6. Clear all breakpoints (BC *), and set a new one:
BPM 9A3EE6 W
Get out of SoftICE, and get hit once. You will be in this location:
00415429 66FF8AE63E9A00 dec word ptr [edx+009A3EE6]
00415430 8D82E63E9A00 lea eax, dword ptr [edx+009A3EE6] ; You land here
Wow! Did you see this! We found the DEC instruction that controls the value
of lives! OK, we see it takes 7 bytes, so we just put 7 nops instead of this
instruction. In SoftICE do this:
A 415429 <ENTER>
NOP <ENTER>
NOP <ENTER>
NOP <ENTER>
NOP <ENTER>
NOP <ENTER>
NOP <ENTER>
NOP <ENTER>
<ESCAPE>
Clear all Breakpoints (BC*), and get back to the game... get hit again by one
of those dead people, and BOOM! The lives did NOT DECREASE! Success!
End
---
Whew... I enjoyed writing this text... I hope everything was clear for you.
In case it wasn't, don't hesitate mailing me, or coming to the EFNet IRC channel
#gamehacking, join us and IDLE :)
Greetz:
[SHEEP], calligula, Keyboard Junky, jmp_fce4, MacDeath, and all the other people
from #gamehacking, and all the people I forgot, sorry... :(
/\
____/__\____
\ / \ /
\/ \/
/\ /\
/__\____/__\
\ /
\/
when you find 1 of the codes such as X Spred or Speed for them to work in stats a
go into a game with your code such as speed we will use speed for this tut , 1st
code , go to Auto Hack at the top click and hit "enable debugger" ok now go to au
again and click "auto hack window"now the window is open right click on your code
auto hack now go into your game and turn speed on and use it for a sec , notice i
hack window the code is thier now highlight it and click "tmk" at the top and cho
script it will tell u what to put in TMK to make the code work
-------------------------------------------------------------
Introduction:
This mini-tutorial contains information to maximize the speed of your TSearch sea
Configuration:
Set the Max Address Show value to 100 (Learned from Mace/Sliderz)
Check the Fast Search and Freeze game during search check boxes.
Using the Refresh Rate slider set the refresh rate to about 1/4. Ex:
|||||||\/|||||||||||||||||||||||||||||||
Tips/Tricks:
A. Set TSearch hotkeys so you do not have to minimize from the game constantly.
Click the scroll right arrow in the top right corner until you see the hotkey tab
On the Search frame click the icon that looks like a white piece of paper to crea
BATTLEFIELD 1942 SPECIFIC: Use console command (I highly recommend Saida's consol
Or
D. You can run t-search with networking option. This enables you to run your game
part 2
if the code still doesnt work try setting a break point by useing auto hack
and clicking at the top where it says "edit" (this is in the auto hack
window) and click set break point now a window will pop up just type in the
code and press ok thats it you just set a break point
NOTE: This quick and easy tutorial will show you how to defeat basic DMA using TS
- Open Process
- Init new search (magnifying glass)
- Select type of search
- Type value your searching for
- Select size (byte, float, double)
- Click ok
TSearch AutoHack
Once you find the value you were looking for click the address in the table on th
Now that you have the address in the table on the right, select the menu item Aut
Right click on the address in the table on the right and select AutoHack from the
TSearch is now watching the address you AutoHacked for any changes.
Now go back to the game and do something that would change the value at the addre
For instance if you AutoHacked the address for Ammo, shoot the gun a few times.
Now that you have changed the value at the address you AutoHacked, you can go bac
If you shot a bullet, TSearch prolly found the decreaser. If you got ammo or relo
If you simply want to NOP (No operation) the found addy(s) in the AutoHack window
Whatever you selected is now patched or NOP. If you patched the decreaser your am
If you want to know what to put in TMK, select the addy in the AutoHack window, a
-TSearch tutorial by XaZ/GorgnutHi, all this is my first tutorial.
Lets say you have 100 health in a game. Remember that, or write it down.
Now, switch to TSearch using ALT-TAB in game. In Tsearch, click the "Open Process
Now you will see a list of allthe process (programs, games etc etc).
Now double click on your games process (i.e sof2.exe, starcraft.exe etc etc).
Now your process is loaded in TSearch. Now remember the value of your Life/gold/a
Click the search buttonbelow the "Open Process" button (the button looks like a b
Now, write in the value of that you wrote down. Thenfrom the list select "Exact V
Now TSearch is finding all the memory adresses with the value youentered.
It can find up to some millions of memory adresses with that value.
So how do we know which one of these memory adress is ours? Hold on and i will te
Now go back into the game and fire a bullet or loose some life or build something
Do somthing that effect your value!When you done that, switch back to TSearch and
Now from the list where you choosed "Exact Value" select Has Decreased or Has Inc
Now click ok.
Now it will searchfor all values that where decreased from last time you searched
Now do thisprocess a couple of times untill you only have like 2-3 results.
Good, you have the 2-3 results now? Then read on... Select the adress that was fo
This will add the adresses to an other list, just beside theother one.
Now to freeze this value, click in the little box on adress that you want to free
Go back to the game andVoila!
Your ammo/gold/life should be freezed!Thats all for now!
If you got any problem, want to give me feedback etc etc,
please e-mail me at gorgnuts@extalia.com
Tune in for my other tutorial "Hacking DMA with TSearch" which i will do soon :)
Until then have fun and hack on :)
Hacking Minesweeper with Omni Trainer v 1.0
Hi there guys it's me again and this time with an tutorial on hacking
Minesweeper of Win 98! I know...its easy, but i like this game 'cause i'll
show how to use Omni Trainer and its a new tool ;)
Needed Tools :
» Any Game (i'll use Minesweeper)
» The OMNI TRAINER v 1.0 - get in www.omnitrainer.cjb.net
» Some Coke, Fanta or Coofe (hmm... I like coke, he he he....)
» Some music , of course....like Rock or Eletronic Music :)
» Do u have a brain, right?
1. Open Minesweeper.
2. Open the Minesweeper process in Omni Trainer. You can do this by using
the Process / Open Process menu command. Now, scroll down until you find
a process with the window title "Minesweeper". Select it and then click
OK.
4. Search for the Seconds Address. Click the Search button. To find the
second address we perform a single out search; we will continue to search
for the seconds value until we have found a single address (the address of
the seconds value). Since the timer can range from 0 to 999 we should be
safe by searching for the DWord data type since most game use the DWord
data type for all their numeric data. Select DWord in the Type combo box. A
Forward-Normal search will work just fine. The seconds value in
Minesweeper should currently be zero, so type "0" in the search text box and
click search. Omni Trainer indicates that a search for zero is not
recommended. An initial search for zero usually returns too many values and
can lead to errors. Click No and change the seconds value to a number other
than zero by playing Minesweeper and losing. Back at the search dialog,
enter the seconds value that is currently shown in Minesweeper, and click
Search. A large number of values will appear in the Addresses Found List,
but we want only one. In the Search Again field, retype the seconds value
and click Search Again. Notice that the number of addresses found either
changed very little, or not at all. This is because some values may not
change in a program unless the user activly using the program. Play
minesweeper again and lose at a different time than before. Enter the new
second value in the Search Again text box and click Search Again. The
number of addresses found should reduce significantly. Continue this until
only one value is in the Addresses Found list. Note: If you encounter
problems just restart your search. Double-click the one address to select it
so that it appears in the Addresses Selected list, then click OK.
5. Check the Address. You should make sure that the seconds address you
found is correct by returning to Minesweeper, starting a new game (but do
not click anything) and then returning to Omni Trainer and pressing the
Update button on the New Location dialog. The current value text box
should read "0". If not, go back and repeat the search.
6. Set the Modify Value and the Refresh Time. Since you want to get the
lowest time possible in Minesweeper, type "0" into the Modify Value field.
However, if you use a refresh time of zero, you would have to keep enabling
the location to a low seconds value since a Refresh time of zero only writes
the location once. Therefore, you will want to change the Refresh field. The
refresh rate is measured in milliseconds, so change the value to "1000" to
make it refresh every second.
7. Personalize the Location with a Label and Info. You may want to label
this location for quick reference. Change the Label field to "Seconds". Then,
add a more detailed description in the Info field and click OK.
8. Enable the Location. Double-click the location you just created to enable
it. Play Minesweeper, and notice that your time remains at one. This
demonstrates that when you change a value, it is not immediately noticeable
because values are only shown when they are updated in the application.
The time, for example, is only updated when it is incremented. Since Omni
Trainer modifies it to zero, its first update occurs when Minesweeper
increments the value to 1. Therefore 1 is shown.
9. Saving your Location List. To save your newly created location list use
the LocationèSave Location List menu command. This displays the Save
Location List dialog. First, type "Minesweeper Tutorual" in to the Location
List field. Some programs have different versions, while others only work
on specific operating systems. For Minesweeper, type your Operating
System name in the Version Info text box. Then, pat yourself on the back.
You have just completed the Omni Trainer Basic Tutorial!
Tutorial by [D.N.A]
The East KidZ (c) 2002
contact : dna.netz@ig.com.br or dna@tsongkie.com
web: www.vngamecenter.com
transparent trainer using game trainer studio
tools:
gts
any photo editor (i'm using adobe photoshop)
okay, this tuts will explain how to make a transparent trainer using GTS.
first of all, open up your photo editor and draw your trainer bitmap.
please make sure that your bitmap's background color are different from any other color on your trainer bitmap.
i'm using white as background color. you might ask "why?" :) i'll explain it later. when you done with your bitmap,
save it as *.bmp
format file. i named it as trpic.bmp.
okay, we're here. now, open up your GTS and make a new trainer project.
now, right click on the trainer dialog, choose trainer setting. trainer setting box will open up. go to bitmap tab.
1 - choose your bitmap. remember our bitmap name? yes, its trpic.bmp. click on 'choose bitmap',
find where our bitmap is and choose it.
2 - now, we will create RGN file for our trainer. click on 'create rgn file' and you'll be here.
okay. click on 'browse' and choose our bitmap, trpic.bmp and open. now click on 'pick' and right click on white
area.
that why i told you to use a different background color for our trainer bitmap. rgn meant 'region' and in this
case,
white is a our trainer region. click ok. then click on 'create', give your rgn file a name. i'm using trrgn.rgn
3 - now you'll choose the rgn file you've make, trrgn.rgn. click on 'choose rgn file', find your rgn file and click open.
greets
Bie, a_jaxxx, divine shadow, all gamehacker around the world - you know who you are.
tutorial witten by
hotfloppy
hotfloppy@malaysia.com
hotfloppy.cjb.net
- do not eat -
|- TUTORIAL BEGIN HERE -|
Cya,
[D.N.A]
WIN32 - Inside Debug API
------------------------
(Things you need to know: the mysterious CONTEXT structure)
I'm very proud that my previous work "Tweaking with memory in Windows 95" was go
enough to open a new section ,"+HCU's PAPERS", at Reverser's.That's very stimulat
back! I hope that will be many other contributors to this section.Let's bring lig
shadows!
BTW, Reverser ,I really like the picture for your new section.I'm with you boys,
and forever!And one more thing:for now one I will send you my essays in .htm for
plain text files!
In this document I will focus on Debug API functions.I think that it is an
interesting chapter,who worth a closer lock.
Note:In order to use those functions in Windows NT your user must have debug
privileges access right granted.I don't know for sure but it seems that NT does n
this for default to administrators.
I have started to work on part two of "Tweaking with memory in Windows 95" this
time I want to present a VxD aprroach.It's nice to write self-modifying code usin
trick(Make code section read-write at link time).But wouldn't be nicer to relay o
to tweak with memory leaving that damned section write protected and without ANY
calls to functions like VirtualProtect? The target will be this time the virtual
itself.Anyone out there who could HELP?.
=================================================================================
A good WIN32 API reference for future reference is OK.I don't explain here all
the parameters those functions take, nor all structures.But for now,let's see the
ContinueDebugEvent
DebugActiveProcess
DebugBreak
FatalExit
FlushInstructionCache
GetThreadContext
GetThreadSelectorEntry
IsDebuggerPresent
OutputDebugString
ReadProcessMemory
IsDebuggerPresent
SetThreadContext
WaitForDebugEvent
WriteProcessMemory
DebugActiveProcess
------------------
BOOL DebugActiveProcess(
DWORD dwProcessId
);
Parameters:
WaitForDebugEvent
-----------------
This function allow the debugger to wait until a debug event heapens
in target process.
BOOL WaitForDebugEvent(
LPDEBUG_EVENT lpDebugEvent,
DWORD dwMilliseconds
);
Parameters:
LPDEBUG_EVENT lpDebugEvent: Pointer to a DEBUG_EVENT type structure.
This struct will receive info about the
debug event trapped.
DWORD dwMilliseconds: Number of ms. to wait.Could be INFINITE.
If it is INFINITE WaitForDebugEvent does
not return until a debug event occurs.
ContinueDebugEvent
------------------
This function allow the debugger to resume a thread that previously raised a
debug event.
BOOL ContinueDebugEvent(
DWORD dwProcessId,
DWORD dwThreadId,
DWORD dwContinueStatus
);
Parameters:
Debug Break
----------
This function causes a breakpoint in current process.
VOID DebugBreak(VOID);
FatalExit
---------
This function force the exit of caller process,transferring execution to debugg
VOID FatalExit(
int ExitCode
);
Parameters:
int ExitCode : Exit code
BOOL GetThreadContext(
HANDLE hThread,
LPCONTEXT lpContext
);
BOOL SetThreadContext(
HANDLE hThread,
CONST CONTEXT *lpContext
);
Parameters:
HANDLE hThread: A handle to thread whose context is being read
or set.
LPCONTEXT lpContext: Pointer to a CONTEXT structure to receive /set
context info.
GetThreadSelectorEntry
----------------------
The GetThreadSelectorEntry function retrieves a descriptor table entry for
the specified selector and thread.
BOOL GetThreadSelectorEntry(
HANDLE hThread,
DWORD dwSelector,
LPLDT_ENTRY lpSelectorEntry
);
Parameters:
HANDLE hThread: A handle to thread containing specified
selector.
DWORD dwSelector: Selector Number
LPLDT_ENTRY lpSelectorEntry Pointer to a structure that receiv
descriptor table.
=================================================================================
Chapter2:Debug events.
----------------------
From Debug API functions point of view a debug events is an object used to commu
with the debugger.When a debug event occurs in target process the OS inform the d
this.The debugger use WaitForDebugEvent to retrieve info about the event that occ
process(See chapter 5).Following debug events exists:
1.CREATE_PROCESS_DEBUG_EVENT & EXIT_PROCESS_DEBUG_EVENT raised every time than a
process is created/destroyd by the process being debugged.
2.CREATE_THREAD_DEBUG_EVENT & EXIT_CREATE_THREAD_DEBUG_EVENT raised whenever a n
thread object is created/destroyed by the process being debugged.
3.LOAD_DLL_DEBUG_EVENT & UNLOAD_DLL_DEBUG_EVENT generated whenever the target lo
unloads a dll.
4.OUTPUT_DEBUG_STRING_EVENT generated than target calls OutputDebugString.
5.EXCEPTION_DEBUG_EVENT generated when an exception occurs in target process.Thi
include breakpoint instructions such INT 3 , DivideOverflow .....
6.RIP_DEBUG_EVENT generated when a RIP exception occurs.
WaitForDebugEvent receives the debug event and returns information about the eve
in a DEBUG_EVENT structure.This structure is defined as below in WIN32 AP:
=================================================================================
In this short chapter I present you how to create a process for being debugged,o
how to attach to an already running process.
=================================================================================
A minimum skeleton for using Debug API function is easy to implement.All you hav
do is to create a process for being debugged and the implement code to watch for
I call the part responsible with watching debug events "The Main Loop".Why?Becaus
simple to implement as a While loop.The functions you have to use for this are
WaitForDebugEvent - ContinueDebugEvent. As we have seen before WaitForDebugEvent
certain amount of time for a debug event to occur in target process.If a debug ev
occur in this time the function times-out and return FALSE. If a debug events occ
this function return TRUE,fill a DEBUG_EVENT type structure with info about even
freeze the thread in witch the debug event ocurred.The programmer is responsible
event type checking and take appropriate meassures.After the specific code for ha
event is executed we have to use ContinueDebugEvent to resume thread execution an
other events to occure.Another thing to worry: the only thread witch is allowed t
WaitForDebugEvent is the thread who created or attached to target process.So let'
code:
PROCESS_INFORMATION pi;
STARTUP_INFO si;
DEBUG_EVENT devent;
if(CreateProcess( 0 , "target.exe" , 0 , 0 ,FALSE ,DEBUG_ONLY_THIS_PROCESS , 0 ,
&si , &pi))
while(TRUE)
{
{
if (WaitForDebugEvent( &devent , 150)) // wait 150 ms for debug event
{
switch(devent.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
// your handler here
break;
case EXIT_PROCESS_DEBUG_EVENT:
// your handler here
break;
case EXCEPTION_DEBUG_EVENT:
// your handler here
break;
}
ContinueDebugEvent(devent.dwProcessId , devent.dwThreadId , DBG_CONTINUE);
else
{
// other operations
}
}
} // while end here
else
{
MessageBox(0,"Unexpected load error","Fatal Error" ,MB_OK);
}
=================================================================================
In previous example we can see that how we can trap debug events and take approp
actions using case/switch C /C++ statements.Each debug event has a personal handl
gets executed when corresponding debug event occurs.More information about the de
can be found in union u member of DEBUG_EVENT.As a example let's the structure co
to EXCEPTION_DEBUG_EVENT.I choose this because encountering breakpoints and traci
code generates an exception debug event.See a API reference for other events.
Using the information from those structures we can find all we need.We can retri
the thread there exception occurred , type of exception , if we can continue exec
the address where exception occurred and others.
Note that trying to continue a EXCEPTION_NONCONTINUABLE exception type will
generate a EXCEPTION_NONCONTINUABLE_EXCEPTION exception.
Currently used exceptions are EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP.The
first exception is raised on a breakpoint hit, the seconds signalizes that trace
signals that one instruction has been executed.
Using a similar mechanism you can gather information about threads , dll's used
by running process and other things.
=================================================================================
I really enjoyed writing this chapter.All others are things easy to figure out.D
scare it not really difficult to understand what's going on in this chapter.Befor
those two functions and their use I want to remember some basic things about proc
threads.
In WIN32 philosophy a process is a object who has an private address space , cod
data , and a primary thread.Each process has at the very beginning only one threa
primary thread we can later create other threads which run in the same address sp
to the popularly belief a process does NOT execute any kind of code.The threads a
who executes the code.The thread objects share the same address space and resourc
have individual contexts.What means that? Windows95 and WindowsNT are multitaskin
multithread operating systems.The OS seems to run all threads in the same time ,
not true. Every individual thread is scheduled for execution for a short time , a
OS save the thread state in a structure called CONTEXT structure and goes for the
The information saved in this structure represents the thread context and is form
- threads machine registers (CPU registers)
- the kernel stack and the user stack address
- thread environment block address.
The the OS encounter again our thread it restores it's context info from associa
structures and resume execution like nothing happened.
Ok,so let's see the CONTEXT structure.Unfortunately seems that Microsoft does no
include info about this structure API help files. The structure is documented at
in winnt.h header file in Watcom compilers(can be elsewhere in others.Keep lookin
mind that this structure is hardware dependent so expect different implementation
x86 , Alpha...
} CONTEXT;
Now let's take a deep breath.We are almost through.As usually I want to present
you an interesting trick.Let's inject some code into another process address spac
how,but first let's talk about a little impediment.We need some committed memory
our brand new code.A VirtualAllocEx function was not provided in WIN95 API.It see
this one along with it's companion VirtualFreeEx exists under NT.
If our code is very little we can use the space provided by our compilers: The MS
the PE files,copyright strings or even unnecessary data strings(I dont care too m
About the program says that it was developed by "!^$##@*^$f76").Another method is
save a code page of target process , overwrite with new code , execute new code ,
code page.Let's see this step by step.
If we need that our resides in target process address space at the same tim
original code,and our code is BIG we have to commit some memory in the target pro
space.The code to call VirtuallAlloc is very small,so use previous method to call
in the context of the target process.This will commit memory in target's address
return a pointer to it.Several kb should be more than enough,so don't be a fool a
to commit cosmic values like 10 Mb.I wonder if there is another method to impleme
VirtualAllocEx under WIN95.I keep looking.Anyone now if VirtualAllocEx is impleme
in Memphis(future Windows 98)?.
If you ever need to convert a segment relative address in linear virtual ad
can use GetThreadSelectorEntry.
Final words: !!WATCH!! the stack.DON'T mess IT.If you do , you will be sorr
=================================================================================
Chapter7.Notes
--------------
1.Any corrections and additions are wellcomed.Please append them at the end of t
document and also include your name (or your nickname ).Slightly editing minor mi
typos is admitted in-place and without notice.
melted MeltICE
(SoftIce 3.xx detection and another lesson for shareware programmers)
by Frog's Print
Well, Frog's Print finding are indeed interesting. I'm pretty sure that we are go
Note that since the programmers keep programming in "high" languages, all this ca
1) Use Visual Basic made protections;
2) Use ready-made third party protections (if the people selling them
would put their money where their mouths are you would see many more
working demos of their protections on the net, btw);
3) Use Visual C++ made protections;
Write your own small protections routines in assembler using some forgotten dos c
Well here you go: Meltice melted away under the touch of Frog's Print...
--------------------------------------------------------------------------------
MeltICE
(SoftIce 3.xx detection)
by Frog's Print
How it works:
The program will open the VxD driver named SICE (Windows 95) or NTICE (for Window
with CreateFile. It will then check the file's Handle (in EAX) in order to see if
SoftIce Win95 or WinNT is loaded or not.
Below are the source code of MeltICE and a disassembly listing that I did with W3
of an .exe file compiled with this code:
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
BOOL IsSoftIceNTLoaded()
{
HANDLE hFile;
int main(void)
{
if( IsSoftIce95Loaded() )
printf("SoftICE for Windows 95 is active!\n");
else if( IsSoftIceNTLoaded() )
printf("SoftICE for Windows NT is active!\n");
else
printf("Can't find SoftICE with this method!\n");
return 0;
} And now, the Dead Listing of an .exe file using that code:
********************************End of detection********************************
* Possible StringData Ref from Data Obj ->"\\.\SICE" ; VxD driver for S-Ice Win95
:00401012 6830604000 push 00406030
* Possible StringData Ref from Data Obj ->"\\.\NTICE"; VxD driver for S-Ice WinNT
:00401052 683C604000 push 0040603C
OK, we see that this new simple and 'ready-to-use' protection will probably pleas
a huge amount of unexperimented shareware programmers. Since it is available at
Windows95.com, I assume we may have to face it very soon.
But is S-T-U-P-I-D because we now will be able to check if any program is detecti
Soft-Ice even before it will have the time to do so: just with a BPX CreateFile(A
Anyway, this will make shareware crackers a little bit easier about the safety of
the software they want to reverse engineer too.
Just replace the string "SICE" with "KICE" (or whatever you want) in the files
"Winice.exe" and "nmtrans.dll"
(Please do not use "KICE" ,just use a unique string... cause those MeltedICE
people may update it by checking for "KICE" too :)
You can check the VxD names with many tools.. (Infospy for example)
This goes for win95 version and i guess would work for NT too..
(although for NT you have to recalculate the checksums as in +HCU Project 2)
Later
Kox
Anti-Debugging & Software Protection Advice
Detecting SoftICE - Protecting your Software
As an author you can clearly see that virtually every serious cracker/reverse engineer will use a
debugger or disassembler of sorts to break your application, of those tools out there I'll wager a
substantial amount that SoftICE is the "debugger of choice". Modern day programmers have still not
really caught up with "crackers", maybe they just consider it a wasted cause?, or perhaps their desire
to roll out their latest software overrides any desire to protect. At any rate, with the progression of
commercial wrapper schemes e.g. VBox, I think a list of the most common tricks encountered by
reversers would be useful for both communities.
Most of these tricks require implementation in Assembly language, evidently that isn't a problem if
you are familiar with in-line ASM coding in your compiler environment (sadly many HLL
programmers are not). Most of these examples are designed to thwart SoftICE users (virtually all of
the existing documents on the web describe tricks which would have been useful in the days of DOS
Debug/Turbo Debug but are happily traced by SoftICE).
Bear in mind that the use of these techniques will only add time to a crackers progress if he/she
doesn't actually realise the debugger has been detected (use at least 2 techniques to make sure you
aren't penalising legitamate users and don't show friendly message boxes like VBox's "Debugger
Detected, please remove me screen"). Hidden detection can work very well if used in shareware key
generation schemes, set a discrete flag and then send the would-be cracker to a routine that requires
hours of analysis time for no result, eventually time is money for the best reverse engineers.
1. - Using the API function CreateFileA to check for the presence of the SoftICE vxd/sys device
(//./SICE, //./SIWDEBUG, //./NTICE in Windows NT). This method is now very well known,
although you could try using _lread() instead (ASProtect).
Bypass by bpx CreateFileA (change API result) or HEX edit the strings from the detection or patch
your nmtrans.dll / Winice.exe against them. (Seen in Advanced Disk Catalog v1.16, MeltICE,
Hardlock/HASP envelope).
This detection pushes 002A002A as a parameter, the high 2A means we are calling VWIN_32 vxd,
the low 2A the INT 41 dispatch service. Bypass with bpint 30 if ax==0xF386 and clear AX,
described in Matt Pietrek's legendary book.
3. - Issue commands to SoftICE. This was one detection I uncovered whilst running an installation
program protected by a Hardlock dongle (HASP wrappers also use it). I had inadvertently enabled
INT 3's with SoftICE's I3HERE toggle.
:? 4647
00004647 0000017991 "FG" <-- Magic Val. 1.
:? 4A4D
00004A4D 0000019021 "JM" <-- Magic Val. 2.
Evidently there are several easy ways to beat this, changing SoftICE's magic values is one option (as
described by The_Owl), another would be editing DI/SI or modifying the string at DX, you could also
just NOP the INT 3 altogether, this detection routine works with varying levels of success. Other
subfunctions exist (0912h, 0913h & 0914h) which can be used to manipulate SoftICE breakpoints.
Another set of magic values are also known ('BCHK'), this is the documented BoundsChecker
interface, if you place BCHK into EBP and set EAX=4 calling INT 3 will return AL=0 in the
presence of Winice (works in Windows).
MOV EBP, 04243484Bh <-- 'BCHK'.
MOV AX, 4h
INT 3 <-- Trap debugger.
CMP AL, 4
JNZ SoftICE_is_here
4. - Using NuMega's own functions. This requires the use of nmtrans.dll but may well appeal to HLL
programmers who aren't keen on using in-line ASM. The idea is to call DevIO_ConnectToSoftICE
and verify the functions return value before taking appropriate action. Sadly this method is based
heavily on CreateFileA (although a small amount of work could change that), hence in its current form
it could easily be found. Looking through some of the other exports from nmtrans.dll I reckon a sneaky
programmer could use some of the other exports.
Get the Interrupt Descriptor Table (IDT) with the SIDT command.
Get the address of Interrupt gate 1.
Move 16 bytes back.
Check if byte is 1Eh - if so SoftICE is running.
SIDT FWORD PTR opIDT <-- Store IDT.
MOV EAX, DWORD PTR [opIDT+2] <-- EAX=IDT.
ADD EAX, 8h <-- EAX has INT 1 vector.
MOV EBX, [EAX] <-- EBX=INT 1 vector.
ADD EAX, 16h <-- EAX points at INT 3 vector.
MOV EAX, [EAX] <-- Get EAX=INT 3 vector.
AND EAX, 0FFFFh
AND EBX, 0FFFFh <-- Remove selectors.
SUB EAX, EBX <-- Find displacement.
CMP EAX, 01Eh
JZ SoftICE_3.0_is_running
6. - Detect SoftICE VxD or SoftICE GFX VxD (obviously ineffective under NT).
The GFX id code is identical to that shown above except AX=1684h & BX=7A5Fh.
8. - Detect and crash SoftICE with an illegal form of the instruction CMPXCHG8B (LOCK prefix) -
opcode: F0 0F C7 C8.
10. - Using the control or debug registers - I remember reading somewhere (perhaps in a fairly old
Anti-debugging FAQ) that SoftICE doesn't handle the control or debug registers very well or not at all
in the case of CR4, try DR4 and above too - a little something for you to play with me thinks :-).
SoftICE View:
xxxx: xxxx
EB01: JMP $+1
E8xxxxxxxx: CALL bad
TRW (not affected):
xxxx: xxxx
EB01E8: NOP
xxxx: xxxx
12. Calling the Windows function IsDebuggerPresent() (exported from kernel32.dll), returns non-zero
in the presence of a debugger, implemented only under NT so not a great trick on its own. A few
reversers have already patched their kernel32's against this one.
14. Using a timer to check the execution speed of a routine can be an effective way of detecting
debuggers, under single step analysis the routine will run much slower, how you choose to react of
course is down to your own ingenuity.
15. Check if a potential cracker has set breakpoints on key API functions :-
LEA ESI, GetDlgItemTextA
CALL CheckForSoftICEBP
CMP EAX, "xxxx" <-- Substitute for your own identifier.
JE SoftICEBPIsSet <-- Send bad cracker to some really horrid routine.
CALL ESI
CheckForSoftICEBP:
PUSH ESI
PUSH DS
PUSH CS
POP DS
MOV ESI, [ESI+2] <-- Get dll function jmp address.
MOV ESI, [ESI] <-- Get dll function real address.
MOV EAX, ESI <-- Get first dword of dll function.
AND EAX, 0FFh <-- Use only first byte.
CMP AL, 0CCh <-- INT 3 ?.
MOV EAX, 'xxxx' <-- Your identifier.
JE BPXSet
XOR EAX, EAX <-- No BPX.
BPXSet:
POP DS
POP ESI
RET
This sadly won't detect the clever cracker who routinely sets breakpoints such as 'bpmb
GetDlgItemTextA x'.
16. Exploit a W32Dasm bug (this probably won't keep IDA users out but will at least stop the real
StringRef crackers which make up the majority).
00401000 JMP 00401005
.
.
.
.
00401005 JMP 00401000
It seems that if this code is placed in a zone that doesn't mess with code flow, it will put W32Dasm in
a memory-consuming -> crashing loop.
Other Resources
Preventing the wide scale distribution of cracks for your program can actually be a worthwhile
exercise, use a search string such as "warez + crack + your application name" in AltaVista and
several of the other engines and you'll probably be able to find out if and where a crack exists for
your software. Remember that most 'crack' sites are operated by bored teenagers and hosted on
anonymous free space providers, most of these have Piracy@ e-mail addresses that will remove the
offending site within a day or 2, just devise your own 'piracy e-mail letter' and send them off at the
click of a button.
Below you'll find a collection of protection tips, these won't make your program bullet proof but
should waste a crackers time if nothing else, if you want more details regarding implementation drop
me an e-mail.
2. When writing your protections functions try to avoid using very obvious names like these that I've
seen - (Auth_Check(), FindDK47(), IsValidSerialNumber() ). Instead frustrate crackers by using less
intuitive even misleading names, further minor irritation can be achieved by using very long names
with @ symbols, and never place your entire protection inside a single dll.
3. Avoid issuing helpful message boxes period, and avoid "Thanks for registering" ones as well, most
legitimate users will type their serial numbers correctly first time, as an example, I give you the latest
version of 3D Studio Max, very expensive software, and reverse engineered by me in under 5 minutes
because of a message box.
4. If you must track registered status using the registry use several keys and don't use names like
"MySoftwareKey', instead use some sort of encryption to decode them. If you decide to use a file
based protection, avoid using *.ini and *.reg, use something like *.sys and *.vxd and make sure they
are of credible length and name.
6. Forget about protecting using runtime-limits or 30 day trials, these are too easy to crack, cmp eax,
1E - jg times_up. If you must use this means have the program disable itself completely perhaps
by deleting critical files.
7. Many crackers struggle with applications written in Visual Basic and Delphi, primarily because
the run-time dll's are a mass of spaghetti code which makes isolating your protection more difficult, in
some cases it can make patching virtually impossible. If you must use these languages, make several
checks and don't use __VbaStrCmp, hyphenated serial numbers like xxx-xxx-xxx-xxx-xxx make for
painful reversing. FPU maths (FCOS, FSIN) are also effective. If you use VB always compile your
final product to p-code.
8. Bore potential crackers to death with fake routines using lots of maths and fake checks. Force them
to work back through your mass of maths (all to no avail). Mix your flags, in function 1 use return 1
for good and then in function 2 use return 0 as good, this will prevent crackers from heuristically
reversing jumps.
9. Save disabling your target?, don't just grey the menu item, take out the code completely and don't
provide helpful documents detailing the precise specification of the file format.
10. Use encryption of any description, even just simple sliding XOR can add hours to a crackers
progress. Consider using arrays of random characters for code calculation routines.
11. Use CRC checks to ensure that key sections of your program have not been modified, its not a
good idea to CRC the entire file for performance and vulnerability reasons, when you find a CRC
error be aware this could be due to virus tampering.
12. ...And finally, invest the money and buy a copy of SoftICE, then attempt to reverse engineer your
own software or ask web crackers to try their hands. Make changes at ASM level if necessary and
strengthen your protection. The longer it takes you to protect, the longer it will take a cracker to de-
protect.
Whilst no protection will ever be completely cracker proof, treat software protecting like you treat
your car (or any other prized possession), if you can implement enough deterrents most thieves will
find an easier target.
I'd really like to add more advice, so if you want to post me a small text file I'll certainly add it here.
www.gamehacking.com
Introduction
In the recent days where assembly language is becoming obsolete in
means of application development, it is hard to find decent
references and tutorials on assembly language. Out of the very few
documents and books you will find on assembly language these days,
most of them focus on assemblers and programming. In contrast, this
document will focus on debugging.
This paper is already long enough as is, if I added every little detail I
could make this an entire book. I suggest you buy a book on assembly
language programming or find an online reference. You won’t need it
to read this tutorial, but after you finish this you should go back to all
the places where I said “consult reference” and read about the
details I missed with your reference. Although Art of Assembly
focuses on programming, I highly suggest that you use this for your
reference. I also suggest the book: “Computer Organization and
Assembly Language Programming” by Michael Thorne
Tool Box
Like any other task, certain tools are required to get the job done.
We will not discuss how to use any of these tools, there are far too
many tutorials floating around the net for that. Here are some of the
programs that most reversers use:
Registers
Registers are places in the CPU where bits can be stored and
manipulated. Registers are divided into two different sections,
General Purpose Registers and Pointer (Index) Registers. GPRs can
each hold a 32bit value, while PIRs can hold a 16bit value. Only nine
registers are listed here, consult reference for more detailed
descriptions and for the rest of the registers.
The GPR registers can also be used as a 16bit register; to do this you
just take away the E.
For example:
32bit EAX can become 16bit AX
A 16bit GPR register can also be divided into two 8bit registers.
For example:
16bit AX becomes 8bit AH and 8bit AL
You can use the same rules for the other GPR registers; just replace
the A with the appropriate letter of the register.
EBX à BX à BH & BL
ECX à CX à CH & CL
EDX à DX à DH & DL
Flags
Like registers, flags also store values, but flags are slightly
different. They can only hold a BOOLEAN value, or a true/false value,
1 or 0. There are nine flags maybe more or less depending on what
version of x86 processor you have. Each has its own purpose. These
are the eight used in SoftICE; instead of boringly listing each and
giving a description, I will just list them. Consult reference for
descriptions and other flags.
Carry Flag
Parity Flag
Auxiliary Carry Flag
Zero Flag
Sign Flag
Interrupt Flag
Direction Flag
Flag
Basic Opcodes
Opcodes are the actual instructions that your processor carries out.
They can be anything from simply adding, to jumping to different
addresses in memory.
The first Opcode we will look at is ADD. You are probably blowing
your brain thinking of what it does…
In this particular operation, the values stored in EAX and EBX are
added, and the result is stored in EAX. When dealing with Opcodes,
destination is always first, and source is second.
The following Opcodes are used in the same syntax, but perform
different operations between their operands, what they do is self
explanatory if you are past kindergarten.
SUB
DIV
MUL
MOV: Move a value into a register, or copy the values of one register in the other.
Remember, when dealing with Opcodes, destination is ALWAYS first, and source is
second. The first example here moves the value 4 into EBX. The second example
copies the value of EBX into EAX, at the end of this particular operation; both of
these registers contain the same value.
Ex. MOV EBX, 4
Ex. MOV EAX, EBX
INC: Increment a value. If you know C++, it’s the same as ++, it adds
one.
Ex. INC EAX
The common metaphor for the stack is a pile of plates. It uses a last
in, first off logic, often referred to as LIFO. To add something to
the stack, the PUSH Opcode is used, to remove something, the POP
Opcode.
JMP
Ex. JMP H######
JA
JB
JAE
JBE
JNC
JG
JL
JGE
JLE
JO
JNO
JS
JNS
JPO
JPE
JCXZ
Buffer Overflows
Buffer Overflows are really beyond the scope of this tutorial; they
are quite complicated and usually won’t have any significance when
game hacking. I decided to put this section in here anyhow, just for
fun or if you want an introduction to exploits. A buffer overflow
occurs when the amount of data being written to memory is larger
than the amount of memory reserved for the operation. When that
occurs, the data being written actually gets written to memory beyond
the reserved section.
If you are familiar with C++ you probably already see the problem in
this, if you don’t know C++ it is still easy to see. Let me explain. There
are two variables declared here, name and buff. Buff is only allotted
10 bytes, but name is a lot more than 10 bytes long. When the
command strcopy is used to copy name into buff, a buffer overflow
occurs because name is too big to be stored in buff.
Hackers look for places where they can cause buffer overflows in
memory so they can do specific things, for example gaining root
access on a remote machine. This is known as exploiting vulnerability.
Vulnerabilities are extremely difficult to find, let alone exploit.
Conclusion
This tutorial covered a lot of assembly, but there is still a lot more
out there. Go out now, read some other documents, and expand your
knowledge of what you learned.
[PREFACE]
This is more of a programming tutorial then anything else, it will teach you how
on another process' window.This is a common method used in creating Stat hacks, w
how many resources each player has, and how many units, or max population, ..etc
other methods of creating a stat hack, but they involve tracking down the games o
function and that may be hard to find.
-------------------
[Windows API Calls]
-------------------
The FindWindow function retrieves a handle to the top-level window whose class na
name match the specified strings. This function does not search child windows.
does not perform a case-sensitive search.
The GetDC function retrieves a handle to a display device context (DC) for the cl
a specified window or for the entire screen. You can use the returned handle in s
functions to draw in the DC.
HDC GetDC(
HWND hWnd // handle to window
);
The SetBkMode function sets the background mix mode of the specified device conte
background mix mode is used with text, hatched brushes, and with non-solid pen
int SetBkMode(
HDC hdc,
int iBkMode
);
Parameters:
OPAQUE :Background is filled with the current background color before the te
hatched brush, or pen is drawn.
The SetTextColor function sets the text color for the specified device context to
specified color.
COLORREF SetTextColor(
HDC hdc, // handle to DC
COLORREF crColor // text color
);
The TextOut function writes a character string at the specified location, using t
selected font, background color, and text color.
BOOL TextOut(
HDC hdc, // handle to DC
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // character string
int cbString // number of characters
);
--------------
[The Function]
--------------
I've saved you the time in trying to do research and what not and gave you my Dra
Put it in a timer, and have the timer be very fast so that it can paint every f
prints RED text with a black drop shadow. You can change this by changing the
SetTextColor().
//PRINTS MY TEXT OVER THE BLACK TEXT IN RED, GIVES IT A DROP SHADOW APPEARANCE.
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,x,y, mybuffer,howmany);
UpdateWindow(gamewindowhandle);
ReleaseDC(gamewindowhandle,hdc);
}
-------
[Usage]
-------
char buff[255];
DrawMyText("Crimsonland",155,35,"Time: ",6);
or
DrawMyText("Crimsonland",155,35,buff,3);
Fourth is the buffer containing text, this could either be a string in between tw
a variable of type char.
[CONCLUSION]
I know I didn't really explain anything, all you need to know is that you need a
paint on a window. And you use TextOut to write text to a DC.
The only problem with this is that every frame that the game updates, it will o
and then you paint it again, so you will get a flickering effect. There is no wa
except to find the games own draw text routine. Alternatively, you could inject
value for gold in an address of your choice ( [0313370] for me ), and then if the
of text display (such as a score display board like in Age of Kings/Mythology)
locate the code and change it to PUSH the value inside of [0313370] rathe
of the score. Thus the game will display the value of gold in the place where the
^chaos^
idxchaos@hotmail.com
www.s-i-n.com/chaos/trainerology.htm
<~~greets~~>
[sheep], MiCRal, Archmage, MrNOP, Visual Perfection, MiraMax, cppdude.
#gamehacking on efnet
Razali Rambli a.k.a Bie Tutorial on
Disable Trainer Spy Protection in TMK Trainer Using Tsearch
Download at http://www.bie.cjb.net
******************************************************************************
This tutorial will show you how to use Tsearch to disable Trainer Spy
Protection in TMK Trainer.
Tools Use
=========
Tsearch
or
memory searcher of your choice.
We Begin!
-------------------------------------------------------------------------------
What is TMK?
-------------------------------------------------------------------------------
TMK or Trainer Maker Kit is a tool to create trainer without knowing any
programming language.
-------------------------------------------------------------------------------
What is Trainer Spy Protection?
-------------------------------------------------------------------------------
Trainer Spy Protection is a solution invented by Drakken to block Trainer Spy
for TMK made trainer.
Poke 0 FF 52 19 FF XX
so XX = 02
Poke 0 FF 52 19 FF 02
1. Run Protected Trainer, for example, let say the trainer have only 1 button
2. Run Tsearch & open process of the Protected Trainer
3. What value to search?
For this example, let say the trainer block 2 address on 1 button
Poke 0 FF 52 19 FF 02
FF 52 19 FF
So if the trainer have this code, thats mean the trainer is protected
But we cannot search for Hex value, we can only search Decimal value in
FF1952FF
But why the above code is in reversed? because usually in memory, the
You will see the value will be 2, because we use 2 address block
4. Change the value to 0, now the trainer block 0 address, that's mean we can
use Trainer Spy on that button.
-------------------------------------------------------------------------------
The End
-------------------------------------------------------------------------------
I hope this will help you
Razali Rambli aka Bie
http://bie.cjb.net
razali_bie@hotmail.com
Razali Rambli a.k.a Bie Tutorial on
Disable Trainer Spy Protection in TMK Trainer Using Hex Edit
Download at http://www.bie.cjb.net
******************************************************************************
This tutorial will show you how to use Ultraedit to disable Trainer Spy
Protection in TMK Trainer.
Tools Use
=========
Ultraedit http://www.ultraedit.com [Shareware]
or
hex editor of your choice.
We Begin!
-------------------------------------------------------------------------------
What is TMK?
-------------------------------------------------------------------------------
TMK or Trainer Maker Kit is a tool to create trainer without knowing any
programming language.
-------------------------------------------------------------------------------
What is Trainer Spy Protection?
-------------------------------------------------------------------------------
Trainer Spy Protection is a solution invented by Drakken to block Trainer Spy
for TMK made trainer.
Poke 0 FF 52 19 FF XX
so XX = 02
Poke 0 FF 52 19 FF 02
FF 52 19 FF
3. After you find it, look at the value on the right of "FF 52 19 FF"
4. If the trainer protect 2 poke address, the value should be
FF 52 19 FF 02
FF 52 19 FF 00
7. So although the trainer use the Protection, we just make it block 0 address
8. Thats mean Trainer Spy can show what & where the value is writen in memory
-------------------------------------------------------------------------------
The End
-------------------------------------------------------------------------------
Contents
What Trainer Spy does.
Detecting if Trainer Spy is running
Protecting trainers against Trainer Spy
Most Windows based trainers use a Windows API call named WriteProcessMemory to change values
in a target process. Trainer Spy monitors these calls and records the addresses and values used.
Having a tool like this can be useful when troubleshooting a newly programmed trainer. If the trainer
doesn’t work, or works incorrectly Trainer Spy will show exactly what address is being written to
and what value is being written there. It will show if either the address or value is wrong, or both,
making it easier to figure out what is going wrong.
Unfortunately while Trainer Spy allows trainer makers to easily debug their trainers, it also lets
anyone else monitor the same information. Any wannabee game hacker can ‘steal’ the addresses and
values from a trainer and release an identically working trainer claiming it as their own. While not
exactly a crisis, most people want to protect the addresses and values they spent so much time
obtaining.
There are a couple of ways to prevent Trainer Spy from loading. One way is during trainer
initialization use the CreateFile API call to create a ‘dummy’ file in c:\windows called Traspy.vxd.
As you can imagine this could be easily defeated, and if the trainer was loaded after Trainer Spy it
would have no effect at all until Trainer Spy was restarted. The code would look like the following:
A better scheme is to detect if Trainer Spy is currently running before each call to
WriteProcessMemory. There are several ways to do this.
1. The easiest way to detect if Trainer Spy is running is to use the FindWindow API call.
This method works and is relatively quick but is also very easily defeated.
2. A method that can’t be defeated easily is to use the EnumWindows callback. This involves
checking a offset in each running window’s process against a known value. Though hard to
defeat there is a performance penalty to pay, so it should be considered only as a last resort.
Check msdn or other Windows help files for more information on EnumWindows.
3. A third way to detect if Trainer Spy is running is to check the WriteProcessMemory call and see
if Trainer Spy has modified it. It turns out Trainer Spy replaces one byte (the first byte) of
WriteProcessMemory to allow it to intercept API calls. By checking this byte we can tell if
Trainer Spy is active and by replacing this byte to the original one we can prevent our addresses
from being intercepted. The detection can be done using the following code.
BOOL IsTrainerSpyActive()
{
BYTE byte;
DWORD addr;
if(hKernel) {
addr = (DWORD)GetProcAddress(hKernel, "WriteProcessMemory");
ReadProcessMemory(GetCurrentProcess(), (LPVOID)addr, &byte, 1, 0);
FreeLibrary(hKernel);
return FALSE;
}
There are other ways of detecting if Trainer Spy is running but this is enough to get you started. The
code is written in C but should be easy to convert to any other language.
Once you know Trainer Spy is running there are a couple of things you can do to prevent others from
reading your addresses. One way is to just skip your WriteProcessMemory calls while Trainer Spy is
running. Or you could give an error message and shut down the trainer. Along with any other action
let the cheater know what you think of him. Write to a dummy address a string containing your
message for him. The code below is one way to provide protection by detecting if Trainer Spy is
running (using method number 3 above) and if it is returning without writing to the target processes
addresses.
void WriteMemory()
{
DWORD pid;
HWND hwnd = FindWindow(NULL, "Anti Trainer Spy");
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
char str[100] = "I see your using Trainer Spy; well good luck.";
And finally the complete code for a trainer in VB using the info above. (Sets the money to 2,000,000
on level 1 of the Trainer tester available from http://www.gamehacking.com/, version 1.1)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
IsTrainerSpyActive = False
hKernel = LoadLibrary("Kernel32.dll")
If hKernel <> 0 Then
addr = GetProcAddress(hKernel, "WriteProcessMemory")
ReadProcessMemory GetCurrentProcess, addr, value, 1, 0
FreeLibrary hKernel
If value = 204 Then IsTrainerSpyActive = True
End If
End Function
' This sub sets the money to $2,000,000. It gets called when the
' button SetMoney is clicked
This tutorial only covers a few of the possibilities. I encourage everyone interested in making trainers
to expand upon these ideas, experiment and come up with new ideas.
beans / techno
AN ALTERNATIVE TO TRAINER-SPY
More and more trainers are protected against TS nowadays... Maybe the trainers
don't like this programs (or have an allergy for this...)
So, now you wanna know how TS can be replaced... Well, SoftIce can do the job!
When TS is launched, it loads (dynamically) a VxD in memory. This Vxd is the key
of what TS means. It hooks API WriteProcessMemory, and when a trainer calls t
API, TS intercept the pushed parameters & shows them to us:
If you don't believe me, try this: bpx on a push before writeprocessmemory is exe
Then trace down with F8 inside the API. And soon, you will find yourself in t
traspy.vxd code. Of course traspy if you hadn't changed it (like i did :)
********************************************************
* macro Sorin = "? *(esp-10);? *(esp-8);d *(esp-c) l 10"
* bpx writeprocessmemory do "p ret;cls;Sorin"
********************************************************
==========================================================================
BOOL WriteProcessMemory(
NOTE : When the push instruction is executed, the stack is DECREASED by 4 bytes,
and when the pop instruction is executed, the stack is INCREASED by 4 byte
Esp is the stack.
ex:
Let's imagine that a trainer writes some data at 401000 in a game's process.
And let's say that the stack (esp) is 63FBC0.
So the trainer acts like this:
stack (esp)=63FEC0
push lpNumberOfBytesWritten ->stack is DECREASED by 4, so this means esp is now
push number_of_bytes_to_write ->stack is DEC. by 4, so (esp-4)-4=esp-8
push pointer_to_data_to_write ->stack is DEC. by 4, so (esp-8)-4=esp-c (it's hex
push address_where_to_write ->stack is DEC. by 4, so (esp-c)-4=esp-10
push game's_process'_handle ->stack is DEC. by 4, so (esp-10)-4=esp-14
call WriteProcessMemory
That's all you need to know for now. So, after API WriteProcessMemory is executed
easily determine what contained the pushed parameters...
If we do "? *(esp-4)" in SoftIce, we'll see the "actual number of bytes written"
parameter is usualy 0. By typing "? *(esp-8)" in SoftIce, we'll see how many
were written in the game's memory by the trainer. "d *(esp-c)" will show us t
buffer containing the bytes written (what the trainer wrote). NOTICE that her
typed "d" instead of "?", because we want to see the bytes at *(esp-c). And f
we get the most important thing (the address where the trainer writes data) b
"? *(esp-10)" in SoftIce.
That was the theory. (the above method can be used with ANY API).
macro Sorin = "? *(esp-10);? *(esp-8);d *(esp-c) l 10" is just a macro that displ
the address where the trainer writes data, the number of bytes that the train
and the bytes that the trainer writes at that address.
bpx writeprocessmemory do "p ret;cls;Sorin" - like you can see, sets a breakpoint
writeprocessmemory. If the API is called, then SoftIce will do a "p ret" taki
the trainer's code. Then the "cls" command is executed that clears the SI dis
window, and after that the macro Sorin is executed (see above)...
You will see something like this (IN SOFTICE) when a trainer writes some data:
00401384 00004199300 -> the address where trainer writes (hex & dec)
00000002 00000000002 -> how many bytes the buffer with data is
016F:4030EC 90 90 A2 04 00 00 00 00 40 00 1F 0E 00 00 8C 04 ........@....... -
buffer. NOTE that in this example ONLY the first 2 bytes (90 90) are written at 4
00401384 00004199300
00000002 00000000005
016F:4030EC 90 90 A2 04 00 00 00 00 40 00 1F 0E 00 00 8C 04 ........@.......
That's it for now, I hope you understood something useful from this...
Cheers,
Sorin ( Splinter@email.ro ).
eof
N Ways of protecting your trainer
PART I
Short Intro
~~~~~~~~~~~
So, here we are, thinking out how to defeat those "address stealers" and their
beloved Trainer Spy...
The code will be converted to (M)ASM, so it can be more clear and can be
translated to any other programming language easily...
BEGIN
~~~~~
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
window_name db "TRAINER SPY",0
.code
invoke FindWindow, 0, addr window_name
.IF eax!=0
.END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Remarks : This is a standard method. But it can give fake results if other
program (other than Trainer Spy) has the window caption "TRAINER SPY".
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
class_name db "#32770",0
.code
invoke FindWindow, addr class_name, 0
.IF eax!=0
.ELSE
.END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Remarks : This is a standard method. But it can give fake results if other
program (other than Trainer Spy) has the class name "#32770"
Explanation : Here we search for Trainer Spy's class name (main window is a dialo
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
vxd_name db "\\.\TRASPY",0
.code
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ+FILE_SHARE_WRITE
push GENERIC_READ+GENERIC_WRITE
push offset vxd_name
call CreateFile
.IF eax!=-1
.ELSE
.ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Remarks : Another standard method... Like the other ones, it's too known and easy
to bypass. But it's more "professional" than the first 2.
Explanation : Trainer Spy does its job by putting a breakpoint on WriteProcessMem
with the help of TRASPY.vxd (look for this file in Trainer Spy's
folder). The code above tries to open a VXD (in our case, TRASPY.vx
If the vxd exist in memory, then CreateFileA will return the handle
to the vxd, which means Trainer Spy is spying. If CreateFileA retur
-1 then it isn't a vxd with the specified name in memory, which mea
Trainer Spy is not active...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
file_name db "c:\logwmemory.bin",0
.code
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push 0
push GENERIC_READ+GENERIC_WRITE
push OFFSET file_name
call CreateFile
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.data
file_name db "c:\logwmemory.bin",0
.code
invoke DeleteFile,addr file_name
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Explanation : Like above, instead of restricting the access on this file, we simp
erase it.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.code
mov eax,WriteProcessMemory ; -> mov in eax the "jmp to WriteProcessMemo
mov eax,[eax+2] ; -> mov in eax the address of WPM
mov eax,[eax] ; -> mov in eax the address of first instr.
add eax,3 ; -> we jump over the first 2 instr. (3 byte
mov lll,eax ; -> we save this address to next instructio
push 0 ;----|
push how_many_bytes_to_write ; |
push offset data_buffer ; |> the WriteProcessMemory parameters
push lpAdress ; |
push phandle ;----|
mov ebp,_return_ ; -> we save the address where we want to re
push ebp ; -> first instruction in WPM
sub esp,4 ; -> we pushed before, so we must recalibrat
mov ebp,esp ; -> second instruction in WPM
call [lll] ; -> call WriteProcessMemory from the THIRD
_return_: ; -> a label where we will be after WPM was
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Protection Mark : 11/10 (yes, it's ELEVEN OUT OF TEN) - SUPER TECHNIQUE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.code
pushf
pop ax
test ah,1
je no_debugger
jmp debugger_found
;.................
no_debugger:
; here you can continue. This means your code isn't debugged.
;.................
debugger_found
; you will be here if your code is debugged
; so put here the defensive code
; see the "DEFENSIVE" section
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Remarks : The above code has to be the first code after .code :)
Explanation : When a debugger is present, it sets some flags. So, we test this an
we find a debugger, you know what you have to do. Those few lines o
are VERY OFTEN used by the virii, kicking the ass of AntiVirus prog
(thnx KurruPt - FiLe again)
DEFENSIVE SECTION
Here will be presented some attitudes that you'll have to take if you find someth
inconvenient spying your code.
- do nothing
Well, this rubric will not be as usual... I'll thank now the people who wrote
anti-X tutorials/materials or explained them which inspired me to write this
2003
eof
======================== I N T R O=====================
Well, i decided to write another essay, but what should i put in it?
I can't tell u how much i like cartoons, because this text would never end ;}
Now the good hackers (and the hard working ones ;) ) would fuc* my ass:
"Hey man! What the fu*k are u teaching the lamers how to steal our work?, u mothe
But here comes the tricky part: this tut is dedicated to the hard_working newbies
after hours and hours of hacking, couldn't find where the MineSweeper inc the
=> just joking, hehehe...
Seriously, i don't think that's a good idea to hide all your work (from the eyes
people that wants to learn something from u, after they tried and tried and t
any result! ).
And i don't think the lazy lamers would loosing their time coding in asm or C the
schemes!
Let's study a little Micral's essay about the TS (trainer spy) protections! He di
into 3 parts:
1) The Beginner's Way (Search for TS's window, if found then don't train)
2) The Middle Way (Mess up with C:\logwmemory.bin, by setting it's access to read
3) The Good Way (Check if there is a breakpoint on WriteProcessMemory, and if it
or a debugger is active => no poking )
Now, let's analyse those one by one, finding the way to break in !!!
1) Now, this method is quite good (in my opinion), because the lamers don't want
around with anything, they just want to steal the offsets !
So, i think no lamer would try to change the TS's window text! Besides, they
"TRAINER SPY" string in the file :)
This piece of code changes the TS's window text from TRAINER SPY to put here a na
this done, this protection is passed!!!
REMARKS: BEST WAY
b) Disassemble the "protected" trainer and look on where the API FindWindow is c
the pushed value points to "TRAINER SPY" string, this is it! Change the cmp
after.
REMARKS :This should work on non-encrypted\packed trainers. BTW, use W32Dasm for
disassembling part :)
2) The second method is a LAME !!! A LAME AND NOTHING ELSE !!!
In this method u should "protect" your trainer by setting readonly access on
called logwmemory.bin . HEHEHE... Let's see how can we bypass this...
a) MOVE the Traspy.vxd from your Windows dir (if the file exist) in the same dir
TS.exe.
Grab any hex-editor and change the logwmemory.bin into hehehehehe.bin (for
in TS.exe and in Traspy.vxd (be sure that the length IS LESS OR THE SAME ie
of logwmemory.bin=14, then your new name for the file must have the length
u choose <14, then fill the remaining 14-your_length with 00h).
REMARKS: BEST WAY
b) Trap the CreateFile function called from the "protected" trainer, nop-it or c
it's SecurityAttributes from 0 to 5 for example (the file won't be accessed
and TS will do it's job :) )
REMARKS: This should work on non-encrypted and non-packed trainers!
.....................
many many more !!!
.....................
3) Ah! The good way... This is indeed a way to protect your trainers! But still c
defeated! Especially when u use API's ! (see LAST-WORDS).
Here the trainer will search for a breakpoint on the API WriteProcessMemory. If
a CCh in front of it, ==> no pokes (CCh=breakpoint).
The solutions ??? Here they are :
b) See where and how the "protected" trainer is fuc*ing with kernel32 (the owner
of WriteProcessMemory) and, you know, NOP!!! hehehe...
REMARKS: This method is quite risky!
Needs experience from u !
Should work on non-encrypted\packed trainers!
========================= L A S T W O R D S========================
When u code your trainers, always try to avoid using many API's ! You see, there
of manuals on how the api's are processed, and you will find your code unsecu
i know that we are in window(s)' age, but there are methods! No matter how mu
your code, it still can be "deprotected". There are many commercial products
encrypt\pack your program, but there will be always the de-crypter\un-packer
groza
all members in gamehacking's forum
micral ( i hardly wait some other protections to "unprotect" heheh! hope u will n
on me for this essay! as i write, this is not for thievs -i am a lamer,
never be a thief !- )
all members in new2cracking (especially parabytes!)
YOU for loosing your time with this (better go outside and play ! :} )
JUVENTUS (like always)
romanian greetings:
**********************************************************************
* Salutari tuturor celor din Romania -crackeri,hackeri,zidari,macaragii,profesori
* Cautati-ma!!!
* (si aveti grija cu cine votati -hehehe...-)
* La Revedere!
**********************************************************************
Sorin ( Splinter@email.ro )
2003
eof
;********************************************************************************
;---------------------------------------------
; Protection-Suit Version 1.0 (c) by [NtSC]
;---------------------------------------------
;
; I prefer to implement this Sub-Routine in an Routine permanently called by your
; (not only once,at the init...)
;
;Contents (Trainer specified):
;-----------------------------
; - CheckBreakPoints (if BreakPoints on Read/Write will be found,Goodbye)
; - CheckTrainerSpy-Routine (if Window present,Goodbye)
; - CheckTrainerSpy-Routine (if CLass present,Goodbye)
; - Create TrainerSpy data file (c:\logwmemory.bin) + set specific File-Attribute
;********************************************************************************
; Still in development:
; - checksum routine for complete suit/Trainer main routine
; - cryption of Asciiz
; - check for breakpoints on Range
;--------------------------------------------------------------------------------
Thief db "TRAINER SPY",0 ; Trainer-Spy Window-Caption
ThiefClass db "#32770",0 ; Trainer-Spy Class
Kernel32 db "Kernel32",0 ; Base of our Api´s
ReadMemory db "ReadProcessMemory",0 ; Api´s to check
WriteMemory db "WriteProcessMemory",0 ; (most common used by trainers
Data db "c:\logwmemory.bin",0 ; TrainerSpy file (Info from vxd
;--------------------------------------------------------------------------------
;--------------------------------------------------------------------------------
CheckTrainerSpyWindow:
call FindWindowExA,0,0,0,offset Thief ;TrainerSpy Window active? if yes,Go
cmp eax,0
je CheckTrainerSpyClass
jmp LamerFound
CheckTrainerSpyClass:
call FindWindowExA,0,0,offset ThiefClass,0 ;TrainerSpy Class found?..if yes,
cmp eax,0
je CreateAntiTrainerSpy
jmp LamerFound
jmp WecontinuewithoutLamers
;********************************************************************************
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MM MMMMMMMMMMMMMMMMMMMMMMM DMMMMMMMMMMMM DMMM
MM MMMMMMMMMMMMMMMMMMMMMMM DMMMMMMMMMMMM DMMM
MM222+ 222MMMMMMMMMMMMMMMMMMMMMMM DMMMMMMMMMMMM22222 DMMM
MMMMMD MMMMMMMMMMMU2+ 22UMMMMMMMM DM222DMMMMMMMMMMM+ DMMMM
MMMMMD MMMMMMMMMM2 UMMMMMMM D2 +HMMMMMMMMMM+ DMMMMM
MMMMMD MMMMMMMMMH HMH MMMMMMM + +HMMMMMMMMMM2 DMMMMMM
MMMMMD MMMMMMMMMD 222 MMMMMMM +MMMMMMMMMM+ UMMMMMMM
MMMMMD MMMMMMMMMD 222222MMMMMMM DMMMMMMMM+ UMMMMMMMM
MMMMMD MMMMMMMMMH UMUUUDMMMMMMM 2D HMMMMMMD +22222UMMM
MMMMMD MMMMMMMMMM2 UMMMMMMM DM2 +MMMMMMD DMMM
MMMMMU222MMMMMMMMMMMD2+ +2HMMMMMMMM222UMH222HMMMMMU222222222UMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
8888 11 9999 3333
88 88 111 99 99 33 33
88 88 1111 99 99 33
88 88 1 11 99 99 333
8888 11 99 99 33
88 88 11 99999 33
88 88 11 99 33
88 88 11 99 9 33 33
8888 11 999 3333
+------------------------------------------------------------------------------+
[ n4m3 ] : ANTI-TRAINER SPY TUTORIAL
[ By ] : MiCRaL
[ c0nt4ct ] : ex_micral@yahoo.com
[ r3l34s3 tYp3 ] : essay
[ d4t3 ] : September 6th, 2001
[ URL ] : http://www.vngamecenter.com
+------------------------------------------------------------------------------+
Table of Contents :
1. INTRODUCTION
2. HOW TO DEFEAT TRAINER SPY
2.1 SIMPLEST WAY
2.2 NORMAL WAY
2.3 GOOD WAY
3. NOTES
+------------------------------------------------------------------------------+
================================================================================
1. I N T R O D U C T I O N
================================================================================
You know Trainer Spy do you ??? Well just in case you don't know, Trainer
Spy, as the name says, is a program that can monitor any chains written in the
memory, it is used to see what bytes and what address a trainer have written in
the game's memory. It was made for educational purpose, for newbie to learn by
looking at other's code. But if it is put in the wrong hand, it could be VERY
LAME to use TS to steal the addresses and claim it as the lamer's own.
This tutorial use Delphi for example because Pascal is one of the easiest
language out there, and you can easily convert the codes in this tut to another
language like C++ or ASM... Don't ask me for these sources, they're easy to
convert so do it yourself.
Actually, the methods in this tutorial are not the BEST ones as they can
still be defeated, but ones with enough knowledge to defeat 'em don't need the
steal the addresses anyway.
Lastly, I wrote this tutorial on request only, and myself I don't think
preventing TS is good. If you do that you've over-generalize anyone to be a
lamer. There are ones willing to learn and I would really like to help.
Now, for those who want to protect your code, here comes your solution!
================================================================================
2. H O W T O D E F E A T T R A I N E R S P Y
================================================================================
Let's see... how do you identify a game when you program your trainer ?
It's FindWindow() API function right ? You could also use this function to
identify the Trainer Spy window, if it is found kill the trainer (or do anything
you like). Let's pass 'TRAINER SPY' as the parameter since it is the TS's window
caption. Here's the code :
This method is quick and easy to understand, but what if the caption wasn't
'TRAINER SPY' ? If it was changed ? (Yes this is possible but I won't mention
how to do that here...just in case... :-) Let's try other methods.
CreateFileA('C:\logwmemory.bin',$40000000,1,0,2,1,0);
Just put it at the beginning of your program, in the Form Create event or
such... you know how to do that ! If you don't, learn now.
This way Trainer Spy still run, the trainer won't exit, but TS has became
useless now, if you try to monitor some pokes you'll see that no addresses can
be found !
This is a better method, but, again, it can still be defeated... and again,
I won't mention how to do that here. :)
And in case this method fails, I think the below method is the most
efficient and easy to do one.
function IsTrainerSpyActive:bool;
var hProcess,hKernel:dword;
addr:pointer;
b:byte;
dummy:cardinal;
proc:pchar;
begin
//nothing done yet, result is false
result:=false;
The codes are well commented and I think you could understand easily. This
code can be convert to any language easily too. This is a very efficient way and
it can be done quickly too.
================================================================================
3. N O T E S
================================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[EOF]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DETECTING TRAINER SPY
What you will learn:How to detect trainer spy (a.k.a TS, not Tiberian Sun)
and stop most kiddies from stealing your work.
Beggining:
A lot of us have been looking for a good way to prevent people from using
Trainer Spy. Sure its a good tool to help you learn, but a lot of people steal
the memory addresses and try to pass off the work as their own. It happened
to me a few times, someone took my addresses and even the wording from
my homeworld trainer and changed 2 words (credits into cash) and claimed
he made it.
How:
Since I come from a cracking background I watched how Trainer Spy
worked. It uses a file called traspy.vxd (virtual driver device - kind of like
a .dll) to capture things from memory anytime a process (program) opens
and writes to another programs memory. So naturally I opened up
TRASPY.VXD. Then by chance I found the following string
'logwmemory.bin' ...gee what could this be. Looks like Log Windows
Memory. So I did some investigation, I went to my c:\ but there was no file
named 'logwmemory.bin' there so I made an empty one just to make sure
that there really wasn't a file there. So I ran trainer spy and turned logging
on, and with Trainer 2.01 I modified some values, and TS was triggered.
Okay TS logged one hit, I hit the stop icon. I checked back in my c:\ and the
'logwmemory.bin' was gone. So I tried to make an empty 'logwmemory.bin'
again but to my surprise Windows popped up with a msgbox saying
"ERROR cannot create file, file already in use". So the file was hidden
(Even though I have Show All Files selected under Explorer) and write
protected. So I deduced that every address taken from memory got placed in
that file. I closed trainer spy, 'logwmemory.bin' no longer existed, so I
made a new 'logwmemory.bin' and I wrote protected it (in explorer select
the file hit alt+enter and check read-only). I again started up TS and played
around with Trainer 2.01 and TS had 5 hits recorded. I hit the stop button..
and what do I get? Nothing!
Solution:
The solution to finding if trainer spy is running, first check for
'logwmemory.bin' in the root dir with the FindFirstFile() api call. If its
there then TS is currently running & recording. If its not there then TS is not
running OR the user hex edited the 'traspy.vxd' & 'trainer spy.exe' and
changed the filename 'logwmemory.bin' to something else or just the drive
letter. Most not to bright lamers will just hex edit the title bar of Trainer
Spy from "Trainer Spy" to something else so the FindWindow() won't find
TS. The filename that is being used to store the captured addresses is stored
in the TS process at the following address: 00426247. So if you modify this
address and change it to lets just say 'stealing_is.gay', TS will never get
results.
Here lies the only problem, it might be hard to find which program is TS if
they change the title from Trainer Spy to something else. My only solution
is to use GetWindowClass() and open every Dialog (Window Class:
#32770) based process and write 'stealing_is.gay' into 0042647.
Conclusion:
I hope I gave you some new incite on how TS works and how to prevent
people from stealing your shit. Sure there are a lot of work arounds and
someone who really wants to get your addresses will, but this will hinder
them in their attempts. Anyone who hasn't read this won't really know how
to prevent us from preventing them from getting our addresses. And if you
plan on punishing someone for trying to use TS to get your shit, don't delete
their files, its lame and illegal (I am sure you are shaking in your boots), as
most people are only trying to learn how you did something.
^chaos^
June 26th, 2000
First things first, I promise to not make this tutorial as lengthy as the previous one, if you're going in
order you most likely would not want another 12 page massacre, and if you don't you're in luck, for
now.. In this tutorial, I'll show you how to poke multiple values at once & poke multiple addresses.
This tutorial will attempt to take the same format as the previous tutorial.
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_YESNO
.if eax==IDYES
invoke Poke, address, addr Value, 1
.endif
invoke ExitProcess, NULL
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_YESNO
.if eax==IDYES
invoke Poke, Freezeadr, addr Freezeval, 5
invoke Poke, Barfrz, addr Barfrzval, 5
.endif
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
LOCAL pid:DWORD
LOCAL windhand:DWORD
Invoke FindWindow, NULL, addr wndName
mov windhand,eax
Invoke GetWindowThreadProcessId, windhand, addr pid
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
Final note
Well if you'll be able to continue waiting, my next tutorial should be the one you're waiting for how to
make a dialog in Masm, without 50 lines of code, with visuals
Well here goes my third tutorial, the one you've been waiting for, creating the dialog without knowing
a mass amount of asm. This tutorial requires picking up Reshacker and a .res file which I can provide
if you don't already have them.
Reshacker This is made to edit the res file to what you want.
Example res file The example res file used in this tutorial.
Starting off
First off open ResHacker, and set it to open .res files like so, and open the example.
The first thing we'll do upon opening Reshacker is changing the icon of our trainer. Click the icon on
the left side like so
Hit the open file with new icon button then choose which icon you want your trainer to have. Next
we'll start with editing the dialog. So we'll start by selecting the dialog like so.
right now the dialog should be just a quit button on a window. You can easily resize the window by
clicking and dragging the edges, and you can move or resize the quit button easily by moving it or
resizing it like the window. If you want to change the caption of the window you right click on it and
hit edit dialog. If you want to add a button you'll have to right click on the dialog and hit insert
control. The insert menu should look something like this.
The window should look something like this(minus the orange in the ID box.) To add a button hit the
button that says OK on it. From there put a Caption on the button, and don't forget to give it a unique id
number(in the box highlighted in orange above). After adding a few buttons we have our standard
trainer. Mine looked something like this.
Once we're finished all this we hit the compile script button at the top. Then go file->Save as and
save it in your bin directory.
The next step would be to link it to your obj file. The way we would do this is to open up Qeditor and
your asm file, reassemble it if necessary and hit the Command Prompt button(black windows beside
the printer button). After hitting that it should take you to a dos prompt in your bin directory, while in
your directory type in
link /subsystem:windows /libpath:C:\masm32\lib file.obj file .res
This should assemble the file and upon looking at your newly created file you'll notice the cool new
icon on it.
--Q&A--
Q:Where's my dialog????
A:Right where you left it, you gotta define it in your asm file for it to work.
-------
Defining the Dialog
Now we must make the dialog the main window much like they do in Iczelion's tut #10(the part 2
part). First we start off by defining the Dialog items above the .data.
Poke proto :DWORD,:DWORD,:BYTE
.data
Then we define the dialog proto above the .data
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
Poke proto :DWORD,:DWORD,:BYTE
.data
Next would be to actually define the DlgProc proto.
DlgProc Proc hWin: DWORD, uMsg: DWORD, wParam:
DWORD, lParam: DWORD
xor eax,eax
ret
DlgProc endp
Now we should put in some actions.
DlgProc Proc hWin: DWORD, uMsg: DWORD, wParam:
DWORD, lParam: DWORD
.if uMsg==WM_COMMAND
.if wParam==ID_QUIT
invoke ExitProcess,0
.elseif wParam==ID_NUM
invoke Poke, Freezeadr, addr Freezeval, 5
.elseif wParam==ID_BAR
invoke Poke, Barfrz, addr Barfrzval, 5
.endif
.elseif uMsg==WM_CLOSE
invoke ExitProcess,0
.endif
xor eax,eax
ret
DlgProc endp
Then we gotta remove the old dialog(the messagebox) and put in our new one of the new dialog. We
do this by calling DialogBoxParamA and looking at the API guide we see that in order for it to work
it needs process instance, and in order to get that we need to use the GetModuleHandle API. The final
code looks something like this.
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParamA,hInstance,ID_DLG,0,addr
DlgProc,0
invoke ExitProcess, NULL
and to end it all off give it the variables it needs to identify itself to windows, we put this in a tag
under .data called .data? this is just like the .data tag except it's not too sure of itself so it doesn't do
anything till the program is running.
.const
Freezeadr equ 401384h
Barfrz equ 4013EAh
.data?
hInstance HINSTANCE ?
The final product should look something like this
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
Poke proto :DWORD,:DWORD,:BYTE
.data
Caption db "Caption",0
Text db "Text",0
Freezeval db 090h
db 090h
db 090h
db 090h
db 090h
Barfrzval db 090h
db 090h
db 090h
db 090h
db 090h
wndName db 'prog test',0
.const
Freezeadr equ 401384h
Barfrz equ 4013EAh
.data?
hInstance HINSTANCE ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParamA,hInstance,ID_DLG,0,addr
DlgProc,0
invoke ExitProcess, NULL
Author:EEDOK
E-mail/MSN:Mr_eedok@hotmail.com
Webpage:http://eedok.simplehost.com/
Version:1.00
Date:May 14,2003
This will be a quick tutorial on how to make a trainer in Masm, by using trial and error(many errors),
my no dialog Masm trainer skeleton will be the file I'll be making reference to(most the time). Getting
the uncommented version is recommended if you just want your own comments. This tutorial also
includes Q&A sections, which read your mind of the questions you were about to e-mail me to ask,
cause I'm psychic and I know exactly what you're going to ask.
Stuff you might want
Required
Masm Tells you how big of a dumbass you are and how much you shouldn't even be attempting to
compiler program, proving this wrong is your ultimate goal.
Text either notepad, Or Qeditor, I like Qeditor though cause it's more fun cause it wasn't made
editor by Microsoft. So for this I'm forcing you to use Qeditor.
Recommended
Programmers dictionary, trying to program without one of these is like trying to tell a
API guide
french person how to get to the theatre, but only knowing the very basic words
My trainer see the finished results, so once you get bored of this tutorial you can go ahead and
skeleton copy my code and cheat, you lousy cheater
Hex code for without this you'll be making a trainer that does nothing, which is about as useful as a
your trainer swiss condom(just think swiss cheese).
Starting off
well first you'll want all your required files. If you use Qeditor this is as easy as hitting a button, well
2 buttons, Script then ASM Model. Otherwise you'll have to go through all the work of copying and
pasting the code below.
---------------
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
.data
.code
start:
end start
;----------Stop Copying and pasting here-----------
Well now that we got the required files, We'll want to create a dialog in which gives the user of the
trainer the option of using it. The simplest predefined type of dialog is a message box. The other thing
we'll need is the function to exit the program, cause as much as you want to send the user into an
eternal loop of your training damnation, the user most likely doesn't want to(either that or the
compiler forces you to have one). But how oh EEDOK, could we make such functions? Well for the
exit it's actually really easy. Just place this code under where it says .code, so it looks like this..
.code
start:
invoke ExitProcess,NULL
end start
--Q&A--
Q:What does that NULL mean?
A:hell if I know, it's in working order as it is, don't change it(unless you know what you're doing)
Q:What about the message box?
A:Oh yea, I'll get back to that now
-------
Time for the message box. How to make such a simple thing? well pulling up the API guide it says to
go invoke MessageBox, (put hWnd here), (put lpText here, which is really just gonna be a reference
to the data section), (put lpCaption here, which is gonna be another reference to the data section), (put
uType here, which we have a vast choice upon, but in this tut I'll stick to MB_OK and/or
MB_YESNO)
--Q&A--
Q:I don't understand that all looks like jibberish.
A:That's not a question, and just don't worry I'll do it all for you :)
-------
So lets make this easier for you, first thing I said looking at hWnd was wtf does that do? so I set it as
NULL. Next is lpText, which I'll simplify as Text, and I'll do the same with lpCaption. For the uType
We'll use MB_OK. So then the code looks like this..
under data put this
.data
Caption db "Caption",0
Text db "Text",0
Now for the code part, for the message box put in, invoke MessageBox, NULL,addr Text, addr
Caption, MB_OK as the code, now remember the code goes starting at the top down. So here's some
examples of what's wrong and right.
Wrong
.code
start:
invoke ExitProcess, NULL
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
end start
Right
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke ExitProcess, NULL
end start
---funny tip----
copying the MessageBox code multiple times will make it so for every time you copied it the user
will have to hit OK, even though you had to hit the paste button that many times, annoying to you or
him?
-----------------
With all this in the code, all it does is makes a message box with the Caption and Text you defined.
Now quit saying "KW1CK lOoK @t MY leEt Tr@1Ner" realize it still has no training functions.
--Q&A--
Q:But how do I make my uber 1337 trainer work?
A:Well it's kinda complicated, but I'll continue on to how to figure it out..
-------
Well thinking what does a trainer do? If you answered that question with A.)Write new values to a
running program you'd be correct. If you answered B.)manipulates predefined addresses to overwrite
the existing values there to modify them to what the programmers set the values to, such to cause the
program to react in the way the programmer intended, Drink a beer, and repeat until your answer
changes to A.). If your answer changes to what is this 'trainer' you speak of? Then immediately stop.
Asking such questions is not healthy for you. Now once you've correctly answered this question, we
pull out the API guide and go line by line to find which API would properly do this, or we could
cheat and look at someone else's source code and find it, either way you'll find this API,
WriteProcessMemory. You can look at it how you like but I'm gonna define the parameters in this API
as phandle, aHack, nVal, iSize, NULL.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
invoke ExitProcess, NULL
end start
Now we save it as something.asm, next we go to compile it, This is done in Qeditor by hitting
Project, then hit Assemble ASM file. This will come up with the compiler, which will promptly say
we have an idiot factor of 8. Taking a closer look at these errors they're saying our variables in
WriteProcessMemory aren't defined, and saying this 8 times. Pretty redundant eh?
--Q&A--
Q:How do we fix this recurring error?
A:Define the variables
-------
Now to define the variables. well there's aHack nVal and iSize, we should define them in the .data
part of the source.
.data
Caption db "Caption",0
Text db "Text",0
nVal db 000h
iSize db 000h
.const
aHack equ 41D090h
(this is for MTC prog test, with these values it'll change the value of the number to 0)
--Q&A--
Q:What's with the .const thingy?
A:No idea, but it seems like ppl like it better putting the aHack there instead of under the .data part.
Silly people never explained why.. Lets keep it that way..(response from ddh:All data in your
program that doesn't change and will never need to should go under .const to help prevent bugs.)
-------
--Q&A--Again
Q:Hey that phandle variable still isn't defined!!!
A:Please ask that in question form from now on.. So I guess that's what we gotta do next..
-------
I defined them as such, PROCESS_ALL_ACCESS(because we want super powers over our program
mwahahahah), 0(which means false, we don't need this stuff), pid(cause it sounds like piddle, j/k,
acronym for process id). The other thing we gotta do is define what type of variable phandle is. doing
so will look something like this.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
LOCAL phandle:DWORD
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
invoke ExitProcess, NULL
end start
So now we go back and compile this once again.(Project>Assemble ASM file, remember to save
first.) This time it'll come with an error that looks like this PROC, MACRO, or macro repeat
directive must precede LOCAL. And that phandle still isn't defined, that and now there's a variable
known as pid that's not defined. So time to fix these errors.
--Q&A--
Q:How do I fix these errors?
A:Did you not just read my previous transitional phrase?
-------
Now to fix these errors we're gonna move all the write memory code into a PROTO. What PROTO
means is beyond me, but you won't need to know this, you'll just have to know how to use it. The first
step in think of what parts of write memory actions would we want to be user defined. Looking at the
current ones I'd say aHack, nVal and iSize. Next thing to think about is what type of values these
should be, what I say is when in doubt, use DWORD. So now onto defining the PROTO. Start by
naming it, I named mine Poke after a common way to greet people where I come from. Seeing how
we're gonna have 3 variables in the code we'll define them in the proto definition process(named so
by myself). I defined them as 2 Dwords and a byte, or someone else did and I just copied them(Most
likely Micral). So now for the defining part, for some odd reason this likes to be defined over the
.data instead of under it like other types of data, this is because Proto's are rebels and don't wanna
conform to the standard procedure. So now our data part would look something like this.
Now that it's defines we'll have to put it in the code section. That and we should define the variables
to use with it. Also we should move the phandle from where it was to it's new home. So our code
would look something like this now.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
ret
Poke ENDP
end start
looks nice, on problem is, it's not doing anything as it is, so next we would relocate our code to this
location.
----Important note-------
now that aHack, nVal and iSize are in the Poke function we could rename them to easier to read
values so our .data could look something like this
--Q&A--
Q:Where'd size go
A:It ran away cause you smell, either that or we'll be defining it in a different way
-------
Now to get on with relocating our code. we'll move all the non message box code into the Poke proto.
So now the code looks something like this.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
That looks nicer, now we attempt to compile again. now we get an undefined symbol : pid, and
another error caused by that undefined symbol.
--Q&A--
Q:How do I define this pid?
A:Read the next section
-------
Well the first thing we gotta do to define this pid is give it a value type, I give it a DWORD cause I'm
in doubt. I like keeping all my defining together at the beginning of the proto so I'll give it it's value
right by where I did it with phandle. So our code would look something like this
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
LOCAL pid:DWORD
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
Now that we got a variable type to it, we gotta use the API to find it, now we could go through line
through line of our API guide to find it, steal from someone else's source, but it'd be easier if I just
told you that it was the GetWindowThreadProcessId API. Now looking at our handy API guide
again(if you haven't deleted it because I'm telling what to do anyways) you'll see that we need to
define window handle and where to write the pid of the window handle to. I put them as windhand
and addr pid, so the code now looks like
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
LOCAL pid:DWORD
Invoke GetWindowThreadProcessId, windhand, addr pid
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
Attempting to compile it at this time causes us to have the error that we have another undefined
variable, this time the one known as windhand.
--Q&A--
Q:How do I define this variable?
A:read on
-------
Now to define this variable, just as every other one, we need to give it it's Variable type and find the
API for defining this(FindWindow). for FindWindow you need to give a null terminated string to the
window you want to define(meaning you gotta put it in ur .data section), or use a process lister to find
the class of the window, but we won't do that quite yet. So with this addition to the data section,
would make it looks something like this.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
LOCAL pid:DWORD
LOCAL windhand:DWORD
Invoke FindWindow, NULL, addr wndName
mov windhand,eax
Invoke GetWindowThreadProcessId, windhand, addr pid
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
Compiling it now,Drum roll makes it come up with... a grand total of.. () 0 errors, now before you
start going hah in ur face compiler I pwned ur ass, you should realize that your trainer still does
nothing.
--Q&A--
Q:Why isn't my trainer doing anything?
A:You haven't got any commands to run it.
-------
The next step would be to call this process, The way we would do this is Invoke Poke, (what to put in
for aHack),(what to put in for nVal), (what to put for isize). We'll make it do this after clicking OK on
the message box. So the new code would look like this.
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_OK
invoke Poke, address, addr Value, 1
invoke ExitProcess, NULL
Poke PROC aHack:DWORD, nVal:DWORD, iSize:BYTE
LOCAL phandle:DWORD
LOCAL pid:DWORD
LOCAL windhand:DWORD
Invoke FindWindow, NULL, addr wndName
mov windhand,eax
Invoke GetWindowThreadProcessId, windhand, addr pid
Invoke OpenProcess,PROCESS_ALL_ACCESS, 0, pid
mov phandle,eax
invoke WriteProcessMemory,phandle, aHack, nVal, iSize,
NULL
ret
Poke ENDP
end start
compiling this we get no error, now to make this into an exe. We go up to where it says Project and
hit Link OBJ Object. After hitting this hit Project and run file, and we'll see that after hitting the OK
button on your program, it does change the value of the number to 0. But the only problem is you have
no choice but to change the value to 0. A good idea now would to be to give the user of choice, but
there's one problem with our current dialog, it only has one button. So now we're going to change the
MB_OK is the msgbox function to a MB_YESNO so then there'll be 2 buttons. Upon doing so will
cause the dialog to have 2 buttons, the only problem is they'll both do the same thing, so we must
define what each one will do.
--Q&A--
Q:How would we find out on how to make the program react differently to the 2 buttons?
A:Ask a gamehacking forum, but I've already done that, so now it's in this tutorial.
-------
The we tell what button the user hit is defined in the eax. If the eax=ID_YES the user hit yet if
eax=ID_NO then the user hit no. If you do not understand how this works I just have to ask you how
did you get this far into the tutorial?(lousy cheaters skipping the other sections) I made it so that it
would do the functions when the user hits yes, so after this change in code the .code section most
likely looks something like this
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_YESNO
.if eax==IDYES
invoke Poke, address, addr Value, 1
.endif
invoke ExitProcess, NULL
And now for the finished project, that looks something like this
.486
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
.code
start:
invoke MessageBox, NULL,addr Text, addr Caption,
MB_YESNO
.if eax==IDYES
invoke Poke, address, addr Value, 1
.endif
invoke ExitProcess, NULL
------Final Q&A--------
Q: What do the mov windhand,eax, and mov phandle,eax do?
A: They move the results from the previous api to the defined variable(windhand or phandle).
.if eax==0
invoke MessageBox, NULL,addr Errortext, addr Caption,
MB_OK
ret
.endif
.data
Errortext db "Error",0
Author:EEDOK
E-mail/MSN:Mr_eedok@hotmail.com
Webpage:http://eedok.simplehost.com/
This tutorial assumes you've read my previous tutorials and already have a grasp of where to put stuff
and add functions and the likes. If you don't understand where to put things, it is recommended you
read my previous tutorials.
.endif
ret
Poke ENDP
And to invoke it, it looks something like this:
invoke Poke, Address, addr ReadVal, 4, 1
Remember if you use this method to change all your pokes that WriteProcess memory to
invoke Poke, Address, addr Value, 4, 0
Putting it to use
One way to put ReadProcessMemory into use is to read the value then add to the value and Write the
value back into the program. I will use method B to show how this is done, because it's less typing for
me.
invoke Peek, Address, addr ReadVal, 4 add ReadVal,10
invoke Poke, Address, addr ReadVal, 4
When wanting to add negative numbers in order to make the total value a smaller value isn't an order
of adding negative number, but that of using a different function, one known as subtraction, which
looks something like this.
invoke Peek, Address, addr ReadVal, 4 sub ReadVal,10
invoke Poke, Address, addr ReadVal, 4
Freezing values
Ok so what you need to do it Read your Values you want to freeze, then chill them to 0 degrees
Celcius.. ok well maybe it doesn't quite work like that, it's more of a read to a value then constantly
write it back to the program.. To start all this off, We need to set up a timer, taking a quick look in our
handy API guide, we see that there's a nice function to do this. One known as SetTimer. Looking at
that function we see that you have to define, the hwnd, the Timer ID, How often the Timer functions
are done, and a Timer Proc for the functions. So lets start our defining, we shall start by defining the
SetTimer, the best place to do so(in my opinion for a small project like this) is right before creating
the dialog.
Change this:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParamA,hInstance,ID_DLG,0,addr
DlgProc,0
To this:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke SetTimer,hInstance,1,90,DoTimer invoke
DialogBoxParamA,hInstance,ID_DLG,0,addr DlgProc,0
now add this among your already existing proto's
DoTimer proto
and now add this proc under your .code section, before the end start.
DoTimer Proc
DoTimer endp
Now that you've got your timer set up, you're most likely wondering how to use it to freeze values..
Well first you'll need a flag to tell the timer either to poke the memory, or not to poke the memory. A
simple flag looks like this under your .data? section.
State db ?
Next you must add functions to a button to read the original value and toggle the flag.
invoke Peek, Address, addr ReadVal, 4 mov State,1
Then define the write memory actions into the timer.
DoTimer Proc
.if State ==1
invoke Poke, Address, addr ReadVal, 4
.endif
DoTimer endp
To Unfreeze the value simply change the flag to a different number, which goes something like this.
mov State,91
So there you have it, a few uses of the ReadProcessMemory API..
**********************************************************
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**********************************************************
INTRODUCTION
------------
On this series of tutorials, I *WILL* try and teach you how to program in
Win32ASM (mASM Specific). There is a great tutorial by rECLAIM in TASM, which
helped me in the process of learning. But 90% ASM programmers code in mASM
so its a good choice. If you got stuck in a code, you can get support easily.
WHY MASM?
---------
1. MASM improves the readability of your source code and makes learning ASM
a lot easier.
push param4
push param3
push param2
push param1
call API
While in MASM:
These are:
.IF, .ELSEIF, .ELSE, .ENDIF
.REPEAT, .UNTIL
.WHILE, .ENDW, .BREAK
.CONTINUE
Give yourself a break and dont write rc scripts. (ONLY USED BY PEOPLE
WHO VALUE THEIR TIME)
3. TEXT EDITOR --
MASM package includes a text editor (I dont use that though). Just use
a text editor with SYNTAX HIGHLITING *VERY USEFUL*. I use ULTRAEDIT.
OPCODES
-------
OPCODES are the instructions for the Processor. Here are the OPCODES NEEDED.
OPCODE MEANS
REGISTERS
---------
eax ax ah al ACCUMULATOR
ebx bx bh bl BASE
ecx cx ch bl COUNTER
edx dx dh dl DATA
Although they have names, you can use them for anything.
WINAPI
------
These are the set of functions provided by the system. The heart of
Windows Programming.
Contact
-------
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**********************************************************
WHAT NOW?
---------
WHAT YA NEED
------------
API's TO USE
------------
1. GetModuleHandle
2. DialogBoxParam
3. SetTimer
4. LoadIcon
5. SendMessage
6. ExitProcess
7. MessageBox
8. GetAsyncKeyState
9. FindWindow
10. GetWindowThreadProcessId
11. OpenProcess
12. ReadProcessMemory
13. WriteProcessMemory
14. CloseHandle
TRAINER ROUTINE
---------------
If you have seen the source you will see the TrainerEngine Procedure. I have mad
this procedure to make programming easier. It takes care of editing game values.
Very Useful if you have *MANY HOTKEYS*.
The SourceCode
--------------
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib
DlgProc PROTO :DWORD, :DWORD, :DWORD, :DWORD ;Declare Procedures
TrainerEngine PROTO :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
.data
;the variables
buffer1 dd ? ; buffer to place read data
hInstance dd ? ; handle of our program
_hanicon dd ? ; handle of icon
windhand dd ? ; window handle
phandle dd ? ; process handle of game
pid dd ? ; process id of game
.const
DIALOG105 equ 105 ;
ICON106 equ 107 ;look at the resource file
ABOUTBUT equ 101 ;for these constants
HELPBUT equ 102 ;
addie1 equ 401384h ;CHANGE!!! your address to edit
addie2 equ 41D090h ;CHANGE!!! your address to edit (h means hexadecimal)
.code
; Call DialogBoxParam, handle of our prog, our dialog for trainer.res, NULL, adre
Invoke DialogBoxParam, hInstance, DIALOG105 , NULL, offset DlgProc, NULL
pushad ;Saving registry is needed... the program will crash if you omit th
.elseif uMsg == WM_CLOSE ;Did the user close the Dialog Box?
.endif
.endif
DlgProc ENDP
TrainerEngine PROC lpWindCap:DWORD, lpAdress:DWORD, lpNewValue:DWORD, nAdd:DWORD,
.endif
.endif
TrainerEngine ENDP
end c_mahal
ASSEMBLING
----------
@echo off
ml /c /coff /Cp trainer.asm
link /subsystem:windows /LIBPATH:c:\masm32\lib trainer.obj trainer.res
pause>nul
3. Save it as make.bat
4. Run make.bat
FINAL WORDS
-----------
You can modify the source in any way you want. If you have any questions
and shit... don't hesitate, e-mail me tsongkie@gamefreaks.ph
Archea Hacking - Trainers in MASM 1
[Written by Archea254]
All of the code examples used here are written in MASM, if you havn't
downloaded the example code you will need to download it now!
http://primal.framper.com/Downloads/antidebugmasm.zip
Say for example you press a button on a program and a messagebox pops up.
When you pressed that button, the program calls USER32.DLL and imports
what it needs to make the messagebox! Since USER32.DLL is an import.
If one wanted to find where the offset inside of the executable that calls
USER32.DLL is, they would type bpx messageboxa into softice or any other
similar debugger and the debugger could get the offset by patching the
MESSAGEBOXA offset within USER32.DLL.
Now that we know how a debugger works let's describe some ways to defeat
debuggers! :D
Ok, let's get started! Let's discuss some of the more direct methods
of debugger detection!
TSPYVXD db '\\.\TRASPY',0
That about it, there are a few other ways; but these are the most popular and
I don't feel like listing anymore...
Ok, now that we have established techniques trainer spy, let's go and talk about
and 16bit debuggers and direct ways to specifically detect them!...
The way you detect a 16bit debugger in masm is by using the IsDebuggerPresent.
It will return 1 if a dos debugger is present. Basically from my observations
it will only detect dos debuggers. So softice we will not be detected!
invoke IsDebuggerPresent
cmp eax,1
je @@16bit
There are a few ways to detect if softice is running or installed on the users
system. As we mentioned in the trainer spy section there is a bit of code that
can be used to detect the presence of certain vxds in memory. Softice actually
has 2 vxds.. SICE and SIWVID... using the same bit of code should work perfectly!
.data
.code
Start:
Argh! That was a lot of typing ;) That's about all I feel like listing for now!
Now that we have successfully digested the milk let's go right on to the meat!
Now we will be discussing the best ways [in this tutorial] to detect if a
debugger is present!
Pretty simple, huh? ;) This little trick will fool almost all newbies..
However, there are tricks that can fool this code into thinking everything
is all ok. It's fine for now untill you start studying anti-anti-debugger
tricks. But by then you should know enough on how to protect your programs! ;)
Now let's talk about the exceptions handler technique.. This is also a very simpl
and effective technique. It's very similar to the above code except it detects if
a debugger is patching any import table. If a debugger is not detected it then
calls a protocol, which in this case I have named startproc.
Below int 3 you should call a messagebox with an exitprocess or something along
that line, as it just continues on if the debugger is found...
Well, that's about all I feel about writting about now! You should know enough no
to keep most of your code safe as long as an intelligent, hardcoded, and dedicate
cracker doesn't want to take a peek at anything! ;) But if someone does get a pie
of your code don't blame me! After all, someone has to be within that 5% ;P
;*************************************
; NO NEED TO CHANGE THIS SECTION
;*************************************
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\shell32.inc
include \masm32\include\kernel32.inc
include \MASM32\INCLUDE\masm32.inc
include \MASM32\INCLUDE\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \MASM32\LIB\masm32.lib
includelib \MASM32\lib\user32.lib
includelib \MASM32\lib\shell32.lib
;*************************************
;*************************************
;*************************************
; REFERENCE TO DIALOG OBJECT (in res file)
;*************************************
;**Make sure the ID in the res files is the same as your ID here
;**If your 1st button = 101 in res, put your ID_ON = 101 too
ID_DLG equ 100 ;your dialog id
ID_ON equ 101 ;1st button id
ID_OFF equ 102 ;2nd button id
ID_QUIT equ 103 ;exit button id
;*************************************
;*************************************
;*************************************
; NO NEED TO CHANGE THIS SECTION
;*************************************
;Write value to address specified
Poke Proc lpBaseAddress: DWORD, nValue: DWORD, bie: DWORD
invoke FindWindowExA,0,0,0,addr gamenamehere
invoke GetWindowThreadProcessId,eax,addr Dummy
invoke OpenProcess,PROCESS_ALL_ACCESS,0,Dummy
mov hProcess,eax
invoke VirtualProtectEx,hProcess,lpBaseAddress,bie,PAGE_EXECUTE_READWRITE,addr D
invoke WriteProcessMemory,hProcess,lpBaseAddress,addr nValue,bie,addr Dummy
invoke CloseHandle,hProcess
ret
Poke endp
end main ;Remember, if you change 'main' at the begining of this 'code' change th
*************************************
below this, you can write anything &
it wont be compile inside the trainer
Suitable for u to write note or something
Razali Rambli
Malaysia
razali_bie@hotmail.com
http://bie.cjb.net
Devious (http://www.devious.tsongkie.com)
CES (http://www.gamehacking.com)
Extalia (http://www.extalia.com)
UnknownCheat (http://www.unknowncheats.com)
XCheater.com
and all over the world, past, future, present.
History:
;;
;; Note by Uwe E. Schirm:
;; This refers to the 'Anti Debugging Tricks' by Inbar Raz
;; which is also found in the 80XXX Snippets as ANTIDBG.TXT
;;
Sun 24 Jan 93
By: Michael Forrest
> This is a really nasty trick, and it should be used ONLY if you
> are ABSOLUTELY sure that your programs needs no more debugging.
It IS a really nasty trick against a real-mode debugger like Debug or
something else available 5-10 years ago, but completely useless against
Soft-ICE, TD386, or any other protected mode debugger.
> This method simply retains the value of the clock counter, updated
> by interrupt 08h, and waits in an infinite loop until the value
> changes. This method is usefull only against RUN actions, not
> TRACE/PROCEED ones.
That'll defeat DEBUG and not much else. Any other debugger has a key
that'll break into the code. At that point, one could go into trace
mode or just replace the JZ 0109 with a series of NOP instructions.
> This is a very nice technique, that works especially and only on
> those who use Turbo Debugger or its kind. What you should do is
> init a jump to a middle of an instruction, whereas the real address
> actually contains another opcode.
I'm not really sure what you're trying to accomplish here, but it
doesn't do much. A simple "U CS:IP" or its equivalent in any other
debugger will show the current instruction. Anyway, the code isn't
correct.
IN AL,21 IN AL,21h
MOV AL,FF MOV AL,0ffh
JMP 0108 JMP 108
MOV Byte Ptr [21E6],00 ---> MOV BYTE PTR [21e6h],0cdh
INT 20 ---> db 20h
> This is a nice trick, effective against almost any real mode
> debugger. What you should do is simply set the trace flag off
> somewhere in your program, and check for it later.
Assembling a NOP over the int 3 will get rid of the break. Also, many
debuggers (like Soft-ICE) can be set to not break on an INT 3.
> This trick is based on the fact that debuggers don't usually use a
> stack space of their own, but rather the user program's stack space.
I'm not sure where you're getting this, but today's debuggers keep their
own stack safely hidden away in a protected segment where your program
can't corrupt it. This is also only effective against real-mode
debuggers if you intend to run your entire routine with interrupts
cleared, since most ISR's depend on your stack being there as well.
> This is a nice way to fool Turbo Debugger's V8086 module (TD386).
> It is based on the fact that TD386 does not use INT 00h to detect
> division by zero.
Did you actually try this? It doesn't seem to have much effect at all
on TD386. Soft-ICE traces through it quite happily too.
Yes, and in a debugger it's _really_ easy to change the code while
you're tracing through it to jump right over the offending instruction.
All that you've done is eliminated compatibility with a lot of systems.
> The first category is simply a code, that has been encrypted,
> and has been added a decryption routine. The trick here is that
> when a debugger sets up a breakpoint, it simply places the opcode
> CCh (INT 03h) in the desired address, and once that interrupt is
> executed, the debugger regains control of things.
ANY decent debugger these days will let you use hardware breakpoints
which have nothing to do with INT 3 or any other instruction replacing
existing code. They'll let you set breakpoints wherever you'd like
without messing up encryption routines or self-modifying code.
I had to change the routine you included since it doesn't handle multi-
byte instructions very well.
* DSE Online! * The Home of PB/VISION & PB/WORKSHOP for PowerBASIC 3.0
--
/\/ Daniel P. Stasinski /\/ Voice: +1-707-459-4358 /\/
/\/ DSE Software Publishing /\/ FAX/BBS: +1-707-459-4484 /\/
/\/ Post Office Box 96 /\/ Email: dse@pacific.net /\/
/\/ Willits, CA 95490-0096 /\/ FidoNet: 1:125/123 /\/
Tutorial 28: Win32 Debug API Part 1
In this tutorial, you'll learn what Win32 offers to developers regarding debugging primitives. You'll
know how to debug a process when you're finished with this tutorial.
Theory:
Win32 has several APIs that allow programmers to use some of the powers of a debugger. They are
called Win32 Debug APIs or primitives. With them, you can:
In short, you can code a simple debugger with those APIs. Since this subject is vast, I divide it into
several managable parts: this tutorial being the first part. I'll explain the basic concepts and general
framework for using Win32 Debug APIs in this tutorial.
The steps in using Win32 Debug APIs are:
1. Create a process or attach your program to a running process. This is the first step in using
Win32 Debug APIs. Since your program will act as a debugger, you need a program to debug.
The program being debugged is called a debuggee. You can acquire a debuggee in two ways:
You can create the debuggee process yourself with CreateProcess. In order to create a
process for debugging, you must specify the DEBUG_PROCESS flag. This flag tells
Windows that we want to debug the process. Windows will send notifications of important
debugging-related events (debug events) that occur in the debuggee to your program. The
debuggee process will be immediately suspended until your program is ready. If the
debuggee also creates child processes, Windows will also send debug events that occur in
all those child processes to your program as well. This behavior is usually undesirable.
You can disable this behavior by specifying DEBUG_ONLY_THIS_PROCESS flag in
combination of DEBUG_PROCESS flag.
You can attach your program to a running process with DebugActiveProcess.
2. Wait for debugging events. After your program acquired a debuggee, the debuggee's primary
thread is suspended and will continue to be suspended until your program calls
WaitForDebugEvent. This function works like other WaitForXXX functions, ie. it blocks the
calling thread until the waited-for event occurs. In this case, it waits for debug events to be sent
by Windows. Let's see its definition:
dwMilliseconds is the length of time in milliseconds this function will wait for the debug event
to occur. If this period elapses and no debug event occurs, WaitForDebugEvent returns to the
caller. On the other hand, if you specify INFINITE constant in this argument, the function will
not return until a debug event occurs.
DEBUG_EVENT STRUCT
dwDebugEventCode dd ?
dwProcessId dd ?
dwThreadId dd ?
u DEBUGSTRUCT <>
DEBUG_EVENT ENDS
dwDebugEventCode contains the value that specifies what type of debug event occurs. In short,
there can be many types of events, your program needs to check the value in this field so it
knows what type of event occurs and responds appropriately. The possible values are:
Value Meanings
A process is created. This event will be sent when
the debuggee process is just created (and not yet
CREATE_PROCESS_DEBUG_EVENT running) or when your program just attaches itself
to a running process with DebugActiveProcess.
This is the first event your program will receive.
EXIT_PROCESS_DEBUG_EVENT A process exits.
A new thread is created in the debuggee process or
when your program first attaches itself to a running
CREATE_THEAD_DEBUG_EVENT process. Note that you'll not receive this
notification when the primary thread of the
debuggee is created.
A thread in the debuggee process exits. Your
program will not receive this event for the primary
thread. In short, you can think of the primary thread
of the debuggee as the equivalent of the debuggee
EXIT_THREAD_DEBUG_EVENT process itself. Thus, when your program sees
CREATE_PROCESS_DEBUG_EVENT, it's
actually the
CREATE_THREAD_DEBUG_EVENT for the
primary thread.
The debuggee loads a DLL. You'll receive this
event when the PE loader first resolves the links to
LOAD_DLL_DEBUG_EVENT DLLs (you call CreateProcess to load the
debuggee) and when the debuggee calls
LoadLibrary.
UNLOAD_DLL_DEBUG_EVENT A DLL is unloaded from the debuggee process.
An exception occurs in the debuggee process.
Important: This event will occur once just before
the debuggee starts executing its first instruction.
The exception is actually a debug break (int 3h).
When you want to resume the debuggee, call
EXCEPTION_DEBUG_EVENT
ContinueDebugEvent with DBG_CONTINUE
flag. Don't use
DBG_EXCEPTION_NOT_HANDLED flag else
the debuggee will refuse to run under NT (on
Win98, it works fine).
This event is generated when the debuggee calls
OUTPUT_DEBUG_STRING_EVENT DebugOutputString function to send a message
string to your program.
RIP_EVENT System debugging error occurs
dwProcessId and dwThreadId are the process and thread Ids of the process that the debug event
occurs. You can use these values as identifiers of the process/thread you're interested in.
Remember that if you use CreateProcess to load the debuggee, you also get the process and
thread IDs of the debuggee in the PROCESS_INFO structure. You can use these values to
differentiate between the debug events occurring in the debuggee and its child processes (in case
you didn't specify DEBUG_ONLY_THIS_PROCESS flag).
u is a union that contains more information about the debug event. It can be one of the following
structures depending on the value of dwDebugEventCode above.
I won't go into detail about all those structures in this tutorial, only the
CREATE_PROCESS_DEBUG_INFO structure will be covered here.
Assuming that our program calls WaitForDebugEvent and it returns. The first thing we should
do is to examine the value in dwDebugEventCode to see which type of debug event occured in
the debuggee process. For example, if the value in dwDebugEventCode is
CREATE_PROCESS_DEBUG_EVENT, you can interpret the member in u as
CreateProcessInfo and access it with u.CreateProcessInfo.
This function resumes the thread that was previously suspended because a debug event occurred.
dwProcessId and dwThreadId are the process and thread IDs of the thread that will be
resumed. You usually take these two values from the dwProcessId and dwThreadId members of
the DEBUG_EVENT structure.
dwContinueStatus specifies how to continue the thread that reported the debug event. There are
two possible values: DBG_CONTINUE and DBG_EXCEPTION_NOT_HANDLED. For all
other debug events, those two values do the same thing: resume the thread. The exception is the
EXCEPTION_DEBUG_EVENT. If the thread reports an exception debug event, it means an
exception occurred in the debuggee thread. If you specify DBG_CONTINUE, the thread will
ignore its own exception handling and continue with the execution. In this scenario, your
program must examine and resolve the exception itself before resuming the thread with
DBG_CONTINUE else the exception will occur again and again and again.... If you specify
DBG_EXCEPTION_NOT_HANDLED, your program is telling Windows that it didn't handle
the exception: Windows should use the default exception handler of the debuggee to handle the
exception.
In conclusion, if the debug event refers to an exception in the debuggee process, you should call
ContinueDebugEvent with DBG_CONTINUE flag if your program already removed the cause
of exception. Otherwise, your program must call ContinueDebugEvent with
DBG_EXCEPTION_NOT_HANDLED flag. Except in one case which you must always use
DBG_CONTINUE flag: the first EXCEPTION_DEBUG_EVENT which has the value
EXCEPTION_BREAKPOINT in the ExceptionCode member. When the debuggee is going to
execute its very first instruction, your program will receive the exception debug event. It's
actually a debug break (int 3h). If you respond by calling ContinueDebugEvent with
DBG_EXCEPTION_NOT_HANDLED flag, Windows NT will refuse to run the debuggee
(because no one cares for it). You must always use DBG_CONTINUE flag in this case to tell
Windows that you want the thread to go on.
5. Continue this cycle in an infinite loop until the debuggee process exits. Your program must
be in an infinite loop much like a message loop until the debuggee exits. The loop looks like this:
.while TRUE
invoke WaitForDebugEvent, addr DebugEvent, INFINITE
.break .if DebugEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
<Handle the debug events>
invoke ContinueDebugEvent, DebugEvent.dwProcessId, DebugEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED
.endw
Here's the catch: Once you start debugging a program, you just can't detach from the debuggee
until it exits.
Example:
This example debugs a win32 program and shows important information such as the process handle,
process Id, image base and so on.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\user32.lib
.data
AppName db "Win32 Debug Example no.1",0
ofn OPENFILENAME <>
FilterString db "Executable Files",0,"*.exe",0
db "All Files",0,"*.*",0,0
ExitProc db "The debuggee exits",0
NewThread db "A new thread is created",0
EndThread db "A thread is destroyed",0
ProcessInfo db "File Handle: %lx ",0dh,0Ah
db "Process Handle: %lx",0Dh,0Ah
db "Thread Handle: %lx",0Dh,0Ah
db "Image Base: %lx",0Dh,0Ah
db "Start Address: %lx",0
.data?
buffer db 512 dup(?)
startinfo STARTUPINFO <>
pi PROCESS_INFORMATION <>
DBEvent DEBUG_EVENT <>
.code
start:
mov ofn.lStructSize,sizeof ofn
mov ofn.lpstrFilter, offset FilterString
mov ofn.lpstrFile, offset buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke GetStartupInfo,addr startinfo
invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+
DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi
.while TRUE
invoke WaitForDebugEvent, addr DBEvent, INFINITE
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke MessageBox, 0, addr ExitProc, addr AppName, MB_OK+MB_ICONINFORMATION
.break
.elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ProcessInfo, DBEvent.u.CreateProcessInfo.hFile,
DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread,
DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_CONTINUE
.continue
.endif
.elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT
invoke MessageBox,0, addr NewThread, addr AppName, MB_OK+MB_ICONINFORMATION
.elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT
invoke MessageBox,0, addr EndThread, addr AppName, MB_OK+MB_ICONINFORMATION
.endif
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED
.endw
invoke CloseHandle,pi.hProcess
invoke CloseHandle,pi.hThread
.endif
invoke ExitProcess, 0
end start
Analysis:
The program fills the OPENFILENAME structure and then calls GetOpenFileName to let the user
choose a program to be debugged.
When the user chose one, it calls CreateProcess to load the program. It calls GetStartupInfo to fill
the STARTUPINFO structure with its default values. Note that we use DEBUG_PROCESS
combined with DEBUG_ONLY_THIS_PROCESS flags in order to debug only this program, not
including its child processes.
.while TRUE
invoke WaitForDebugEvent, addr DBEvent, INFINITE
When the debuggee is loaded, we enter the infinite debug loop, calling WaitForDebugEvent.
WaitForDebugEvent will not return until a debug event occurs in the debuggee because we specify
INFINITE as its second parameter. When a debug event occurred, WaitForDebugEvent returns and
DBEvent is filled with information about the debug event.
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke MessageBox, 0, addr ExitProc, addr AppName, MB_OK+MB_ICONINFORMATION
.break
We first check the value in dwDebugEventCode. If it's EXIT_PROCESS_DEBUG_EVENT, we
display a message box saying "The debuggee exits" and then get out of the debug loop.
.elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ProcessInfo, DBEvent.u.CreateProcessInfo.hFile,
DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread,
DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress
invoke MessageBox,0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_CONTINUE
.continue
.endif
.elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT
invoke MessageBox,0, addr NewThread, addr AppName, MB_OK+MB_ICONINFORMATION
.elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT
invoke MessageBox,0, addr EndThread, addr AppName, MB_OK+MB_ICONINFORMATION
.endif
invoke CloseHandle,pi.hProcess
invoke CloseHandle,pi.hThread
When the debuggee exits, we are out of the debug loop and must close both process and thread
handles of the debuggee. Closing the handles doesn't mean we are killing the process/thread. It just
means we don't want to use those handles to refer to the process/thread anymore.
Tutorial 29: Win32 Debug API Part 2
We continue with the subject of win32 debug API. In this tutorial, we will learn how to modify the
debuggee process.
Theory:
In the previous tutorial, we know how to load the debuggee and handle debug events that occur in its
process. In order to be useful, our program must be able to modify the debuggee process. There are
several APIs just for this purpose.
ReadProcessMemory This function allows you to read memory in the specified process. The
function prototype is as follows:
The next two API functions need a little background on context. Under a multitasking OS like
Windows, there can be several programs running at the same time. Windows gives each thread a
timeslice. When that timeslice expires, Windows freezes the present thread and switches to the
next thread that has the highest priority. Just before switching to the other thread, Windows saves
values in registers of the present thread so that when the time comes to resume the thread,
Windows can restore the last *environment* of that thread. The saved values of the registers are
collectively called a context.
Back to our subject. When a debug event occurs, Windows suspends the debuggee. The
debuggee's context is saved. Since the debuggee is suspended, we can be sure that the values in
the context will remain unchanged . We can get the values in the context with
GetThreadContext and we can change them with SetThreadContext.
These two APIs are very powerful. With them, you have at your fingertips the VxD-like power
over the debuggee: you can alter the saved register values and just before the debuggee resumes
execution, the values in the context will be written back into the registers. Any change you made
to the context is reflected back to the debuggee. Think about it: you can even alter the value of
the eip register and divert the flow of execution to anywhere you like! You won't be able to do
that under normal circumstance.
hThread is the handle to the thread that you want to obtain the context from
lpContext is the address of the CONTEXT structure that will be filled when the function
returns successfully.
SetThreadContext has exactly the same parameters. Let's see what a CONTEXT structure
looks like:
CONTEXT STRUCT
ContextFlags dd ?
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value
CONTEXT_DEBUG_REGISTERS
;-----------------------------------------------------------------------------------------------------------
iDr0 dd ?
iDr1 dd ?
iDr2 dd ?
iDr3 dd ?
iDr6 dd ?
iDr7 dd ?
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value
CONTEXT_FLOATING_POINT
;-----------------------------------------------------------------------------------------------------------
FloatSave FLOATING_SAVE_AREA <>
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value CONTEXT_SEGMENTS
;-----------------------------------------------------------------------------------------------------------
regGs dd ?
regFs dd ?
regEs dd ?
regDs dd ?
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value CONTEXT_INTEGER
;-----------------------------------------------------------------------------------------------------------
regEdi dd ?
regEsi dd ?
regEbx dd ?
regEdx dd ?
regEcx dd ?
regEax dd ?
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value CONTEXT_CONTROL
;-----------------------------------------------------------------------------------------------------------
regEbp dd ?
regEip dd ?
regCs dd ?
regFlag dd ?
regEsp dd ?
regSs dd ?
;----------------------------------------------------------------------------------------------------------
; This section is returned if ContextFlags contains the value
CONTEXT_EXTENDED_REGISTERS
;-----------------------------------------------------------------------------------------------------------
ExtendedRegisters db MAXIMUM_SUPPORTED_EXTENSION dup(?) CONTEXT ENDS
As you can observe, the members of this structures are mimics of the real processor's registers.
Before you can use this structure, you need to specify which groups of registers you want to
read/write in ContextFlags member. For example, if you want to read/write all registers, you
must specify CONTEXT_FULL in ContextFlags. If you want only to read/write regEbp,
regEip, regCs, regFlag, regEsp or regSs, you must specify CONTEXT_CONTROL in
ContextFlags.
One thing you must remember when using the CONTEXT structure: it must be aligned on dword
boundary else you'd get strange results under NT. You must put "align dword" just above the line
that declares it, like this:
align dword
MyContext CONTEXT <>
Example:
The first example demonstrates the use of DebugActiveProcess. First, you need to run a target named
win.exe which goes in an infinite loop just before the window is shown on the screen. Then you run
the example, it will attach itself to win.exe and modify the code of win.exe such that win.exe exits the
infinite loop and shows its own window.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\user32.lib
.data
AppName db "Win32 Debug Example no.2",0
ClassName db "SimpleWinClass",0
SearchFail db "Cannot find the target process",0
TargetPatched db "Target patched!",0
buffer dw 9090h
.data?
DBEvent DEBUG_EVENT <>
ProcessId dd ?
ThreadId dd ?
align dword
context CONTEXT <>
.code
start:
invoke FindWindow, addr ClassName, NULL
.if eax!=NULL
invoke GetWindowThreadProcessId, eax, addr ProcessId
mov ThreadId, eax
invoke DebugActiveProcess, ProcessId
.while TRUE
invoke WaitForDebugEvent, addr DBEvent, INFINITE
.break .if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
.if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, addr context
invoke WriteProcessMemory, DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr
buffer, 2, NULL
invoke MessageBox, 0, addr TargetPatched, addr AppName,
MB_OK+MB_ICONINFORMATION
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
invoke ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId,
DBG_CONTINUE
.continue
.endif
.endif
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,
DBG_EXCEPTION_NOT_HANDLED
.endw
.else
invoke MessageBox, 0, addr SearchFail, addr AppName,MB_OK+MB_ICONERROR .endif
invoke ExitProcess, 0
end start
;--------------------------------------------------------------------
; The partial source code of win.asm, our debuggee. It's actually
; the simple window example in tutorial 2 with an infinite loop inserted
; just before it enters the message loop.
;----------------------------------------------------------------------
......
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL
mov hwnd,eax
jmp $ <---- Here's our infinite loop. It assembles to EB FE
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.while TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.break .if (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endw
mov eax,msg.wParam
ret
WinMain endp
Analysis:
invoke FindWindow, addr ClassName, NULL
Our program needs to attach itself to the debuggee with DebugActiveProcess which requires the
process Id of the debuggee. We can obtain the process Id by calling GetWindowThreadProcessId
which in turn needs the window handle as its parameter. So we need to obtain the window handle
first.
With FindWindow, we can specify the name of the window class we need. It returns the handle to the
window created by that window class. If it returns NULL, no window of that class is present.
.if eax!=NULL
invoke GetWindowThreadProcessId, eax, addr ProcessId
mov ThreadId, eax
invoke DebugActiveProcess, ProcessId
After we obtain the process Id, we can call DebugActiveProcess. Then we enter the debug loop
waiting for the debug events.
.if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, addr context
Now that we get the value of eip, we can call WriteProcessMemory to overwrite the "jmp $"
instruction with NOPs, thus effectively help the debuggee exit the infinite loop. After that we display
the message to the user and then call ContinueDebugEvent to resume the debuggee. Since the "jmp
$" instruction is overwritten by NOPs, the debuggee will be able to continue with showing its
window and enter the message loop. The evidence is we will see its window on screen.
The other example uses a slightly different approach to break the debuggee out of the infinite loop.
.......
.......
.if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread, addr context
add context.regEip,2
invoke SetThreadContext,DBEvent.u.CreateProcessInfo.hThread, addr context
invoke MessageBox, 0, addr LoopSkipped, addr AppName, MB_OK+MB_ICONINFORMATION
.......
.......
It still calls GetThreadContext to obtain the current value of eip but instead of overwriting the "jmp
$" instruction, it increments the value of regEip by 2 to "skip over" the instruction. The result is that
when the debuggee regains control , it resumes execution at the next instruction after "jmp $".
Now you can see the power of Get/SetThreadContext. You can also modify the other register images
as well and their values will be reflected back to the debuggee. You can even insert int 3h instruction
to put breakpoints in the debuggee process.
$$$$$$$$$$$$$$$$$ : $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$ : /| ?_?_? $
$ ._ / |__ ____ ____ ____ ____ ____ ____ $
$ ____| \/ \ _/ \/ \_ /: \/ \_ / ? \ $
$ / |o \ _// _\ | _/_|\ \ |/ ? \_ $
$ \ : /_ ) ____ \/\ |/ / \ _|_ \ $
$ / . \ \/ \ \ | / ?_ \ | /\/? ? $
$ / \ / \ / | \ | / _? + $
$ _ _ \__ |_____/___/\ /:___ /____ /__|_ / | \ \ / $
$ | | rECLAIM |/ |/ |/ \_:_/ | \ \ / $
$ |_ | : : : \_ ? _\ \_/ $
$$$$$$$$ \ | $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$: \___/\___/ $$$$$$$$$$$$$$
\|
:
Chapters....
*********************************************************************************
CHAPTER i)
==========
Intro : Hey guys.. ive noticed the lack of tutorials on the subject of game tr
so i decided to contribute to it and write this little essay to inform
hopefully enlighten you all to the world of Assembly language Trainer
Assembly Language has got a bad rap for being complex, and actually fo
best part of it is.. but for simple programs such as the one we will b
there is no REAL complexity.... I`ll endevour to explain everything as
First of all you may be asking yourself why bother with Assembly langu
create my trainers when there are simple trainer maker kits out there.
the benefits from creating your own trainer (in any programming langua
limitless.. but the main advantages are size and flexibility... the co
be showing you today will compile into a 8k program.. if you zip it yo
take it down to 1k... MAN!! considering that most trainers are like 10
hope this gives you some insentive to carry on reading... :o)
Needed : Something to create the asm program in (Text Editor), all my code is T
specific.. so its a good idea to get that.. a resource editor to edit
file which contains the main dialogbox that will be created.. you will
edit this so that people know who made the trainer and that kind of th
and we will be dealing with API calls also so its a good idea to get t
referece... so...
To get the most out of this tutorial it would be best if you have a li
bit of Assembly knowledge... THIS IS NOT ESSENTIAL... because ive desi
the source code so that the real beginers can just change certain valu
then compile the source code into a program.....
*********************************************************************************
CHAPTER ii)
===========
The first thing i am going to do is list all the api calls we will be
you a run down of what they do.....I`ll explain them in the order the
use them..or there abouts :o)
-----------------------------------------------------------------------
HMODULE GetModuleHandle(
-----------------------------------------------------------------------
-----------------------------------------------------------------------
int DialogBoxParam(
UINT SetTimer(
-----------------------------------------------------------------------
-----------------------------------------------------------------------
LRESULT SendMessage(
details: Well not really too important in this tutorial i only use i
my code to load the icon.....etc..
-----------------------------------------------------------------------
-----------------------------------------------------------------------
SHORT GetAsyncKeyState(
-----------------------------------------------------------------------
-----------------------------------------------------------------------
BOOL CreateProcess(
details: This api does a lot of work for out trainer.. this is the api tha
runs the game and returns to us all the information we nee
write our trainer values into the games memory. Createproc
is our friend.. :o)
-----------------------------------------------------------------------
-----------------------------------------------------------------------
BOOL WriteProcessMemory(
details: This is obviously the most important api call we will use
the trainer because it pokes our values into the games mem
This api is our best friend :o)
-----------------------------------------------------------------------
-----------------------------------------------------------------------
int MessageBox(
details: This api is used to create a small box on the screen usual
to inform the user of some error or other activity.. In my
trainer code its used to indicate an error and also the in
on how to use the trainer.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
VOID ExitProcess(
details: well this api is called when we have finished with our tr
it closes our process down and hands control back to good
windows :o)
-----------------------------------------------------------------------
Ok.. thats all the api calls out the way.. i use a couple more in the t
i think but dont worry these are not really needed to code a trainer..
line of my code is commented to the max... so you wont get lost... :o)
*********************************************************************************
CHAPTER iii)
============
Trainer process.....
Step 4. If run game button is pressed then run the game (call createpro
Step 6. Check to see if a virtual key has been pressed (Call GetAsyncKe
Step 7. If a key has been pressed then jump to the code that writes mem
Step 9. When trainer is close down exit and return control to windows (
The above steps should make it easier to understand the already comment
*********************************************************************************
CHAPTER iv)
===========
Before we go head first into the source code, ive marked on the code places
that you need to edit to make it work with your trainer addresses... these
places are marked with a CHANGE!!! and even if you dont understand any asm
you will be able to edit these values and also the .res file (covered in the next
and then compile it.. to create your own trainers :o)
.386 ;
.Model Flat, StdCall ;
Locals ;Dont worry about this bit
jumps ;
;
UNICODE=0 ;
;************************************************
;************* Include Files ********************
; Files to include
include w32.inc ; This file contains lots
; equates for us to use wi
;************************************************
;************************************************
.Data
.data?
;***********************************************
.CODE
main:
call GetModuleHandle,0 ; Get handle for our program
mov _hInst,eax ; Store the handle of our program
Push 0 ; Initialization value
Push offset Dlg1Proc ; Address of dialogbox procedure
Push 0 ; Handle of owner window (0 = no owner)
Push DLG1 ; Dialogbox template to load (from .res)
Push _hInst ; Push the hInstance (handle of our program)
Call DialogBoxParamA ; Create the dialogbox and enter message handle
dlg1Proc proc uses ebx edi esi, _hwind:DWORD, wmsg:DWORD, wparama:DWORD, lparama:
end_it:
kill_it:
_initdlg:
events:
cmp [wparama],ABOUT_BOX ; Was the about button pressed?
jnz @next1 ; If no carry on checking for other events
call @about_box ; if yes call the about_box procedure
@next1:
cmp [wparama],RUN_GAME ; Was the Run Game buttin pressed?
jnz @next2 ; If no carry on checking for other events
call @startgame ; if yes call the start game procedure
@next2:
push VK_f1 ; CHANGE!! F1-F12 this will change the key you
call GetAsyncKeyState ; Find out....
cmp eax,0 ; If no,
jz @n1 ; Carry on and check the other keys....
call @f1 ; else, call the F1 cheat routine
@n1:
push VK_f2 ; CHANGE!! F1-F12 this will change the key you
call GetAsyncKeyState ; Find out....
cmp eax,0 ; If no,
jz @n2 ; Carry on and check the other keys....
call @f2 ; else, call the F2 cheat routine
@n2:
push VK_f3 ; CHANGE!! F1-F12 this will change the key you
call GetAsyncKeyState ; Find out....
cmp eax,0 ; If no,
jz @n3 ; Return cus there are no more keys to check...
call @f3 ; else, call the F3 cheat routine
@n3:
push VK_f4 ; CHANGE!! F1-F12 this will change the key you
call GetAsyncKeyState ; Find out....
cmp eax,0 ; If no,
jz @n4 ; Return cus there are no more keys to check...
call @f4 ; else, call the F4 cheat routine
@n4:
ret
@f1 proc
@f1 endp
@f2 proc
@f2 endp
@f3 proc
@f3 endp
@f4 proc
@f4 endp
@startgame proc
@okie:
@startgame endp
dlg1Proc endp
@about_box proc
@about_box endp
@error proc
@error endp
End main
;*************** FEW!!!! We made it!! i hope you understood it.. :o) ************
*********************************************************************************
CHAPTER v)
===========
In this chapter i will just go quickly through how to edit a .res file..
DIALOG
104
ICON
105
Step 5. Click on the 104 and you will see a dialogbox appear in the r
hand window.
Step 6. Double click 104 and you go into EDIT mode.. you can now chan
all aspects of the dialogbox.. ie caption on the blue bar.. a
text and edit boxes/buttons can all be edited from here.
All you have to do to edit these RESOURCES are double click o
Step 7. When you have the dialogbox looking how you want.. then you n
goto the File menu again and click on "SAVE PROJECT" now when
compile the code it will have your new edited dialogbox. :o)
*********************************************************************************
CHAPTER vi)
===========
Ok I`m assuming if you have got this far then you really want to code an
so i will do you all a favour and give you the urls for all the things t
need to complete this little asm trianer project :o)
Also i hate reading a tutorial and not being able to find the stuff i ne
WARNING!!! i dont know how long these urls with be around for, i will tr
urls that are on stable sites.. but be warned.
2. Tasm 5.0.. This zip file has got all the files you need to compile
the trainer.. all you have to do is change the source
code and the .res file.. I have included the TRAINER.ASM
and the TRAINER.RES inside this zipfile.
http://www.cronus.spaceports.com/~reclaim/tasmbuild.zip
*********************************************************************************
CHAPTER vii)
============
Ok.. finally i will tell you how to obtain a fully working trainer onc
have edited the source code and .res file... its very simple really..
The TRAINER.ASM and TRAINER.RES have also been included in the tasmbui
so you will either have to edit these files or overwrite them with you
own TRAINER.ASM and TRAINER.RES
*********************************************************************************
CHAPTER viii)
=============
Ok.. final words from me.. You are all free to change my source code
way you want to... be my guest... i hope this short essay has taught y
something.. i also hope you will send me your comments good or bad.. :
email me at... reclaim@operamail.com....
The source code in this tutorial is nothing special in fact its not al
useful.. because it uses a simple writeprocessmemory api to write a co
of bytes into a games memory.. this will be of no use when you have lo
addresses and different values to patch.. which is sometimes the case.
i have done is designed an engine for my trainers. which is basically
set of asm instructions that do a certain task but over and over again
The engine i use is simple but well designed, instead of constantly wr
the writeprocessmemory api.. it just needs values passed to it and it
the work for you.. this makes my trainers very small... well until i s
picture on them anyways :o)
1 last thing.. the source in this essay is included in this essay zipf
dont need to cut and paste... :o)
If i have a good responce from this essay i will write another 1 cover
i designed my trainer engine and also how to defeat trainer spy with l
tricks....etc...
.........................
RECLAIM!
-
-----=========-----
-------==========================================----------
----------=====_masta_'s tut on win32-ASM-coding part 2 revision 1=====----------
-------==========================================----------
--==INTRO==--
Hi,
since part0 and part1 have been relatively successful, I am happy to
present you part2 now.
Actually I wanted to do something on GUI, but I was very busy lately
so something without GUI-coding for now. I think it will be interesting
anyway I hope.
Starting from this tutorial I won't explain the easy things like
MessageBox anymore, because they have been fully explained in both of
the first parts. I don't think it will cause you any problem once you
did the ealier parts.
--==WHAT IS NEEDED?==--
1. Texteditor
2. TASM 5.0 with libs, etc.
3. A Windows API reference (WIN32.HLP)
4. Starcraft (ONLY for testing purposes!;])
5. some Braincells left ;)
6. some basic ASM-knowledge (earlier lessons)
7. Numega Softice 3.xx (not really a must)
Is there any gamer who doesn't apreciate little aids sometimes ...
more lives
more money
more energy
more gas
more ...
--==STRUCTURE==--
3. OpenProcess
4. Change values
--==IMPORTANT API-FUNCTIONS==--
The handle of the main window we can get with FindWindowA, where we gotta
get the name of the windowclass ("SWarrClass") and the name of the window
("Starcraft"). We can do this with the help of Softice (TASK->HWND).
With the windowhandle we can get the corresponding process, or rather PID
by using GetWindowThreadProcessId.
Now we take a handle of the memory area of the process with the help of
the PID -> OpenProcess.
We can easily get the adds of for example the minerals by using a debugger
and searching for the hex-values of the decimal-values shown on the screen.
In my version it it like the following:
Minerals = 04EFE08h
Gas = 04EFE38h
--==THE SOURCE==--
This time not very long and as usual not very good structured, but should
be easy to understand anyway ...
mb_ok equ 0
minerals_pos equ 04efe08h
gas_pos equ 04efe38h
; Introtext , 0-terminated
is_SC_RUN:
open_the_process:
push pid_sc ; PUSH PID
push 0 ; only used when
; building new
; processes
push PROCESS_VM_WRITE OR PROCESS_VM_OPERATION ; activate write-access
change_Minerals:
Trainer_ready:
push mb_ok
push offset readycap
push offset readytxt
push 0
call MessageBoxA ; Everything OK
close_the_PID_Handle:
push p_hand
Call CloseHandle ; CloseHandle
jmp end_ ; Go to End
error_on_write:
push mb_ok
push offset err_cap
push offset no_write
push 0
call MessageBoxA ; Mmmhhh, Error while writing
jmp close_the_PID_Handle ; Close handle before quit
SC_isnt_run_end:
push mb_ok
push offset err_cap
push offset notrun
push 0
call MessageBoxA ; nothing there to train =(
end_:
;--------------------------==END OF SOURCE==----------------------------
;--------------------------------START---------------------------make.bat
@echo off
echo assembling your trainer
tasm32 /mx /m3 /z /q w95asm_2
tlink32 -x /Tpe /aa /c w95asm_2,w95asm_2,, import32.lib
del *.obj
del *.map
;---------------------------------END----------------------------make.bat
--==FINAL WORDS==--
OK, as I told you before this was a little tutorial, but I think very
interesting anyway. I guess there is not much to optimize (sorry fungus),
maybe the routine for writing into memory (use of a procedure).
I hope my mailbox (masta_t@usa.net) is flodded soon (CRITICS ARE WELCOME)
and you are all here next time. I promise the next one will be about GUI,
because many people told me to do so.
BTW, I am trying to build an IRC channel (EFNET) on this (#win32asm) and
finally there is a project-page 'HTTP://win32asm.cjb.net'!
If anyone is interested, any contribution to this subject is very welcome,
we are waiting for it ...
I really hope there are enough people, who spend their time on this
subject and who are willing to give their knowledge to others, too.
--==GREETINX==--
VucoeT (Translator and Designer), scut (You are GREAT, why not code in Win32?),
|caligo| (bad news about you :(), fravia (best on the web), +Aescalapius
(i hope to break Brainbreaker), not4you (wir Ossis muessen zusammenhalten ;)),
fungus (something to optimze), CyberBobjr (for translating to frensh), DASavant,
mornings, i_magnus, Quest, Silvio, TheDoctor, everyone on #LAC and
#cracking4newbies and to every cracker around the world.
--==WISE WORDS==--
------===========================================================-------
-----=====A hardcoded serial is as common as a 25-year-old virgin=====------
------===========================================================-------
-----=========-----
-
Defeating Trainer Spy with Trainer Maker Kit
IntroWhen I released my first Warcraft II BNE trainer it was the very first to have upgrade
cheats for Archers/Axes and Catapults/Ballistas. Within a week at least five other trainers
were released that had the same cheats as mine. I was pissed. I've been blocking Trainer
Spy from all of my recent trainers ever since. And I'm sure some of you already noticed.
Since then none of my codes have been ripped off. I've written this tutorial so that you too
can protect your hard work from lamers.
Poke 0 FF 52 19 FF XX
You must replace XX with the number (in hex) of pokes that you want to hide. It sounds a
little complicated at first but let me give you some examples. I'll use the codes from the
starcraft mineral cheat in my first tutorial.
Poke 0 FF 52 19 FF 01
Poke 508728 FF FF
This would successfully block that button from Trainer Spy. Notice that XX is now 01
because there is one poke below to hide. You could also do this.
Poke 0 FF 52 19 FF 02
Poke 508728 FF
Poke 508729 FF
This also works. Notice that XX is now 02 because there are two pokes below it to hide.
Ok now let's say you had ten pokes to block. Would you make XX 10? NO! You would
make XX to be 0A because 0A in hex = 10 in decimal.
Refer to the Hex to Ascii chart for more help with hex.
Conclusion
This is a 99%* working method of stoping Trainer Spy. This will even stop the lamers who
hex edit their copy of Trainer Spy to change the window name.
Note: Trainer Spy is not the only way to steal codes from a trainer. Just don't ask me how.
F.Y.I. - Trainer Maker Kit and Trainer Spy were made by the same guy.
Tutorial written by Drakken
::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::
I assume you have also read part 1 and 2 of my tutorial. In the first tutorial yo
what cheating in games actually is, and how fun it is. In the second tutorial I s
to find the STATIC ADDRESS instead of a DMA (DYNAMIC MEMORY ALLOCATION).
Do you still remember what we got in the second tutorial? Here it is:
::::::::::::::::::::::::::::::::::::::::::::::::::::::
Tmk button script
Copy and Past into tmk using ctrl+V
Ex: Patched script for a ON button
and Unpatched script for a OFF button
Patched script:
Poke 464FA2 90 90 90 90 90 90
UnPatched script:
Poke 464FA2 89 8F 74 A7 D5 00
::::::::::::::::::::::::::::::::::::::::::::::::::::::
It says it is a TMK BUTTON SCRIPT. What is TMK? TMK is TRAINER MAKING KIT. It is
to build your trainer to it's physical form. Download it from:
http://fly.to/mtc
Start up TRAINER MAKER KIT (TMK) and fill in at PROJECT NAME for example "strongh
press the CREATE button. Now you are in the TMK OBJECTS screen now. Here you can
your trainer. But first we have to configure our trainer. On the down-left you se
tabs: OBJECTS, BUILD SETTINGS and HELP. Press the BUILD SETTINGS TAB.
You will see a list of the running processes (games and programs). Select the Str
Crusader Process from the list (the game must be running). Also behind EXE NAME u
PROCESS list fill in "crusadertrainer". Do NOT add .exe because TMK will do that
Okey go back to the OBJECTS tab. Rightclick on the blue space under DIALOG (your
and select PROPERTIES. Remove "Dialog" and fill in "Stronghold: Crusader Trainer"
Enter. You see that your title has changed. Now go to INSERT --> BUTTON on top of
screen. A button has appeared. Move it to the middle left of your trainer. Then a
button and move that one to the middle right of your trainer. So your trainer wil
this:
|-----------------------------|
| |
| |
| .-------. .-------. |
| |button1| |button2| |
| ------- ------- |
| |
|-----------------------------|
Rightclick on BUTTON 1 and select PROPERTIES. Change its name to ON. Do the same
and change it to OFF.
|-----------------------------|
| |
| |
| .-------. .-------. |
| | ON | | OFF | |
| ------- ------- |
| |
|-----------------------------|
Patched script:
Poke 464FA2 90 90 90 90 90 90
UnPatched script:
Poke 464FA2 89 8F 74 A7 D5 00
CONGRATULATIONS !!!
Your trainer is also saved as "crusadertrainer.exe" in it's own map under TMK dir
For example: C:/gamehacking/TMK/crusadertrainer/crusadertrainer.exe
::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::
BliZZard, blizzard_1337@hotmail.com
another tut....game hacking archive please bie?
--------------------------------
- eVoByte
--------------------------------
*-----------*
Tools Needed:
*-----------*
OllyDbg - www.evobyte.net
Brain - ...
*-----------*
This tutorial started off from some guy on btcsquad.com forums not wanting to accidently turn on options while typing in delta force. Well, there is a way to change the hotkeys but to fully
CODE
------------
Push Param5
Push Param4
Push Param3
Push Param2
Push Param1
Call ApiName
------------
The parameters are pushed onto the stack in reverse order, then the API is called. Lets take GetAsyncKeyState being as we are using it, and see what we need to be looking for:
CODE
----
SHORT GetAsyncKeyState(
int vKey
);
Parameters
vKey
[in] Specifies one of 256 possible virtual-key codes. For more information, see Virtual-Key Codes.
Windows NT/2000/XP: You can use left- and right-distinguishing constants to specify certain keys. See the Remarks section for further information.
----
Ok, so it has 1 parameter, int vKey. This is what holds the key which is being checked. So lets adapt our Push/Call method for GetAsyncKeyState :
CODE
------------
Push vKey
Call GetAsyncKeyState
------------
Now, this would be all good if the key was assembled as VbKeyNUMPAD1 or VK_NUMPAD1, but it isnt, as this isnt valid asm code. It pushes the hex value for the key instead.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcesdkr/html/_wcesdk_Virtual_Key_Codes.asp
If you goto this link and scroll down to VK_NUMPAD1, then you will see it has a hex value of 61. This means the GetAsyncKeyState for Numpad 1 will look like :
CODE
Push 61
Call GetAsyncKeyState
Alright, I'm using Diablo*GE*'s LW Trainer which you can get at www.gameditions.com, by clicking trainers, then D.
------
---
------
Ok, so, load up the trainer and press the hotkeys button. Wall Hack On = Numpad 4. Let's concentrate on changing this to key Z.
Load up OllyDbg and select the trainer to debug ( File > Open ). One thing about VB ( might be the same with C++ n asm, not checked yet ), is that the API calls are declared and then the
address is called later instead of the API name. You will see what I mean soon enough.
Right click anywhere on the main window, and goto Search For > All Referenced Text Strings. A window will pop up showing them all, so scroll down until you see:
CODE
ASCII "user32"
ASCII "GetAsycnKeyState"
on the right of the window on the Text String column. Take a note of the line number, like on this trainer of Diablo*GE*'s it is 00403B4C. Close down this Reference Window, maximize the main
Now scroll down 'til you get to the line number you just noted down. Now, there will be a block of code below it ( hopefully ). Here is what mine looks like :
CODE
------------
DD Land_War.0040E580
MOV EAX, DWORD PTR DS:[40E588]
OR EAX,EAX
JE SHORT Land_War.00403B67
JMP EAX
PUSH Land_War.00403B4C
MOV EAX,<JMP &MSVBVM50.DllFunctionCall>
CALL EAX
JMP EAX
------------
Select this whole block by selecting the first line, holding shift and then pressing the down arrow on your keyboard. Right click on the selected group and goto :
Now, another window will load up with loads of CALL's and some other stuff, but to us, only the CALL's are important. Remember above I said API's are CALLed and the parameters are PUSHed?
Well, double click on one of the CALL's and then scroll up 1 line, and there is the push =)
So, I want to change Wall Hack on mine, which was Numpad 4. If you look on the Virtual Key chart which I gave a link for earlier you will see that the Hex is 64. Double click on each Call, and
then scroll up one until you find "Push 64", and then note down the line number. For Diablo*GE*'s trainer, the address is 0040CB20. Now, finally, you can close OllyDbg but make sure you noted all
Now load up your Hex Editor. Search for the address, in my case 0040CB20.
Being as this number is a multiple of 10 ( has a 0 at the end ) it will most likely be at the beginning of a line. On other hotkeys it may be mid line though.
At 0040Cb20 there is 6A, then next to it is 64. The 6A is an opcode for PUSH, and then 64 is the value. Change the 64 to 5A ( the hex for key Z ) and then save the trainer. Go in game, press Z
and there you have it, wallhack.
Shoutouts : Diablo, Zehcnas, Just M3, i.Brid, jb, OxY, Demented, Bie, Predator, coral ( the guy who wanted hotkeys changing )
www.evobyte.net
www.gameditions.com
www.toxic-cell.net
www.btcsquad.com
www.gamehacking.com
VB hotkeys ::
You have to make a timer for hotkeys , put this code as timer code, dont ever use
if ur code was more than one line you can add them in the next line for example :
then you have to add this code to the top of your Code library so it becomes the
then you have to change the Timer Properties . change Enabled to true and interva
now we come back to timer code , we put GPS on as our example .and we want to pre
1.We have Saw Scope Code for Df2 and we want to activate it by pressing E.
undead@extalia.com
TUTORIAL WRITTEN BY x-UnDeaD
Poke 0042697C 90 90
in TMK well that is in TMK if you put your codes in that way in VB the VB gets er
( Call WriteAInt
This wont work too , so You have to put the address in Parenthesis
now You have to Put (&H) at the begging of each Value so it becomes like this
and delete the space between Those 9090 , you have to clean any spaces between He
!!! JUST KEEP IN MIND YOU CANT USE Call WriteAInt FOR ALL CODES !!!
87940 90 90 43253 90 FF
You cant put Call WriteAInt in the begging of each code line For the EVEN line yo
Another Example , Saw Scope For Df2 in VB will be written in this way :
you can look at each codes and find the tricks in it , ;).
You Can change Your Button look by select Your Button ( command ) and then go to
You Can Make your trainer Now , if You are done with ur codes and you need to get
there is View On Top Toolbar click that and then Choose Object .then you will get
Just Press File at the Top Tool bar and then CHoose "Make" whatever.exe . That is
Any Way Some of you may have known VB before , but you didnt know VB template , f
contact :undead@extalia.com
-----------------------------------------
- Using vbTrainerTemplate.zip -
- Snake -
- snake_uc@yahoo.com -
-----------------------------------------
I found this file i guess its pretty helpful to people who would like to learn ho
Im guessing since you guys are trying to learn how to write a visual basic traine
If you notice in the .bas file there is a couple of great premade functions
Before I start out with explaining the functions I will give you some definitions
Definitions
When you see &H or 0x in front of a number such as &H505050 or 0x505050 it means
Now I will start expalining the most important functions located in the .bas file
Functions Documentation
What this does is checks if there is a program running with the window title Game
For example if i wanted to read the address 4bytes from the game minesweeper at t
SEE ReadBytes()
-
-
Now this is probably what your reading this for.. How to write bytes.. This is eq
For example if you wanted to nop 4 bytes at the address 0x1005194 in Minesweeper
Buffer(0) = &H90
Buffer(1) = &H90
Buffer(2) = &H90
Buffer(3) = &H90
If you are confused with why it says (3) in Dim Buffer(3) As Byte when we are sup
These are the most important functions the other ones as self explanatory if you
-Snake
http://snakeuc.no-ip.com
Tutorial on Visual Basic by brzi
Released Under DEViOUS
brzi@devious.tsongkie.com
http://www.deviousonline.tk
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
Tools Needed :
»»»»»»»»»»»»»»
Visual Basic
Api Text Viewer (Comes with Visual Basic)
Api reference (A must have - www.win32asm.cjb.net)
A little brain to remember this
Let's Begin
»»»»»»»»»»»
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
No API's
SetWindowPos
ExitWindowsEx
ShellExecute
FindWindow
SetWindowPos - we have included this before so we dont need to write it
again
LoadString
GetModuleHandle
Sub DisplayWinUser()
Dim hInst As Integer, user As String, _
org As String, title As String, length As Integer
user = Space$(256)
org = Space$(256)
hInst = GetModuleHandle("user.exe")
length = LoadString(hInst, 514, user, Len(user))
user = Left$(user, length)
length = LoadString(hInst, 515, org, Len(org))
organization = Left$(org, length)
frmMain.lblWinUser.Caption = user
frmMain.lblWinOrg.Caption = organization
End Sub
Declare Function GetWindow Lib "user32" Alias "GetWindow" (ByVal hwnd As Long, _
ByVal wCmd As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Lon
ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Sub ArrangeIcons ()
Dim hWnd1 As Long
Dim hWnd2 As Long
Dim Ret As Long
hWnd1 = FindWindow("Progman", vbNullString)
hWnd2 = GetWindow(hWnd1, GW_CHILD)
hWnd1 = GetWindow(hWnd2, GW_CHILD)
Ret = SendMessage(hWnd1, LVM_ARRANGE, LVA_ALIGNLEFT, 0)
End Sub
ArrangeIcons
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
ReleaseCapture
SendMessage - this is included
Sub MoveWithMouse
If Button = 1 Then ' Checking For Left Button only
Dim ReturnVal As Long
x = ReleaseCapture()
ReturnVal = SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0)
End If
End Sub
You must put this sub in the Form_MouseDown event like this:
GetCursorPos
Sub MouseLocatioN ()
Dim Pnt as PointAPI
GetCursorPos Pnt
lblMouseLocation.Caption = "MousePointer is located at " & "; Pnt.X;" & "," & ";
You must put this sub in the Form_MouseDown event like this:
GetWindowsDirectory
GetSystemDirectory
GetWindowsDir
GetSystemDir
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
GetDiskFreeSpace
If X Then
CurrentDisk.RootPath = sRootPathName
CurrentDisk.FreeBytes = lBytesPerSector * lSectorsPerCluster * lNumberOfF
CurrentDisk.TotalBytes = lBytesPerSector * lSectorsPerCluster * lTotalNum
CurrentDisk.FreePcnt = (CurrentDisk.TotalBytes - CurrentDisk.FreeBytes) /
CurrentDisk.UsedPcnt = CurrentDisk.FreeBytes / CurrentDisk.TotalBytes
Else
CurrentDisk.RootPath = ""
CurrentDisk.FreeBytes = 0
CurrentDisk.TotalBytes = 0
CurrentDisk.FreePcnt = 0
CurrentDisk.UsedPcnt = 0
End If
To get FreeBytes :
GetDiskInfo ("c:\", "FreeBytes")
To Get TotalBytes:
GetDiskInfo ("c:\", "TotalBytes")
To Get FreePercent
GetDiskInfo ("c:\", "FreePcnt")
To Get UsedPercent:
GetDiskInfo ("c:\", "UsedPcnt")
And instead of "c:\" you can use "d:\' for drive D:
»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
Hope you have learned something and how to use reusable code.
For comments,suggestion and stuff refer to the mail address at the top
You need to create a speedblock so that you won't get lagged out of the server, a
// These are the basic variables that need to be defined for a speedhack
DWORD last_real=0;
DWORD last_fake=0;
DWORD StartTimeS;
bool speedblock=false;
bool tmp=false;
float speed;
int speedon=1000;
int speedoff=5000;
int TIMOUT=400;
typedef BOOL (WINAPI *QueryPerformanceCounterFunc)(LARGE_INTEGER*);
QueryPerformanceCounterFunc QueryPerformanceCounterPtr=NULL;
if(speedhack)
{
if(!last_real)
{
last_real = last_fake = new_real;
return ret;
}
last_fake += diff_fake;
last_real += diff_real;
}
return ret;
}
Now in glViewport you need some kind of activation key, which would be fire, whic
And now in glEnable, you create a speedblock, so you won't get lagged out of a se
if(!tmp)
{
StartTimeS = timeGetTime();
tmp=true;
}
if((int(timeGetTime() - StartTimeS) > TIMOUT/speed) && !speedblock) // How long t
{
speedblock=true;
}
if((int(timeGetTime() - StartTimeS) > (TIMOUT/speed)*2) && speedblock) // Speed-P
{
speedblock=false;
tmp=false;
}
}
Now, to access different speeds, you would use the variable you've created: float
It's pretty simple. Speedhack does not work with an opengl wrapper (as far as I k
Read through the code so you understand it, just don't copy paste everything .
Thanks,
[z3r0h4x]G0dz
P.S: If you need more help, and if you want me to explain things to you, PM me, I
EDIT:
Left one thing out, you must define newQueryPerformanceCounter first, so you woul
if(!strcmp(lpProcName,"QueryPerformanceCounter")){
QueryPerformanceCounterPtr = (QueryPerformanceCounterFunc)GetProcAddress(hModule,
return (FARPROC)newQueryPerformanceCounter;
}
__________________
www.z3r0h4x.tk
[z3r0h4x]G0dz
#################################################################################
Author: [SHEEP]
Level: Intermediate
Target: VEXX
#################################################################################
Introduction
============
Micro$oft in their infinite wisdom decided that when the xbox was rlsed
they would sign all of their saved games with a digital signature to
prevent you from tampering with the save games in any way.. I wonder
who the fuck they really think they are? I mean.. its our saved game
we should be able to do what the fuck we like with it. :)
This tutorial will attempt to explain to you how you can enable hacked
saved games to be loaded, its a generic approach so you can apply it
to pretty much any game. There isnt that much work involved so you
should be able to keep up. After this you will hopefully be able to
make your own patchs and maybe spread them so that EVERYONE can use
their own hacked saves for ALL games :)
PART 1
------
PART 2
------
i) Starting Work.
ii) Flirt And Functions.
iii) XApi Code.
iv) Recognising The Correct Routines.
v) Creating The Patch.
LETS BEGIN!!!!
PART 1
======
Converting xbe to exe for IDA
-----------------------------
1) Load cxbc
2) Goto File/Open..
4) Close cxbx
ok, now we got that done we can move onto the next stage..
1) Load IDA
When the numbers in the bottom left hand of the screen stop
moving then we are ready to move to the next stage..
3) Move down the list and choose the Xbox Flirt file.
4) WAIT!! this can take a little while..
Again.. when the numbers in the bottom left hand corner have
stopped moving we are ready for the next stage..
PART 2
======
Starting Work
-------------
The first thing we need to do is locate the routines that deal with
signing and checking the saved games..
2) From the list click on "FUNCTIONS" should be the 4th item down the list.
The reason we loaded the Flirt earlier was so that it could run through our
list of functions and give them names (if it recognised them) it wont get
all of them as u will notice, LOTS are still labled with the IDA default
function lables... BUT!! it does name the ones we need so thats all that
really matters..
XCalculateSignatureUpdate
XCalculateSignatureBegin
XCalculateSignatureEnd
They obviously all are related though usually it only takes the first one
to locate the rest within the code as they are all used in conjunction with
each other to form the signing routines..
2) Click on search in the menu.. then click on search from the list.
3) Type in the box, "SIG" without the " " and click ok.
4) If it stops at an xapi that isnt one of the above 3 press CTRL-T
to move onto the next one.
Once you have found it (should have been the 3rd occurance) double
click it and you will be taken to the Xapis code.
XApi Code
---------
*********************************************************************************
*********************************************************************************
We need to start thinking logicaly now to work out what these 2 refereces are for
well.. we know that the game needs them for only 2 things.. 1. CHECK SIGNATURE
ON SAVED GAME WHEN LOADING. 2) CREATE NEW SIGNATURE WHEN SAVING GAME. So the fact
that there is only 2 references to these functions means we are on the right trac
and dont really have 2 much further to go..
We now want to find out which one is used to check our saved game when its loaded
only way to do this is by double clicking 1 at a time and looking at the code aro
it..
So.. click on the first Xref and we can begin, you should land here..
*********************************************************************************
*********************************************************************************
We are now in A signature routine.. as you can see the other 2 Xapis I mentioned
earlier are also here.. this is a good sign that we are indeed in the right place
Hmm, have you noticed anything about this routine?? .. Well let me tell you.. the
doesnt seem to be ANY checks at all.. nothing is compared (CMP) or tested(TEST)..
it just seems altogether 2 quiet :)..
Im more inclined to believe that this routine is what MAKES the signature when
the SAVED GAME is being SAVED not LOADED because we have no checks once the code
has been executed.. of course.. checks are not always within the routine themselv
they can be further on.. we need to check just outside of this routine and see if
its being check there..
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
As you can see all the way down to the bottom of the routine there are no checks
or compares of any kind.. this is certainly looking to be the SAVE GAME routine
and not the LOAD GAME.
*********************************************************************************
We now want to get back to our original place so we can check that other referenc
so TYPE "G" and a box will appear, into this TYPE "11D082" without the " ".
You should now be back to where we started and can right click on
_XCalculateSignatureUpdate@12 again to get the references..
This time double click the bottom reference.. you will end up here..
*********************************************************************************
*********************************************************************************
AH!!.. thats more like it.. you can see all the checks and compares after the xap
This makes me think we are NOW in the right area.. now.. if you look down the rou
you will notice that there seem to be 2 exit points.. these are RETN 10 instructi
you should also notice that ECX is being placed into EAX on each occasion which i
common practice for any routine wanting to return a GOOD or BAD result.. my guess
that one will return EAX as good and one will return EAX as bad.. but that does l
like complex code doesnt it? :) .. well.. as with pretty much all protections..
especially weak ones it all hinges on 1 compare.. 1 check for GOOD or BAD.. and a
this routine returns either a GOOD or BAD result.. the CHECK must be outside of t
routine and EAX is whats going to be checked.. so..
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
AH!! look at that.. just outside the CALL sub_5a2e0 we can see that EAX IS!!! che
Again.. there are 2 exit points.. but this code is MUCH clearer than the last lot
You can see that if eax is NOT 0 then 1 is placed into EAX and it goes off to ano
routine.. but if EAX is = to 0 then EAX is xored and then shipped off..
I think we have found our patch location.. we need it to always return a GOOD res
we do this by altering the following code..
Subtract the BASE IMAGE of the default.xbe which is usually 10000 from
the address we got from IDA.. so..
6) Save.. CLOSE!
Thats it.. :)) now when u load that default.xbe up you will be able to
load in ANY saved games you like.
(75) is the ASM opcode for JNZ .. and (EB) is the ASM opcode for JMP, I suggest
you learn them.
To be honest VEXX was a pretty simple one to start with because it didnt have
any checks on the SAVE GAME section.. Some games do actually use some checks
after saving your SAVED GAME so you need to just follow the code a little
more to figure out whats going on..
#################################################################################
I hope you enjoyed reading this tutorial and hopefully you learnt something
from it..
#################################################################################
How To Hack Sega GT 2002 To Allow It To Accept Hacked Game Save Files
Up until now, the main obstacle encountered when trying to hack game saves was that the game would
detect that you tried to hack it by comparing the game save data to the "signature" (CRC) of the game
save file(s).
However, DEatHrler has found a way around that! He has successfully modified the main game file
itself (default.xbe) to bypass the CRC check. Thus, hacked game saves will load and work despite the
CRC not matching the data.
Below is a little tutorial that he wrote up related to hacking the Sega GT 2002 default.xbe file to
allow hacked game saves to load. While specific to this game, the principals apply to any game.
[ Update ]
Although you initially need to hack default.xbe to load a game save that you hack, you can then
resave the game and will have a valid game save file with the proper CRC recalculated. The save
can then be used by anyone with the game, regardless of whether or not they have hacked their
default.xbe file. This is certainly very good news for those who are less inclined to hex edit their
default.xbe files.
If you just want to hack sega gt, go to the section "Actualy Hacking
the .xbe" everything else is technical for cracking other games...
Fist, open CXBX (0.4.4 was what was available, all should work)
open your file and it'll go to work. you should get a screen that looks like this; disassembling takes a
while so give it time.
Double click the file and it'll bring you to the instance it suspsects the file is being accessed
there might be several instances of it being accessed; usually one for saving and one for loading.
You can tell that this particular instance is for loading because the previous one has idata0.dat
accessed before hand which isn't read for data, it's only used in the load menu.
Here comes the arbitrary part: you must determing which function is being used to checksum the files
It's rather obvious in Sega GT because on one of the calls you come to a bit of code that looks like
this:
I'm not exactly sure what it is doing line by line but it looks to me that it is what I need to get rid of
Look near the bottom of the W32dasm window when you have the call selected and you should see, in
the status bar,
"Line: ######## Pg ##### and ##### of #### Code Data @:###### @Offset 0006DD5Ch in
File:default.exe"
The data that you are interested in is the number that I have bolded, it will be different for every game
but this is what it happens to be for Sega GT
Actualy Hacking the .xbe
Open up WinHex and click Position/Go To Offset
Make sure that the button next to the text box is set to "Bytes" or you will get the wrong place
Enter the offset (6DD5C for Sega GT) from the previous step in the text box and hit OK. It'll jump you
to the offset that the call function is on
Now find the offending call in the .xbe and nop it out (put 90s in for all of the addresses the call
function takes up)
You should now have a cracked .xbe, FTP it to your XBOX and load some hacked save states
An Example of a hacked save state... unfortunately the engine doesn't deal with really large numbers,
it limits itself to $9,999,999 but ~$10,000,000 works
I'll try to document the save state to make modification easier; the most notable offset is 00000018
through 0000001B which is for money,
values of FF FF FF 04 will give you around $10.5 mil, I wouldn't suggest going over because the
engine doesn't like extremely large money values (wont let you buy if you have too much)
Bie comment:
This info is taken from http://www.gamehacking.com forum
Unknown
Hacking The PS2 And Converting By UnderlordKrullik (Original Tutorial can be found here at CES Forum)
PS2DIS(program).
The game you want to hack.
The converter.
Codebreaker Or Gameshark Or Action Replay (Cheat devices for the ps2)
I will post the links after.
Ok 2nd put your ps2 game into your cdrom in your pc.. right click on your CD drive icon E or F which ever you put your disk in.. Hit open and copy the Slus file into another folder (I save my slus
file of the game into ps2dis folder). Ok you can close that out now that you have the slus file out you can also take your disc out.
Now open up PS2DIS and load the slus file.. now all the coding in PS2DIS will look simply of ASM hex including labels such as Car names gun names ETC... now all you do is if you not understand
much of ASM look in the labels and double click on say a AKS-74(Gun) it will bring you to the ASM hex strings of it now it should be i would say 7 addresses.. since this is hex this is where the
converter comes in...
now copy all those hex addresses out into a text file and 1 by 1 convert them to Codebreaker or gameshark or action replay whatever cheat device you use on the PS2.. after you Convert them
put them in your cheat device.. you should only use 5 at a time so the game wont crash if there's an invalid... but Not all games use the labels.. so you might have to look just manually down the
games hex and test.
That's about all I'm getting the links and ill be adding the converting tutorial and some pictures.
I'm sorry its scus not slus my bad SO here's a sample I'm using Socom II for ps2
PS2DIS Interface
Labels in socom II I have ammo lable highlighted
There can be very many addresses in a label so you have to convert and manually test each address.
Ok in ps2dis all the coding is in hex so make sure the converter is on HEX button
Now I got a random hex code out of labels for socom now double click an address in PS2DIS for a little window to open it should say Address and data looks like this for example Address: 000000
Data: 000000 now copy the address and paste it in the converter then copy data into it it should look like this
the first line 001d4538 is the address in ps2dis then the 74736f68 is the data it should look like the pic above and i have the two 0's circled which is important where those 00's are put 2A now after
you have that done click on the CB2 button and it will convert the hex to codebreaker like this
Notice that the CB2 is poked and that the hole address is changed so it converted the PS2DIS addresses into CB2 addresses now all you need to do is put that in your CB2. Now there is no really
way to know what an address in PS2DIS does that's why most PS2 hackers have a team so they can each convert addresses and test them... kinda like for PC hacking if you do the 12345 method
when you poke like 5 addresses at once but in ps2 then try them out.
HINT: this is not the same way for gameshark or action replay if you need it ill post it.
From http://www.gamehacking.com forum.
Author: ghBladez
Looping Tutorial
Ok well here is a small guide on how to loop the label of your choice in the popular disassembler ps2dis. Firstly open your software and the sces sles slus scus file you want to hack and invoke the analyzer by pressing the
tab Analyzer - Invoke, When you have done tap CTRL + G to open up the labels list. Scroll through it and look for a label you like, In this tutorial I'm going to explain to you how i hacked the rank code for SOCOM: US Navy
Seals. So when we have found our label, "PointsEarned" double click it to bring you to the text refer of the code, next you press the space bar (highlighting the function) and press F3 (skipping to the code refer). Now you are
ready to start the real hacking, Scroll up to see the label "RoundStatLBTerrs", Now take that label and press space bar then F3 again to get to the code refer, look up to find the first lw command and copy it to the clipboard.
Then back to pointsearned (A few lines beneath the roundstatlbterrs label. Scroll down to the next jump register (jr) command underneath it which should be about 5 pages down. Once you have found it tap enter to bring you
to the command box and wipe out the current function. Replace this with "beq zero zero $address" address being the first lw up from RoundStatLBterrs. And then Hit Enter which creates the beq (branch when equal).
Enjoy,
ghBladez