Back to My Programs Hacking programs

  OK. If you wanna hack a program, first thang you oughta know is exactly what you`re looking for. You have to think well how you`d do that thang, or what would be the best way to achieve it. You have to picture it all up.

Second, you gotta know where to look. If it`s a code it would probably be in an EXE or OVL file, but you can check other files too. If it`s data it can be packed as constants inside an EXE file or in a outside data structures. You just get yourself a HEX editor, you can use Microsoft Developer Studio as debugger also.

Then you have to search inside a file for a teeny tiny string where all that is written. You can write your own programs to do the job. If you`re not sure if you found the right thang, the best way to figure that out is to corrupt that part. If program freezes, then you`re wrong. If you get expected results, then you`ve hit with the hammer on a nail.

Modify that string ... and voila!



Now let`s get down to business.
 
 

CASE 00, Falcon 3 data crack

 
I wanted to modify a flight simulation so, that it would be possible to use nucear weapons.
That required me to change some numbers inside the program.

To effectively change a weapon I had to change all data connected to it. That would be:

  • Weight of weapon
  • Aerodynamic drag factor
  • Strength of weapon
  • Units-per-pylon data
  • and other stuff, guidance, warhead type, ignition delay, max G-force turn capability...
First I took a look at filenames. I got attracted to files named ARMSxxxx, lots of`em. The best way to find something is to know how it looks like. So I went searching for weapon weight. I picked one weapon, its weight let`s say was 500 pounds.
To write down a number 500 in binary you have a few options. BYTE variable is invalid, cuz it can reach only up to 255. Next one is WORD and then DWORD type variables.
 
DEC
HEX
WORD
500
01F4
DWORD
500
000001F4

Then you also have an option to write it down in FLOAT or DOUBLE types. Consider this, but it ain`t a real possibility, just in special cases.

So, I chose to look at word variables. Be aware, inside the file 0x01F4 is written in opposite order (since variables on stack  are ordered from top to bottom, least significant BYTE is at the top of variable`s area in memory and the Most Significant Byte is at the bottom of variable`s area in memory). If you wanna find a number 0x01F4 you have to search for string F401. (Similary, if you have to find a dword 0x12345678 you`d need to look for hex string 78563412. The same stands for floats=32 bit dword-like numbers and doubles=64-bit qword-like numbers).

