Stunts Forum

Stunts - the Game => Stunts Reverse Engineering => Topic started by: clvn on October 19, 2009, 08:33:07 PM

Title: bypassing load.exe
Post by: clvn on October 19, 2009, 08:33:07 PM
hi!

using info on this forum, stunpack and bit of hacking, heres source code to a quick&dirty program that combines mcga.hdr, the uncompressed ega.cmn, mcga.cod and mcga.dif into a new game.exe. this new exe replaces load.exe/*.hdr/*.cmn/*.cod/*.dif.

made with msvc. some tweaks may be needed. enjoy!


#include <fstream>

void next_offset(unsigned short* arg0, unsigned short* arg2, unsigned long arg4) {
unsigned short var2;
arg4 += *arg0;
var2 = arg4 / 0x10;
*arg2 += var2;
*arg0 = arg4 - (var2 << 4);
}

bool apply_dif(const char* filename, char* bytes) {
std::ifstream fs;
fs.open(filename, std::ios::in | std::ios::binary);

if (!fs) return false;

unsigned short var8;
unsigned char val1;
unsigned short output_ofs = 0x0000;
unsigned short output_seg = 0x0000;//0x01A7;

if (output_ofs == 0)
output_seg -= 0x1000;

output_ofs--;

next_offset(&output_ofs, &output_seg, 0);

while (true) {
fs.read((char*)&var8, sizeof(unsigned short));
if (var8 == 0) break; // eof

next_offset(&output_ofs, &output_seg, var8 & 0x7fff);

int pos = output_seg << 4 | output_ofs;
char* buffer = &bytes[pos];

fs.read((char*)buffer, sizeof(unsigned char));
fs.read((char*)&buffer[1], sizeof(unsigned char));

if ((var8 & 0x8000) != 0) {
fs.read((char*)&buffer[2], sizeof(unsigned char));
fs.read((char*)&buffer[3], sizeof(unsigned char));
}
}


fs.close();

return true;
}

size_t copy_binary(const char* filename, char* exeimage) {
std::ifstream fs;
fs.open(filename, std::ios::in | std::ios::binary);
if (!fs) return 0;
fs.seekg(0, SEEK_END);
size_t size = fs.tellg();
fs.seekg(0, SEEK_SET);

fs.read(exeimage, size);
fs.close();

return size;
}

void save_binary(std::string filename, char* image, int size) {
std::ofstream fs;
fs.open(filename.c_str(), std::ios::out | std::ios::binary);
fs.write(image, size);
fs.close();
}

int main() {

char exehdr[30];

copy_binary("assets\\mcga.hdr", exehdr);

unsigned short bytes_in_last_page = *(unsigned short*)((char*)&exehdr[2]);
unsigned short pages_in_executable = *(unsigned short*)((char*)&exehdr[4]);
unsigned short relocation_offset = *(unsigned short*)((char*)&exehdr[24]);
unsigned short paragraphs_in_header = *(unsigned short*)((char*)&exehdr[8]);

int executable_size = (pages_in_executable * 512);
if (bytes_in_last_page > 0)
executable_size += -512 + bytes_in_last_page;

int header_size = paragraphs_in_header * 16;

char* exeimage = new char[executable_size];
memcpy(exeimage, exehdr, 30);

int size = copy_binary("assets\\ega.cmn", &exeimage[header_size]);
apply_dif("assets\\mcga.dif", &exeimage[header_size]);
copy_binary("assets\\mcga.cod", &exeimage[header_size + size]);

save_binary("game.exe", exeimage, executable_size);
return 0;
}


Title: Re: bypassing load.exe
Post by: clvn on October 20, 2009, 09:53:56 PM
some further analysis reveals the the output game.exe from the above program is compressed with exepack, as with load.exe.

to remove the copy protection, uncompress with unp and put a byte 0x1 at offset 0x2b3c :-)
Title: Re: bypassing load.exe
Post by: clvn on October 26, 2009, 10:22:23 PM
hello again!

ive put game.exe through idapro and worked through random portions of the disassembly. so far its been adhoc hacking, trying to figure out the general structure and flow of the game.

if anyones interested, heres the output game.asm so far: http://dl.getdropbox.com/u/213479/game.asm (http://dl.getdropbox.com/u/213479/game.asm) . also id be happy to share the .idb as well.

of the 500+ functions detected in the exe, about half of them are named roughly after their category or function. the others still have cryptic names like "sub_9F1_2564". the main()-function is right at the beginning of the file (after the struct declarations).


dunno if it is documented somewhere else, but according to the command line parsing code, the exe understands the following parameters:

/ns - no sound
/nb - parsed, but unused
/ssb - use soundblaster (ad15.drv) instead of pc speaker
/sXY - use driver XY15.drv instead of pc speaker (e.g /sad for soundblaster)
/h - sets bios video mode 4 (black screen here)
Title: Re: bypassing load.exe
Post by: BonzaiJoe on October 26, 2009, 10:52:48 PM
Hi clvn! And welcome.

Forgive my ignorance, but what is the point of bypassing load.exe? What can be achieved with this utility?
Title: Re: bypassing load.exe
Post by: Duplode on October 26, 2009, 11:25:24 PM
Quote from: BonzaiJoe on October 26, 2009, 10:52:48 PM
Forgive my ignorance, but what is the point of bypassing load.exe? What can be achieved with this utility?

If I understood correctly what Cas mentioned somewhere long ago, load.exe picks a number of code files (according for different video/sound rivers, etc.) and combines them into a single piece of code which is run as the game. Getting it off the way should make it easier to locate which parts of the executable(s) are responsible for which functions within the game - that is, doing reverse engineering on whatever is buried inside the code.

As for me, I have no disassembly knowledge to be able to help, but highly appreciate the efforts anyway  :) Too bad Cas and the other hackers haven't been around lately...
Title: Re: bypassing load.exe
Post by: clvn on October 27, 2009, 04:11:00 AM
Quote from: Duplode on October 26, 2009, 11:25:24 PM
Quote from: BonzaiJoe on October 26, 2009, 10:52:48 PM
Forgive my ignorance, but what is the point of bypassing load.exe? What can be achieved with this utility?
If I understood correctly what Cas mentioned somewhere long ago, load.exe picks a number of code files (according for different video/sound rivers, etc.) and combines them into a single piece of code which is run as the game. Getting it off the way should make it easier to locate which parts of the executable(s) are responsible for which functions within the game - that is, doing reverse engineering on whatever is buried inside the code.

yes, stunpack+the first code snippet basically re-implement portions of load.exe required decompress and combine the game-executable to disk rather than executing it in-memory. i understand this step wasnt documented here before.

the utilitys use is solely for reverse engineering purposes. it creates a version of the game that is actually possible to disassemble - as is shown in the linked game.asm.

hopefully something more interesting than undocumented command line parameters will come out of this, but time will show.
Title: Re: bypassing load.exe
Post by: clvn on November 01, 2009, 02:54:53 PM
The little reverse engineering project has continued at full pace. Check out the latest .asm-dump from idapro:

http://dl.getdropbox.com/u/213479/game2.asm (http://dl.getdropbox.com/u/213479/game2.asm)

While a lot of analysis remains, the disassembly now has many better-named functions and variables and a bunch of structs. The readability is much improved. Big chunks of the data segment was identified, including tables with mappings between track-tiles and 3D-shapes with rotation, materials, etc.

On a side note, a greater plan is starting to emerge. I've reconstructed enough of the resource manager and original memory layout to code a .trk-viewer-app under windows/d3d. Its pretty lame, so no betas, screenshots nor source code yet. It is meant as a testbed for analyzing and porting assembly from the disassembled stunts game executable. This way the vital parts of the game engine could be reimplemented in inline 32-bit x86 msvc-assembly with only minor changes. Further porting to C/C++ and other platforms would of course be for later.

There are approx 25000+ lines of code (out of 100000+) that are relevant to the core game engine and needs to be ported. So far only 1500 lines in 3 functions were ported in a couple of hours. There is work for at least a few weeks-to-months for somebody with a lot of spare time :)
Title: Re: bypassing load.exe
Post by: zaqrack on November 01, 2009, 07:54:10 PM
absolutely stunning news. Thanks for the efforts!
Title: Re: bypassing load.exe
Post by: Duplode on November 01, 2009, 07:57:58 PM
Quote from: clvn on November 01, 2009, 02:54:53 PM
While a lot of analysis remains, the disassembly now has many better-named functions and variables and a bunch of structs. The readability is much improved. Big chunks of the data segment was identified, including tables with mappings between track-tiles and 3D-shapes with rotation, materials, etc.

Quote from: clvn on November 01, 2009, 02:54:53 PM
It is meant as a testbed for analyzing and porting assembly from the disassembled stunts game executable. This way the vital parts of the game engine could be reimplemented in inline 32-bit x86 msvc-assembly with only minor changes. Further porting to C/C++ and other platforms would of course be for later.

I hope everyone can spare a moment for appreciating the immense significance of this stuff. It is the culmination of the hacking efforts done over all those years. It is really fantastic! There is so much to look at... if you excuse me, clvn, I will start with two kinda trivial questions, coming from someone who knows almost nothing about disassembly:

1. With the information you have already dissected is it possible to locate the materials table and the colour palette(s) used to build it?

2. After locating materials and palettes, how hard would it be to make a patch for modifying the default colours of sky and ground? Or, more ambitiously, to substitute materials entirely?
Title: Re: bypassing load.exe
Post by: clvn on November 01, 2009, 10:25:25 PM
Quote from: Duplode on November 01, 2009, 07:57:58 PM
1. With the information you have already dissected is it possible to locate the materials table and the colour palette(s) used to build it?

2. After locating materials and palettes, how hard would it be to make a patch for modifying the default colours of sky and ground? Or, more ambitiously, to substitute materials entirely?

well, this depends.. of course there is the 768 bytes "!pal"-structure in sdmain.vsh. thats the global 256-color palette used throughout the entire game. tweaking it may have unexpected side effects though.

from what ive learned so far, it is possible to tweak hard coded material assignments for all the individual tile types. e.g render a normal road as icy road, or rotate, move or replace a shape with another one. this could be done before, but not without modifying the 3d files themselves. but the ground and the sky are handled in special ways, and i cant tell which color indexes are used for those.

also, there should indeed be a material index table in there somewhere. it has mappings between the 3d shape materials/paintjobs and the global "!pal" palette. i've ripped some stuff from stressed in order to get the colors in my d3d-rendering correct, but havent located this in the disassembly either.
Title: Re: bypassing load.exe
Post by: dstien on November 03, 2009, 08:35:58 AM
Holy crack! Excellent work, clvn. I didn't notice this thread until now.

To further elaborate on BonzaiJoe's question, having a single, uncompressed EXE file makes static code analysis a breeze. By translating the game back to human-readable C code we can:

If we could make the manual decompilation process a collaborative effort it'll speed up the job. The collabREate (http://www.idabook.com/collabreate/) approach looks interesting.
Title: Re: bypassing load.exe
Post by: BonzaiJoe on November 03, 2009, 10:16:26 AM
Quote from: dstien on November 03, 2009, 08:35:58 AM
Holy crack! Excellent work, clvn. I didn't notice this thread until now.

To further elaborate on BonzaiJoe's question, having a single, uncompressed EXE file makes static code analysis a breeze. By translating the game back to human-readable C code we can:

  • See exactly how game resources are parsed.
  • See what causes the many collision detection and physics bugs.
  • Port the code to modern architectures and operating systems.
  • Port the code to exotic platforms like handheld devices, gaming consoles and web browsers.
  • Extend the game with new features and eye-candy while preserving the eccentric physics we all love.

If we could make the manual decompilation process a collaborative effort it'll speed up the job. The collabREate (http://www.idabook.com/collabreate/) approach looks interesting.

Well that sounds wonderful! Good work clvn :)
Title: Re: bypassing load.exe
Post by: clvn on November 03, 2009, 11:32:33 AM
Quote from: dstien on November 03, 2009, 08:35:58 AM
If we could make the manual decompilation process a collaborative effort it'll speed up the job. The collabREate (http://www.idabook.com/collabreate/) approach looks interesting.
ooh, collabreate looks like a good tool for sharing the effort, considering a regular versioning tool wont work with idapros .idb-file.

im gonna have to try and set up collabreate in a local vm for testing. alas i dont have access to a suitable public server. if anyone here wants to set up a collabreate-server for the task, ill support it for sure.
Title: Re: bypassing load.exe
Post by: llm on November 12, 2009, 12:24:02 PM
hi clvn

first: thank you for reactivating the reverse engeneering subject :-)

i can't create the game.exe with your program - i get an access violation in apply_dif
after serveral runs of the while loop - i think your break condition does not met with my data
what game version did you use?

ciao llm
Title: Re: bypassing load.exe
Post by: clvn on November 12, 2009, 12:45:50 PM
hello!

Quote from: llm on November 12, 2009, 12:24:02 PM
i can't create the game.exe with your program - i get an access violation in apply_dif
after serveral runs of the while loop - i think your break condition does not met with my data
what game version did you use?

it says stunts version 1.1, feb 12 1991.

most obvious point of failure i can think of is not uncompressing the datafiles with stunpack in advance. dunno.

for convenience, heres a zip with the vs project, including the final game.exe both uncompressed and cracked;
http://dl.dropbox.com/u/213479/execombiner.zip (http://dl.dropbox.com/u/213479/execombiner.zip)
Title: Re: bypassing load.exe
Post by: llm on November 12, 2009, 04:03:09 PM
thx yours works perfekt - i forgot to uncompress the files :-)

is the exe fully tested, are there any known problems?
Title: Re: bypassing load.exe
Post by: clvn on November 12, 2009, 04:37:25 PM
Quote from: llm on November 12, 2009, 04:03:09 PM
is the exe fully tested, are there any known problems?

as far as my testing goes, there are no problems using the new exe
Title: Re: bypassing load.exe
Post by: llm on November 12, 2009, 05:37:15 PM
what version of ida do you use - newer version seems to do a much better job in reversing
im currently thinking about buying the latest edition
Title: Re: bypassing load.exe
Post by: clvn on November 12, 2009, 06:39:42 PM
Quote from: llm on November 12, 2009, 05:37:15 PM
what version of ida do you use - newer version seems to do a much better job in reversing
im currently thinking about buying the latest edition

i did use the freeware 4.1 version, which is rather old. mostly out of habit. after reading into collabreate, ive installed a newer version and upgraded the .idb, but havent really progressed any further. using the newer version still feels annoying due to some changed hotkeys.

---

to follow up on an earlier post, i was trying to port the disassembly to inline 32-bit assembler in msvc. which is now on hold. fixing the related pointer issues is possible with a well-planned approach (and even trivial with a smaller program), but now its turning into a mess.

so im still considering how to move forward. maybe making an intermediate 16-bit port in turbo c + tasm as the first step... or maybe look for a plugin for ida that helps porting single functions... ideas are most welcome.

Title: Re: bypassing load.exe
Post by: llm on November 12, 2009, 07:14:47 PM
>i did use the freeware 4.1 version, which is rather old. mostly out of habit.
>after reading into collabreate, ive installed a newer version and upgraded the .idb,
>but havent really progressed any further. using the newer version still
>feels annoying due to some changed hotkeys.

i just saw the differences beween 4.9 and (i think) a recent 5.x version - and it produces a much better and smaller output

>so im still considering how to move forward. maybe making an intermediate 16-bit port in
>turbo c + tasm as the first step

the idea sounds good - got an version of tc/tasm around? maybe you use watcom c or djgpp
Title: Re: bypassing load.exe
Post by: clvn on November 12, 2009, 08:33:21 PM
Quote from: llm on November 12, 2009, 07:14:47 PM
i just saw the differences beween 4.9 and (i think) a recent 5.x version - and it produces a much better and smaller output

ok. sounds like its worth further investigation. perhaps even to the point its worth starting almost from scratch again in idapro, but using sane naming conventions etc. at least the existing work could be used as a reference.

Quote from: llm on November 12, 2009, 07:14:47 PM
>so im still considering how to move forward. maybe making an intermediate 16-bit port in
>turbo c + tasm as the first step

the idea sounds good - got an version of tc/tasm around? maybe you use watcom c or djgpp

tc 2.01 is available from here:
https://downloads.embarcadero.com/free/tc201 (https://downloads.embarcadero.com/free/tc201) ->
http://altd.embarcadero.com/download/museum/tc201.zip (http://altd.embarcadero.com/download/museum/tc201.zip)

while tasm 5 is no longer officially available, it can be found here:
http://www.phatcode.net/downloads.php?id=280 (http://www.phatcode.net/downloads.php?id=280)

tried to locate some ancient microsoft c compilers as well (apparently used for the original game), but google wouldnt tell me. tasm+turboc may be just as good, idapros output should be compatible with tasm.


ive done some investigation into the tasm-approach. for example, just passing the entire .asm-file to tasm doesnt work too well; after getting rid of the obvious errors it stops on "out of memory", presumably and hopefully due to a too large code file.

to get past that, it would be obvious to split game.asm into many smaller ones, which can be assembled and linked separately. like one function per file. but, unless the work in idapro is completely done, one would have to backport any new discoveries in idapro back to the separated .asm-files manually.

so to workaround that, its maybe an idea to automate the process of splitting game.asm into smaller pieces. either as a script that parses game.asm and spits out many smaller ones, or finding or writing a plugin for idapro that does the job directly. this would allow testing+porting in tc/tasm and further reverse engineering iteratively. im guessing a script is the most efficient way to split up game.asm anyway.

alas im stuck with other stuff atm, so i wont be able to follow through with any of this in the near future though.

Title: Re: bypassing load.exe
Post by: llm on November 12, 2009, 09:02:10 PM
im using the borland c++ 3.1 version from

http://vetusware.com/download/Borland%20C%2B%2B%203.1%203.1/?id=5888 (http://vetusware.com/download/Borland%20C%2B%2B%203.1%203.1/?id=5888)

the last pure dos version of "turbo" c with tasm
Title: Re: bypassing load.exe
Post by: Cas on November 23, 2009, 06:41:19 AM
My goodness!

Everytime I'm busy for a few weeks, I come back and there's magic going on!  I would be very happy to help!  Time ago, I had been thinking of a method for decompiling the whole Stunts code (mainly LOAD.EXE). I had already UNPacked the EXE and noticed the structure of the HDR, COD and DRV files. Note that the DRV files are the sound libraries, each of them is supposed to be loaded at the beginning of a segment (offset zero) and starts with a series of jumps to each of the sound functions. I am currently working on a project for FreeDOS that should provide a sound API for DOS and enable some old games to have sound again. Stunts is one of my examples of how this can be accomplished, by replacing the DRV files (specially the AdLib one) with patches that redirect the functions to the new API, called CPOS/NSS.
But back to the decompiling... I am willing to help, but would suggest the following:
1- Do not abandon the game support for pure DOS!  This is an opportunity to support the FreeDOS project. Stunts was born a DOS application and it can still be improved with 32bit code without necessarily having to separate from DOS. Make sure any new code can also be compiled to run under pure DOS. I can dedicate to that myself.
2- MASM and TASM are not very comfortable to receive decompiled code because of the way they structure the sources (ASM files)... having lots of required directives. I strongly suggest Flat Assembler: http://flatassembler.net (http://flatassembler.net)
3- What do you need help with? :)
Title: Re: bypassing load.exe
Post by: clvn on November 23, 2009, 04:27:20 PM
hello!

still busy at work here, but havent completely forgotten about this.

so far i've probed into automating idapro with .idc-scripts. i really like the idea of automating idapro to generate a compilable and extendable project.  such a script would have to do something like this:

- for each segment, generate segN.inc containing extrns to all symbols in that segment (procs, locs and data)
- for each function, generate functionname.asm file with:
- include all seg0..segN.inc, EXCEPT for the segment where the function belongs
- extrns for all symbols in the same segment EXCEPT the current function and data
- public definitions of data and procs
- the implementation of the function and related data
- also, the datasegment must be split into at least two files, since the source code is too big for tasm
- some .bat or project file that assembles and links everything


if this turns out to work, we will have a working exe compiled from the disassembly and the possibility to start porting to C. further reverse engineering can still take place in idapro. e.g when a new variable is discovered and properly renamed, the source files can simply be re-generated from scratch by executing the idc. already-ported c functions may still need to have symbol names back-ported manually, but i still believe this approach would be more convenient than porting everything by hand.

there might turn up some interesting issues related to optimizations made by the original compiler. and lateron the script needs some features related to porting, e.g generate c headers and ignore already ported functions.

here's my attempt at an idc so far. its not usable for anything, but i learnt a great deal when writing it. it was left like this a few days ago, some parts are commented out after testing the built-in method to generate the assembly:

http://dl.dropbox.com/u/213479/anders.idc (http://dl.dropbox.com/u/213479/anders.idc)

Quote from: Cas on November 23, 2009, 06:41:19 AM1- Do not abandon the game support for pure DOS!  This is an opportunity to support the FreeDOS project. Stunts was born a DOS application and it can still be improved with 32bit code without necessarily having to separate from DOS. Make sure any new code can also be compiled to run under pure DOS. I can dedicate to that myself.
agreed. dos support would be nice.

Quote from: Cas on November 23, 2009, 06:41:19 AM2- MASM and TASM are not very comfortable to receive decompiled code because of the way they structure the sources (ASM files)... having lots of required directives. I strongly suggest Flat Assembler: http://flatassembler.net (http://flatassembler.net)
in regards to prefered compilers, assemblers etc, i dont really care. in the beforementioned approach the output can presumably be formatted to suit any assembler. if fasm can compile ida's output with less hassle, then im all for it. the ultimate end-result wouldn't depend on any assembler anyway, so i propose whoever makes (and shares) an idb+idc that produces a compilable project gets to decide on the assembler.

Quote from: Cas on November 23, 2009, 06:41:19 AM3- What do you need help with? Smiley
i need help with "everything". i'll likely resume coding on the idc whenever time permits, unless somebody does it before me. or comes up with a better approach where i can participate. im open for good suggestions.


everybody are also welcome to join on irc in #stunts/efnet. im still alone in there, hardcore idling
Title: Re: bypassing load.exe
Post by: Cas on November 24, 2009, 01:56:40 PM
Great!  Well, I'll tell you what I'm good and bad with, what I have at hand and what I need to know to be able to help.

- I have always been part of the... uh... "resistance", he, he, against Windows, so I have all these years kept on working for DOS. I'm pretty comfortable to it, although I really like and use Linux as well (I have Ubuntu), but I'm still not as good at it as I am with DOS.
- For real-mode high-level, I've worked with Turbo Pascal, Borland C++ and QuickBASIC. I'm specially comfortable with the last two. For low-level, I understand any assembler, but for writing I'm much faster with FASM. For protected-mode high-level, I've been working with FreeBASIC and I've tried it under Ubuntu too. I would like to improve there as well.
- I know very little about network and internet stuff, so I don't even remember how to use an IRC, but I'm willing to participate there if you tell me how.
- I have (some times intentionally) avoided using object-oriented programming, so I am not familiar with languages that develop exclusively in that area. I am used to programming graphic routines low-level and I know how to access old SoundBlaster cards through ports too. I am used to doing that myself, so I don't know about libraries and I'm inexperienced about loading third-party modules in my code.
- I understand the structure of DOS EXE files and know about opcodes
- I am weak about low-level protected-mode programming

So I hope I can be helpful here. It's very good to have somebody else also trying to unwrap all this code. I've been working on analysing Stunts internal variables to block replay handling and I partially succeeded, except that I found some stuff to be system-dependent. Now that car-editing is already possible, the next step (apart from replay-handling control) would be enhancement of track edition, by allowing variable-size maps and more track objects. We need to isolate the (kind of crazy) pseudo-Newtonian force/collision engine, the track/replay file analysis code and the sound and graphics hook-points. About the sound, I've already been working on that. OK... please let me know how we can get in touch. I can pass you my e-mail and Skype IDs and will be glad to participate in the IRC :D
Title: Re: bypassing load.exe
Post by: clvn on November 25, 2009, 02:08:14 PM
Quote from: Cas on November 24, 2009, 01:56:40 PMplease let me know how we can get in touch. I can pass you my e-mail and Skype IDs and will be glad to participate in the IRC :D

irc is an ancient yet popular way to chat in real time. you need an irc client such as irssi on linux or mirc on windows, connect it to irc.efnet.org and join the channel #stunts. we're two people in there right now :)
Title: My most recent research
Post by: Cas on November 25, 2009, 02:47:03 PM
Thank you... I'm installing RSSI.... I'll try to figure out how it works. I once used IRC through a web-based interface, but I don't remember where it was.

I've been researching the memory structure of Stunts as it loads and I found the following data. Many of this, you probably have already figured out, but other stuff might be useful:

- Stunts has HDR, DIF and COD files for MCGA, TDY (Tandy) and CGA, but the DIF file is replaced by a CMN file for EGA. All COD files for some reason are about 64K long (though never exactly), DIF files are about 16K and the CMN file is about 128K. This cannot be just a coincidence!  HDR files are unmistakenly EXE headers. They are 30 bytes long, but nevertheless correspond to EXE files whose code starts at byte 512. The space in between does not contain any code update, though. COD, DIF and CMN files are slightly compressed with a procedure that looks like a very basic kind of Huffman. This is exactly the same procedure used for 3D shapes compression, so it is already known, as cars are already being edited!!  The actual sizes of decompressed codes are specified at the second byte of these files and do not match with the size estimate contained in the headers, which is much bigger.
- STUNTS_K.EXE, the crack, is lightly encrypted. The encryption system can easily be removed with UNP. The unpacker will ask for a passcode. First thing I thought worked: it's just "stunts_k". The resulting file is smaller than the encrypted one.
- STUNTS_K.EXE is loaded, keeping its environment MCB and code MCB. On top of it, STUNTS.COM runs, which also preserves its environment, reads the configuration file and loads LOAD.EXE into memory half-manually, apparently upgrading the code depending on the graphics card selected. LOAD.EXE runs. Environment is preserved again. LOAD.EXE reserves a lot of heap and no dynamic memory is allocated for variables. Only one extra MCB is allocated, but it is used to store only the sound driver, which starts at byte zero. If no sound card is selected, PC-Speaker driver is loaded anyway, but is not used. This last MCB takes up all the rest of the available conventional memory, even though it is not necessary.
- I have verified that the data contained in MCGA.COD and MCGA.DIF is not found in memory while Stunts is running. This is a confirmation that the information is compressed.
- Some variables are stored at positions that seem to be also variable respect to LOAD.EXE's starting code offset, even though they are within the same MCB. This is still a kind of mistery to me

Hope it's useful
Title: Re: bypassing load.exe
Post by: llm on November 26, 2009, 08:59:09 AM
>Hope it's useful

its informative - but a little bit outdated due to the fact that clvn already created an
combined version of the load.exe + hdr, dif, cmn and cod files - only the .drv file is still loaded at runtime
and this version is also cracked (no need for the "unoffical" stunts.com or stunts_k.exe anymore)

just use his version for further investigation (you can then delete load.exe/*.hdr/*.cmn/*.cod/*.dif and stunts.com, stunts_k.exe)

http://dl.dropbox.com/u/213479/execombiner.zip (http://dl.dropbox.com/u/213479/execombiner.zip)



Title: difference between ida 4.9 freeware and a recent version
Post by: llm on November 26, 2009, 09:23:04 AM
@clvn

i ask a friend of mine to diff the output of ida 4.9 freeware with a recent ida version - the differences for the
game_cracked.exe is marginal only some dos interrupts and std c library calls are better recognised

so is seems to be fully ok to go with the 4.9 version
Title: Re: bypassing load.exe
Post by: llm on December 06, 2009, 01:27:31 PM
and it think John Jordan is a good person to ask for the "right" way of doing the port
he creates jjffe - the reverse engeneered version of ffe (frontier first encounters) - from 16bit, dos-extender -> 3dbit win32(directx)

http://jaj22.org.uk/jjffe/jjffefaq.html#q3 (http://jaj22.org.uk/jjffe/jjffefaq.html#q3)

as you can read here he used a special version of the ndisasm from the nasm assembler
maybe he could give good avises for doing the port
Title: Re: bypassing load.exe
Post by: clvn on December 07, 2009, 09:17:09 PM
Quote from: llm on December 06, 2009, 01:27:31 PM
and it think John Jordan is a good person to ask for the "right" way of doing the port
he creates jjffe - the reverse engeneered version of ffe (frontier first encounters) - from 16bit, dos-extender -> 3dbit win32(directx)

http://jaj22.org.uk/jjffe/jjffefaq.html#q3 (http://jaj22.org.uk/jjffe/jjffefaq.html#q3)

as you can read here he used a special version of the ndisasm from the nasm assembler
maybe he could give good avises for doing the port

thats a mad cool project, but apparently the original ffe was written for 32-bit to begin with (borlands dpmi extender to be specific). that simplifies things dramatically from a porting point of view since e.g access to pointer variables and structs containing pointers is basically not a problem. thus most of their disassembly can be copy/pasted without any processing. our case however will require quite a bit of manual fixing to run on 32-bits. that said, i'm still gonna check the output of ndisasm at some point.


btw, ive updated the .idc-script that automates idapro: http://dl.dropbox.com/u/213479/anders.idc (http://dl.dropbox.com/u/213479/anders.idc)

the script spits out an .asm file for each function and an .inc for each segment in the currently open ida-project. still a work in progress. i was able to compile all functions in stunts into separate .obj files using tasm and a few minor adjustments. which is pretty neat, but then linking with tlink failed miserably. i believe the linking issue can be resolved by reorganizing the script a bit to either 1) output an .asm per segment rather than per function, or 2) reduce the number of publics/externs in the asm-files. but i havent found time for it yet.
Title: Re: bypassing load.exe
Post by: llm on December 08, 2009, 07:06:38 PM
Quote...but apparently the original ffe was written for 32-bit

oh! i forgot to mention this (small evil) difference :)

Quotei was able to compile all functions in stunts into separate .obj files using tasm...

so your using the borland toolchain - i think that is the best decision - the best 16bit c and asm environment of that time
+ an wonderfull debugger - what version of borland c do you use - the one from the link above?
i think we should share our toolchain enviroment

Quote...and a few minor adjustments...

do we need an transformer-script or something like that
is the adjustment regular enough for automation? what is you prefered language for scripting? python, perl, php...?

as an idea for the seperation: i would use a function prefix (fake namespace) in ida like unknown_, graphics_..., or msqc_ for automated
seperating the functions in different inc/asm and resulting obj files
(then we can start replacing the .obj bases with c derivates - step by step - without loosing the contact to ida)

and i think it would be great to have all the waiting-for-c-translation asm code in inline-assmbler inside an borland c projekt
(makes it much easier to play with the debugger and doing the replacing stuff)

ciao llm
Title: Re: bypassing load.exe
Post by: clvn on December 13, 2009, 07:59:07 PM
hello!

the project has come to the point where the original game executable is successfully disassembled and recompiled back into a new executable:

http://dl.dropbox.com/u/213479/restunts.exe (http://dl.dropbox.com/u/213479/restunts.exe)

could interested people please download this exe, put it in your stunts directory and give it a test run? id like to hear about any problems/crashes/etc. feedback is welcome here or on irc #stunts /efnet
Title: Re: bypassing load.exe
Post by: llm on December 13, 2009, 08:38:57 PM
a more technical background for the restunts.exe

Title: Re: bypassing load.exe
Post by: dstien on February 06, 2013, 01:20:44 AM
First commit in 18 months. 8)

Finally checked in the remaining decompression functions. Now to focus on some more exciting parts of the code. There are currently some regressions in the ported simulation code that I'll look into.

Current status: http://re.stunts.no/status/2013-02-05.html
Title: Re: bypassing load.exe
Post by: llm on February 06, 2013, 10:37:42 AM
thx for keeping the project active

im still working on my 16-bit-opcode to c code converter/emulator in my very very limited spare time...
(btw: a nice and very small (due to real-mode-only) emulator able to run stunts is fake86 http://sourceforge.net/projects/fake86/)

Title: Re: bypassing load.exe
Post by: RacerBG on February 08, 2013, 05:56:19 PM
I don't know what I can do but if you wish I can help.

For sure I can't code at all. ;D
Title: Re: bypassing load.exe
Post by: AureliusR on March 17, 2013, 06:42:06 PM
My god, I read through the whole thread thinking to myself, nobody will have replied in years, and then I got to the end and to my disbelief, people are still playing and reverse engineering this childhood gem of mine that nobody I've ever known has heard of or played!!

I'm not sure what I can contribute to this reverse engineering as my programming skills are limited to C++, PHP&MySQL and a bit of Visual Basic... :S however I'm sure I can help somehow, whether it be computing power or logic skills, or something. Please keep me in the loop as I'm extremely interested in this project!

I'll even start learning relevant languages if needed. BTW it may be irrelevant but I use Ubuntu, Fedora and Windows so my OS skills are sharp, at least. And what llm said: DOSBox is an excellent emulator that does Stunts perfectly on my x86-64 computer (to my surprise) if you hadn't already heard of it.
Title: Re: bypassing load.exe
Post by: w4kfu on March 19, 2013, 10:50:10 AM
Hello,
I started reverse enginerring also this game for fun and profit.
I have already coded an unpacker for EXEPACK, and a decompressor for their file format using huffman binary tree, I'm going to code a compressor too.
I'm on irc "irc.efnet.org" #stunts, is it the official channel ?
Title: Re: bypassing load.exe
Post by: BonzaiJoe on March 19, 2013, 12:52:44 PM
Quote from: w4kfu on March 19, 2013, 10:50:10 AM
Hello,
I started reverse enginerring also this game for fun and profit.
I have already coded an unpacker for EXEPACK, and a decompressor for their file format using huffman binary tree, I'm going to code a compressor too.
I'm on irc "irc.efnet.org" #stunts, is it the official channel ?

Hey AureliusR and w4kfu, and welcome. Great to hear about your work and your love for Stunts.
#stunts on EFNet is the official Stunts channel, but we don't really use IRC anymore. There is a chat room in connection with this forum, which is sometimes used, but generally the forum is the main channel for communication.

Apart from the people in this thread, Duplode also plays with the code.
Do you wanna play the game also? The competition is happening as we speak at "http://stunts.hu/zak"
Happy reverse engineering! :-)
Title: Re: bypassing load.exe
Post by: CTG on March 19, 2013, 01:08:25 PM
who are these mysterious hackers...
Title: Re: bypassing load.exe
Post by: Friker on March 19, 2013, 04:52:23 PM
Quote from: CTG on March 19, 2013, 01:08:25 PM
who are these mysterious hackers...
your ghosts?
Title: Re: bypassing load.exe
Post by: w4kfu on March 19, 2013, 10:32:51 PM
Tonigh, I found some times to work on my compressor, I'm now able to edit for example "MISC.PRE" after uncompressing it, change some strings, recompress it, and the game prints the strings I edited.
If you are interested to see the code you can find it on my github : https://github.com/w4kfu/Stunts/
Title: Re: bypassing load.exe
Post by: Duplode on March 20, 2013, 03:09:34 AM
Hello w4kfu, and hello AureliusR!

Quote from: w4kfu on March 19, 2013, 10:32:51 PM
Tonigh, I found some times to work on my compressor, I'm now able to edit for example "MISC.PRE" after uncompressing it, change some strings, recompress it, and the game prints the strings I edited.
If you are interested to see the code you can find it on my github : https://github.com/w4kfu/Stunts/

We already had a decompressor for packed resource files, namely dstien's stunpack, though no one had written a compressor yet :) stunpack is at the core of stressed, which is the tool we use for creating custom graphics. You can find it at: http://code.google.com/p/stuntstools/

The Stunts Wiki gives a good overview of what we already know about the data files. http://wiki.stunts.hu/index.php/Resource_file_format is a decent starting point if you want to read on that. In addition, there was reasonable progress towards reading and porting disassembled code, though these efforts are currently under-documented (not to say under-publicized). For information beyond what is hinted in this thread, the best person to ask at this point would be dstien (I am too much of a dilettante in that field to be able to give a sensible overview  :)). I should also mention the replay logging (http://forum.stunts.hu/index.php?topic=2862.0) thread, which reports a very recent attempt to leverage some of that knowledge.
Title: Re: bypassing load.exe
Post by: w4kfu on March 20, 2013, 01:22:40 PM
Quote from: Duplode on March 20, 2013, 03:09:34 AM
We already had a decompressor for packed resource files, namely dstien's stunpack, though no one had written a compressor yet :) stunpack is at the core of stressed, which is the tool we use for creating custom graphics. You can find it at: http://code.google.com/p/stuntstools/

I'm actullay still studying how load.exe works (especially for .COD, .DIF, .HDR, .CMN), and stuntstools handle badly these files, because it checks if the uncompressed file size is present at the first byte of the uncompressed data, see : http://code.google.com/p/stuntstools/source/browse/src/app/resource.cpp#126
But for these files, this information is not present, that's why I rewrote my own implementation (using Huffman tree implementation, despite huffman tree-less in stuntstools), and beeing able to understand well how load.exe deal with these files.
Title: Re: bypassing load.exe
Post by: dstien on March 20, 2013, 08:24:53 PM
Welcome w4kfu, intriguing work!

stressed will only load files in Stunt's resource file container format. There's a separate command line tool in the stunpack repository [1]. There's also a another implementation in restunt's [2] fileio.c, just a direct ASM to C conversion.

[1] https://code.google.com/p/stuntstools/source/checkout?repo=stunpack
[2] svn://anders-e.com/restunts/trunk
Title: Re: bypassing load.exe
Post by: w4kfu on March 20, 2013, 08:50:32 PM
Quote from: dstien on March 20, 2013, 08:24:53 PM
intriguing work!

What do you mean by intriguing ?

Thanks for pointing me to this svn, there is a lot of cool stuff in here, and yeah I didn't see the seperate command line tool :(
Title: Re: bypassing load.exe
Post by: w4kfu on March 21, 2013, 05:23:56 AM
I continued my development, and writting a new toolz for uncompressing the real game.
This toolz can make executable for CGA, EGA, MCGA, TDY, for example :

./bin/makegame -h test/4DSD/MCGA.HDR -m test/4DSD/EGA.CMN -d test/4DSD/MCGA.DIF -c test/4DSD/MCGA.COD

and it outputs a "game.exe", and this file can be unpacked with my unpacker UNEXEPACK on my github.

But ... I run it, click on "let's drive" and got this error :

(http://blog.w4kfu.com/public/stunts_problem.png)

I will try to fix it as soon as possible.
Title: Re: bypassing load.exe
Post by: dstien on March 21, 2013, 09:02:06 AM
Quote from: w4kfu on March 20, 2013, 08:50:32 PM
Quote from: dstien on March 20, 2013, 08:24:53 PM
intriguing work!
What do you mean by intriguing ?
Intriguing as in "arouse the curiosity or interest of; fascinate". ;)

Haven't got the chance to dive into your code yet, but it's very interesting that you've analyzed the compression and made an encoder. restunts have been evolving slowly lately, so I'm eager to see which direction you plan to go with GAME.EXE.
Title: Re: bypassing load.exe
Post by: w4kfu on March 21, 2013, 06:15:10 PM
Quote from: dstien on March 21, 2013, 09:02:06 AM
but it's very interesting that you've analyzed the compression and made an encoder
My program can print graph (.dot) for explaining how my huffman decoding binary tree works. As exemple for the files "MISC.PRE" : http://blog.w4kfu.com/public/stunts/graph_test.png (Image very big, I don't insert it on the forum)
For example as you can see on the graph the byte 0x1B (green nodes) is encoded as follow : "1111001100"

Btw I found my bug, I don't know why but when it try to retrieve information related to the copy protection (X word at Y line ... etc), it try to find a ressource from the file "MISC.PRE" after uncompressing it, prefixed with the letter "e", for example it try to open "eqc0" but ... the file inside "MISC.PRE" is prefixed with : "g" ... "gqc0".
Don't really understand if my toolz fail, or there is another protection that I didn't see at the moment.
Btw this can be patched easily, by iniliazing the variable I called it "protection_disable" to 1 instead of 0 in the main function.
For my version of the game :

dseg:A6AA byte_45E1A      db ? 

seg000:02A8                 mov     byte_45E1A, 0


Btw I'm actually working with 4D Sports - Driving Version 1.1 (Dec 13 1990)

Another fix, If I take the file "MISC.PRE" from your svn, it seems to have the good prefixes, maybe the version of stunts I'm working on has been fucked ...
Title: Re: bypassing load.exe
Post by: w4kfu on March 22, 2013, 10:08:13 AM
Now that I understand how stunts.com, load.exe manage to load the real "game.exe", I'm now able to start reverse engineering the real game, I would like to know what's your need  ?
Is there any file format that are not documented / known ? Is there any bug for some file format ?, I will be glad to start helping you :)
Title: Re: bypassing load.exe
Post by: Oscar on March 22, 2013, 04:22:41 PM
Cheers  :)
Title: Re: bypassing load.exe
Post by: llm on April 13, 2013, 07:38:49 PM
QuoteI continued my development, and writting a new toolz for uncompressing the real game.
This toolz can make executable for CGA, EGA, MCGA, TDY, for example

are you aware of that such a tool already exists since october/2009?
see first post from clvn http://forum.stunts.hu/index.php?topic=2454.0

we've got an working unpacked, unprotected game.exe suiteable for statical reverse engineering
that is the base of the "restunts" project - restunts uses the reverse engineered (using IDA Pro Free) asm code - partialy replaced with c code
in an tasm/msc/wlink environment able to create a working 16bit dos program

the inital idea is to use an 16 bit environment to ease the porting to c and still keep an "working" game around

current status of the porting can be seen here: http://re.stunts.no/status/

source, idb and complete build-system can be found here: svn://anders-e.com/restunts/trunk/restunts

my own idea - wich suffers permanetely from missing spare time is to combine an simple 16-bit emulator with an fake 16bit assembler in C/C++ - i would like to interchange real 32 bit C/C++ code with fake asm-code and still interpreted code, and to get the real power of current development environments on the desk (test example http://pastebin.com/TGe0igCD)

@dstien: are you still updating the idb in the svn repo?
Title: Re: bypassing load.exe
Post by: RacerBG on May 13, 2013, 05:38:40 PM
Hello guys Im back here again (this time with Linux OS). 8)

Here you are making excellent progress and well done for this. I have just 2 newbie questions about this awesome project:

What exactly we can achieve from this? ;D

What is the reason to ignore some things in the .exe file?
Title: Re: bypassing load.exe
Post by: dstien on June 01, 2014, 05:47:20 AM
Ported some more functions (http://re.stunts.no/status/) after another year-long hiatus. Most asset loading and init functions should be done now, and I have begun digging into the heartbeat functions. Real greasy stuff.

When we can run the gameloop path used by repldump I plan to start a new repository that is technically and legally clean, so I'm not focusing on graphics, sound and interactivity. Will probably take another decade at this pace. ;D
Title: Re: bypassing load.exe
Post by: zaqrack on March 16, 2015, 05:34:40 PM
A coder (a very good one at that ;)) friend of mine connected me with a couple of guys who are working on emulating Stunts at the machine code level, while replacing all graphics. They know about ZakStunts, not sure if they are aware of restunts and the rest of stuff here. Hopefully more info coming soon and we can combine forces!
Title: Re: bypassing load.exe
Post by: divip on March 16, 2015, 10:45:10 PM
Quote from: zaqrack on March 16, 2015, 05:34:40 PM
A coder (a very good one at that ;)) friend of mine connected me with a couple of guys who are working on emulating Stunts at the machine code level, while replacing all graphics.

Hi, I'm divip, a Hungarian coder living in Budapest.

Recently I've joined Csaba Hruska's project on an OpenGL based Stunts remake. Maybe you already know of this, here is a youtube video of it:  https://www.youtube.com/watch?v=XoE5CKLLnaM (https://www.youtube.com/watch?v=XoE5CKLLnaM)

We decided that besides developing the modern Bullet physics, the authentic original physics should also be kept. This is what I am working on now.

Quote from: zaqrack on March 16, 2015, 05:34:40 PM
They know about ZakStunts, not sure if they are aware of restunts and the rest of stuff here.

I have skimmed through this thread several times and I have read a few other resources around here too.
The uncompressed game.exe and the disassemled code is a huge help!
Restunts C files also helps understanding.

We chose a different path to revive the original physics.
First, we use the uncompressed game.exe as a starting point.

Then we emulate every single 8086 instructions and the needed DOS functions with a Haskell program.
The Haskell emulator is at the moment 3338 LOC, located in 8 files in this directory:
https://github.com/csabahruska/stunts/tree/master/emulate8086
Currently it is a bit slow (takes 26 seconds to reach the main menu), but it seems to do the right job.

Next, we are going automatically transform the machine code into a program library.
This is not trivial at all, but we have some initial results already.

Quote from: zaqrack on March 16, 2015, 05:34:40 PM
Hopefully more info coming soon and we can combine forces!

I hope I could give a good overview of our efforts and I hope we can report more progress soon!
Title: Re: bypassing load.exe
Post by: Duplode on March 17, 2015, 05:33:24 AM
Quote from: divip on March 16, 2015, 10:45:10 PM
Quote from: zaqrack on March 16, 2015, 05:34:40 PM
Hopefully more info coming soon and we can combine forces!

I hope I could give a good overview of our efforts and I hope we can report more progress soon!

Hello and welcome! Fascinating project - even more so for an occasional Haskeller like myself. I'll be sure to keep an eye on it  :)
Title: Re: bypassing load.exe
Post by: zaqrack on March 17, 2015, 08:39:26 AM
Hi divip,

thanks for joining! Excellent work, thanks for letting us know the progress! Having the option to keep original physics is key aspect for me.
Let me know if we can help with anything.
Would your approach -once completed- possibly open the way for newly designed 3D track elements?

Title: Re: bypassing load.exe
Post by: dstien on March 17, 2015, 11:58:52 PM
Quote from: divip on March 16, 2015, 10:45:10 PM
Hi, I'm divip, a Hungarian coder living in Budapest.

Welcome, divip! Nice to finally hear from the mythical Haskell Stunts project. :)

Quote from: divip on March 16, 2015, 10:45:10 PM
We decided that besides developing the modern Bullet physics, the authentic original physics should also be kept. This is what I am working on now.

Good choice. I too tried to combine Stunts' assets with a modern rendering engine and Bullet once. It turned out to be remarkably boring after just a few minutes. The dirty physics engine is definitely needed. ;D

Quote from: divip on March 16, 2015, 10:45:10 PM
We chose a different path to revive the original physics.
First, we use the uncompressed game.exe as a starting point.

Then we emulate every single 8086 instructions and the needed DOS functions with a Haskell program.
The Haskell emulator is at the moment 3338 LOC, located in 8 files in this directory:
https://github.com/csabahruska/stunts/tree/master/emulate8086
Currently it is a bit slow (takes 26 seconds to reach the main menu), but it seems to do the right job.

Next, we are going automatically transform the machine code into a program library.
This is not trivial at all, but we have some initial results already.

llm was working on a similar approach with Fake86 (http://fake86.rubbermallet.org/) in C, but time is unfortunately not a renewable resource. Really looking forward to hear more about your progress on this project. In addition to being awesome, the outcome will be useful for restunts as well.
Title: Re: bypassing load.exe
Post by: divip on March 18, 2015, 02:52:58 PM
Quote from: zaqrack on March 17, 2015, 08:39:26 AM
Let me know if we can help with anything.

I have just made the emulator 2x faster, it is possible to reach the main menu in 13 seconds now.
Still not playable, but if I succeed with more optimization, then there is the always needed testing task; I have to know that I didn't go off the path and I am working with the same Stunts that you are playing with.

Quote from: zaqrack on March 17, 2015, 08:39:26 AM
Would your approach -once completed- possibly open the way for newly designed 3D track elements?

Yes, there is a high chance for that if my project will be successful!
Title: Re: bypassing load.exe
Post by: divip on March 18, 2015, 03:11:37 PM
It's good that you and Duplode are interested in our project.

Quote from: dstien on March 17, 2015, 11:58:52 PM
llm was working on a similar approach with Fake86 (http://fake86.rubbermallet.org/) in C, but time is unfortunately not a renewable resource.

One of my friends also suggested Fake86. Now I had a look at it again.

I appreciate it, definitely a good resource.

It is at least one magnitude larger codebase than my emulator, partially because I only support Stunts.

The emulator part of our project is almost complete now, only more speedup is needed.
I will use Fake86 as a reference in bug fixing. Currently there is one known bug in my emulator, in some circumstances it cannot find a file; I suspect some weird CPU flags handling behind this bug.
Title: Re: bypassing load.exe
Post by: llm on May 01, 2015, 07:42:38 AM
FYI: i've developed a small tool that integrates the adlib sound-driver into the combined/cracked exe - so no dynamic code loading

latest version is attached a the end of this thread

http://forum.stunts.hu/index.php?topic=3019.15