Also keep in mind, that BYTE may be found on every byte-sized part of memory. A WORD, DOWRD, QWORD, float and double can only br found on addresses that are multiples of two/four/eight (WORD/DWORD/QWORD data alignment). When writing programs it is a tendency to align data inside memory on DWORD alignment - multiples of 4. That is, because in 32-bit mode, all the registers are 32-bit. And 32-bit linear addresses are used to address phisical memory. And when you order processor to load a DWORD number into some register, if that number is NOT located on DWORD-alignment position, then processor needs additional time to addres it. So, when you write programs and create data structures, it is not wise to use BYTE variables if you expect numbers only up to 255. Because then, all the folowing variables will not be properly aligned, and if you`ll access such variables often enough, it will slow down your program very much.

OK. So now we`re searching for a word string F401. We make a special program, that writes down address of every match. Then we do the same for other weapons. And the manually compare the results. If we find that all the weapons have one of the numbers that could be their weight inside (let`s say -512 + 512 bytes from some center point) radius, then that`ll probably be it.

But with this method, you can get A LOT of results and you have to comare all that stuff.
It`s very nice if you know the order in which the weapons may be stored in memory. That order will probably be the order in which you see them in a game.



Well, back to searching. I first searched for weapon weights in them ARMSxxxx files. And found nothing. Zipo. Nada. Then I went looking in the EXE file. And I got a lot of results.
So, I tried to predict the order of weapons. I loaded the EXE file into a HEX browser, and quickly looked over it. I ordered the browser to search for words like "AIM-9", a name for an Air-to-Air missile. And it found several hits. I took a look of them and found on one place, all the names of the weapons. I used that order to search for weapon-weights.
So I wrote another special short program, which searches for a specific weight. When it finds one, then it looks for the others placed relatively to this one but at various radii. First 2 bytes, then 3 bytes and so on. This kinda calculation takes time. Approx an hour maybe, if the file is long.

I got reported hits. I went to check it out with HEX browser, and found all of the weapons WORD weight values stored in proper order. Well, not exactly. If yo make a program that searches for a specific order, then you`ll find nothing. You have to write a program that reports a hit whenever it finds more than let`s say 3 matches. Then you just look at the number of matches and check the most probable ones.
I had this problem. Falcon 3 was an upgrade of Falcon 1.2. And it contained weapons that were infact not used.

OK. I found two places in file that contained weapons weights. So, which one is the correct one? Let`s corrupt it and we`ll see. I chose a specific weapon, and increased its weight to max (0xFFFF). Then I went into the game. When I chose that weapon in Load-Armament window, weapon data said the bomb weight was -32768 pounds. OK. I corrected it to 0xFF7F (remember 0x7FFF=32767, in memory stored at opposite order), and loaded it on the aircraft. I went flyin` and the aircraft took off noramlly!
So, what tha hell went wrong?
Then I corrupted the other string aswell. Bigo! Aircraft fell back on runway after takeoff.

The first string found was used ONLY by aircraft-armament procedures, the second string ONLY by the aerodynamics procedures.

Now I knew the order and where to look for. So, next thing I had to correct was the weapon aerodynamic drag. Put in the search numbers and the order and there they were. String of BYTEs. Also on two places. One for load-armament and one for aerodynamics.



Now I had a bomb of correct weight and drag, instead of Mk-82-1 HDGP, I had a B-43 Thermo Nuclear Weapon. But I could still load 12 of`em on the plane instead of one.
So I went looking for the weapon-hardpoint data. 

Say, F-16 in game has 2 wingtip hardpoints, 6 underwing hardpoints and one under-fuselage hardpoint.

                                              I
                                              I
                                         AAAA
       o______________XXXXXXX______________o
               |      |       |                |                |       |      |
==========================================
       0     0     6      6               0               6     6     0    0          Weapon loadout for Mk-82-1

So we look for a string (probably bytes) = [00 00 06 06 00 06 06 00 00] or [00 00 06 06 00].
And we find one. Actually we finde many of them, because several weapons have the same loadout numbers. We modify the correct one into [00 00 00 00 01 00 00 00 00].



But we still need to modify the energy of weapon. This one`s gonna be tough. It can be a BYTE, a WORD a DWORD or even a FLOAT.

I went into a game, and made several tests.
I shot every type of weapon into the ground so it left a crater. I recorded the whole thang. Then I went to a replay mode, put the viewpoint at the specific distance from every crater and optically measured the size of each of`em. That gave me some clue, about which weapon is stronger (I created the ladder of weapon strengths, from the weakest one to the stronger one).Then I went to search for all types of variables in order mentioned above, with respect that specific vaues have to be bigger/equal/smaller than other specific values. And I found nothing.



I was looking in all possible ways, and had no luck.
I allready knew which part of the EXE file was doing what, so I searched again for the weapons names. And there was one string of names that didn`t fit in my suspected order. Besides, there were also other weapons, used by ground crews (Surface to Air missiles, enemy A-A missiles etc...)

Well, I just wanted to be sure. There were some suspicious numbers folowing that names. They looked like WORD values (y`know: 82 00 4F 00 23 00 12 00 35 02 05 00 E8 01 7F 00 ... where those very small numbers at even places just cry out that they are the HIGH BYTE of a WORD).
Oh well, I blanked them all, made them all 00 00 00 00 00 00 00 .... and went check that out to a game. I dropped a pair of Mk-84s from 500 feet (that should`ve blown my ass to pieces). But instead it just went "Booh...". So I dropped another pair from 100 feet, and nothing. BINGO!!! Weapon strengths. But their order was mixed up. So I had to tilt up ever one of them and check it out in a game.

I lined up a column of vehicles and shot weapons at it. Can y`imagine an AIM-9P air-to-air missile with 20 pounds of explosives torching instantaneously up a one mile column of armored vehicles?
Well, I just had to pin-down my Mk-82-1 bomb, tilt it up to 0xFFFF, and test it.



I expected that the safe drop altitude will be 18000 feet or something. Noooo, it ripped my ass. So I tried again from 25000` then 30000` then I went almost berserk. 35000` and I still suffered a flameout. Well at 40000` with 500 kts I was safe.
But from that altitude you cannot aim accurately. So, I setup a friendly flight at 1000 feet flying below me, then I dropped The Bomb, measured drop-time (until the guy below started screaming) and then measured the distance from release-point to crater.
 

And there y`have them Nuclear Bombardment procedures.


 

CASE 01, X-wing code crack

 
Well, you cannot fly the StarWars X-wing / B-wing or Tie fighter simulation with keys. That`s for sure.
But neither y`can with mouse. Because them clever programmers baked into the program mouse commands that read out mouse velocity insteda mouse position.

I wanted to modify a flight simulation so, that it would read out mouse position instead of mouse movement-velocity.



Every program (well DOS programs) communicates with mouse device through an interrupt. More specificly, that is the INT 33h (0x33). Depending on the task you want the device hadler to perform, you put the number of that task (function) into AX register, if you need to send additional data to interrupt routine you put it into BX or DX or CX register and then you call INT 33. Piece a shit.

The assembly code would look something like that:
mov ah, something
mov al, something else
mov bx, something
int 33h

You can write that down into an ASM file, build an OBJect, and disassemble it again. When you disassembel it, you`ll see exactly into what numbers (machine code) the assembly instructions are coded.

But first wee need to find the area in program, where the mouse functions are. Again, we order the HEX browser to search for hex string CD 33 (0xCD is hex code for INT instruction, and 0x33 is the interrupt number). Of course we look for them in EXE file. And we find nothing. So we select all the files (the longer ones are more probable) and run the scan. And we find some hits in OVL files.
There are several ocasions where CD33 is used. Some of them may be coincidential, maybe data structures or something... But there ain`t many.
So we make an ASM file, where we have let`s say 2048 NOP (no operation) istructions. A verrrrry long text file. We compile it into a neutral OBJ file. This OBJ file will contain only 0x90 machine code (nop). Well, you have to check this OBJ with a hex browser first. Because inside an object file the code gets sliced up into segments (I think) 1020 bytes long. Inbetween there are some 5 bytes of data inserted. Besides, object file has a head. So you have to check out in exactly which areas you can replace the 0x90 instructions with new instructions.

When you know this, you just make a program that copies a part of surrounding code (around the match in OVL file) into this neutral OBJ file. Perserve the neutral OBJ file. The code you need to copy is not long. It will do if you copy -256 to +255 (512 bytes) around offset point.

Now`s the time for disassembly. You`ll get a new ASM file, with all instructions. You have to be carefull to define first whether it is an 16-bit or 32-bit code.
When you`re looking at the code, be advised that the first few (3-4) disassembled instructions won`t be correct. This is because, the machine code can consist of 1 or more bytes. So, if you accidently cut the first instruction, the disassembler will interpret it wrongly. But, we`re not interested in the first few instructions. We`re interested in the main core. And that one will be correct.

So, now you need to visually identify if the code is right. You need to know assembly very well. If you see a bunch of stupid instructions (just randomly ordered instructions, that do nothing), then you`ve just disassembled a data structure.

If you see some sence in it, then you got it.
In my case, I got several functions inside my 512 byte perimeter. One was setting up mouse resolution, one was dealing with mouse velocity ... You have to recognize them by the numbers that are being loaded into AX register before calling INT 33.
So I took that function that was dealing with mouse velocity, and changed the AX parameters (from velocity-detection to offset-detection). But there was a problem. It was necessary for me to insert additional code there. Every function was only around 32 or less bytes long. So, not very much space to throw around. I was lucky there was a page-break or something just after the mouse functions. Just around 20 bytes of free space. So I inserted a JMP (jump) instruction to this free space into a function. I don`t remember very well what kinda code I had to insert. Something with resolution and max. limits. Well, there was just enough space to do that. I calibrated the results to be within 0-511 range. Next thing I`d need to get done was, a subtraction of 256 form the result, so I`d get a -256 to +255 range. But there was not enought space to insert a SUB command, and I had to forget about it. Then just a JMP back to the function and all is done.

Check it out here.

PCGPE (PC Game Programmer`s Encyclopedia)


Visitor no:Impact Counter since Sept. 14th 1999
Last updated by Miran Klemenc jr. on Sept. 14th 1999, have a nice day!
1