Might & Magic World of Xeen hacking
If, for some reason, you want to contact me my email is:
I will try do describe how I went about extracting the information from the xeen.cc, dark.cc and intro.cc, and how I got that information to a readable format.
First of all I would like to thank Mike from the
Might and Magic 6-8 Level Editor project for his help and suggestions which got me started, vrenak for helping me with finding the decryption pattern, Apoc^ for suggestions on how to optimize my code and czn for looking trough the code and beeing the most hacker i know
And a very big thanks to Ramses2 for giving(!) me the oreginal games in perfect condition boxex with manuals and everything
I use the following tools
- NTFILMON - a program that monitors disk access.
- Frhed - a hex editor with some great features.
- Excel - spreadsheet to find the decryption pattern.
- Photoshop - to view the various picture formats.
The first thing I did was to start the ntfilmon and configure it to only displaying access to files in the directory where I have xeen installed. This is done under filters.
Next I started xeen and started a new game, I then alt-tabbed out to se what the program was doing. What I saw was that the exe file first tries to load a file, which is not found, and then it reads from the xeen.cc file. I then went to a specific place in the game where I knew there would be a text dialog and initiated it. The specific place was the mayor of Vertigo, Gunter.
Filemon not only displays what the program is doing to a file: read, write and queries it also displays where the program read from the file and how much it reads and an offset.
Filemon did not show that is had loaded anything new so I scrolled up in the text to se if I could find any interesting "file not found". I found a text file and decided to look at it.
I started frhed and loaded the xeen.cc. Then I used the goto feature from the edit menu, here you can type any address or a +/- offset from the current address. So I typed the offset I got from ntfilmon and I ended at a place in the file where there was a lot(!!) of 7s before the cursor and some characters, mostly capital letters, some symbols (/[]@^) and some characters that wasn't displayable (see the ASCII table).
Then I used the copy feature which has some very nice features in frhed. You can choose which offset you want to copy to or how many bytes you want. The last feature is perfect for this task as ntfilmon displays how many byte the program reads. So I copied the amount that the game read from the file when it loads the area. Then I replaced some common characters with the following character (H -> I) and pasted the changes into my xeen.cc.
I then restarted the game, went to the mayor, saved my game and then I activated the dialog, to my joy the dialog was distorted, some of the characters was wrong.
I had now found a good starting place for probing the encryption to figure it out.
I found out that the first letter in the text segment (an r) was the starting of the mayor dialog (a G) so I started the tedious task of replacing the letter with something else, load the game, and note what the change was.
This took some time as there are 127 characters in the ASCII table, and I also found that the letters with the lowest value was the same as some of the later, it seemed that whatever the pattern was it was repeating. Characters 64 to 192 was mapped to characters 0 to 128 in ASCII, unfortunately it was not something as simple at a rotational encryption (where each letter is replaced with a letter a set number of places shifted left or right in the alphabet). I found all the 127 ASCII characters and I found that they were repeating in the beginning. This should have alerted me that something was wrong. It is illogical that two encrypted characters give the same decrypted text as it wastes bytes.
I put the character in excel like this, fist the character I entered in the test file, then the result from the program. I then incremented the ASCII value in the text file with one and read a new character from the program, "rinse repeat, always repeat".
Encrypted ASCII code in decimal |
--> |
Decrypted ASCII code in decimal |
| 0 |
--> |
53 |
| 1 |
--> |
52 |
| 2 |
--> |
55 |
| 3 |
--> |
54 |
| 4 |
--> |
49 |
| 5 |
--> |
48 |
| 6 |
--> |
51 |
| 7 |
--> |
50 |
| 8 |
--> |
61 |
| 9 |
--> |
60 |
| 10 |
--> |
63 |
| 11 |
--> |
62 |
| 12 |
--> |
57 |
| 13 |
--> |
56 |
| 14 |
--> |
59 |
| 15 |
--> |
58 |
| 16 |
--> |
37 |
I used the decimal numbers from the ASCII table, they are easy to plot to a graph.
I spent quite some time trying to find some smart pattern or algorithm in the order of the decryption. It showed as a very distinct pattern in excel when I plotted the values in a graph. I ended up with a sequence of operations that described the changes in the bytes. And there was a pattern I at least could code my way out of, and I did. I was able to reproduce the number sequence from the decrypted table
 |
| Partially incorrect decryption attempt |
I then wrote a simple program that reads a given number of bytes from a file, from an offset.
And then decrypted it (logging each byte in a table) and wrote the new file... I opened the newly decrypted text file and it was in plain text and readable! Joy!
Next step was the pictures.
There are a lot of file formats in the xeen.cc file and I knew none of them except txt. One file used for animations is a .vga file and another used for static images is a .raw file. I extracted a raw file and searched a file extension database to se what it was. According to the database it is a graphics file format with only the raw data, no header information about the picture. So I opened the file in Photoshop, which prompted me for width and height, earlier I had taken some screen shots from xeen and I knew from there that the file format was 320x200 so I entered those values. I got a very nice grayscale image of the intro screen.
 |
 |
| B/W Xeen intro screen extracted with bad decryption table |
B/W Xeen intro screen |
Next thing was finding a palette, and ntfilmon showed that the program had read a file named mm4.pal file of 768 bytes earlier. So I extracted that and looked at it using another of frhed's features: Under options -> view setting you can give the numbers of bytes to be displayed in a line (remember to uncheck the box where it chooses its one number of bytes to display) so I set it to 3 as I could se a repeating 3 bytes in the start of the .pal file, and it showed a very list of byte values, looking like RGB values. I then changed the image in Photoshop to indexed color and tried to load the palette file as each of the formats Photoshop supports.
The colors were very dark and some of them were distorted, otherwise it looked right.
I wrote a program to convert the palette to other formats but with the same result, the colors were way to dark.
 |
| Xeen intro screen with extracted palette |
Then I opened one of the screenshots I took and extracted the palette from it and used it as the palette from the .raw image. That gave the correct bright colors but the distortion was still there, the orange areas were blue, the red were yellow and some of the bits were just wrong.
 |
| Xeen intro screen extracted with bad decryption table |
I suspected that the program maybe had 2 different ways to handle binary and text data.
I then wrote a program to compare each byte from the extracted image and the screenshot which I converted to a raw file. The images was not exactly the same as there were an animation loop with some green smoke in the sides but it still provided enough data so that I could compare it. The overall structure was the same but there was no repeating pattern. I modified my program to generate code that matched the new set of data and made a new decryption table.
 |
| Correct decryption table, sadly i have no algorithem to describe it with |
Then I extracted the image again and opened it using the palette from the screenshot, it worked.
 |
| SUCCESS! The Xeen intro screen from the new palette |
I then extracted some text which was also correct, so I discarded the old program and am now using the new decryption table.
I spent some time making a program to phrase the ntfilmon logs so I colud extract the mentiond files without having to type in the input, output, size and offset myself
Combined with the new fast extractor i can now start up the game with ntfilmon monotoring disk access. Load a game or do some other things, then I save ntfilmon's log and start my program which then extracts all the files that Xeen used. This takes about 5 seconds.
I also used a modified version of my picture analyze program to analyze the extracted palette and the one from the screenshot. After some messing around I found out that each value in the game palette is 4 times lower than the one from the screenshot. I then have to write a program that corrects this. I have found that there are 4-5 slightly different palettes in the game which i need to correct.
Validated and known file formats:
5. april 2004.
While fiddling with some suspected area data I saw that when you start a new game it copies 5 big (64512bytes) chunks of data into xeen.cur (the current savegame), while comparing the chunks from the encrypted xeen.cc with the xeen.cur I discovered that the data in xeen.cur is not encrypted. And when I extracted the data from it I had previously decrypted it, giving corrupt data.
The lower half of .dat files from the savegames are upside-down and mirrored representations of the game maps. The upper part still makes no sense.
 |
| A part of the first town, I applied the defalut mm4 palette, otherwise you cant tell the colors apart |
Progress is going slow now. The icn files seems to be sprites - there can be several sprites in one icn file, I think I have found some meaning in the header and in the header of the individual sprite. I decoded a sprite by hand and it seemed somewhat right so i wrote a program to decode them. The program also made a somewhat right image but it seems distorted and there are some strange colors in it:
 |
 |
 |
A sprite used when someone is hit by poison, raw from the .ICN file |
Same sprite but put trough my program not that good. |
Same sprite taken from a screenshot |
6. april 2004
The sprite files are giving me quite a bit of trouble, all the work I did yesterday seems to end up giving some distorted image that's not looking anything like the original.
The first byte in the header seems to be the number of sprites in the file, and the number of sprites * 4 seems to be some information on the file, every fourth bit is roughly incremented by one and the next bit holds some number, the remaning bits are 0
 |
| A .ICN header |
8. april 2004
I fanally(!!) made some progress on the icn files today, I took a character portrait from a screenshot and opened the corresponding decrypted file. Then I compared the files, byte for byte and wrote down all the control codes.
First there is a code indicating what to to, it can be a lot of different things, and then a reference to a palette index to operate on.
One of the things puzzling me the most is the newline chars, they are changing all the time. I have found no explanation as to why they do this.
A list of the codes i have discovered so far
The icn file i worked with
The icn file at is should turn out Use a line width of 32.
That was my result so far, i still need to figure out the header and there are quite some code at the end of the file that is not part of the normal face. I suspect that it is the different expressions the characters can have, tired, poisoned, insane and so on.
29. may 2004
Long break due to school project/exams
I belive that I am fearly close to having a fully working sprite extractor. I have extracted the first sprite from all the charecter portraits, but i am still missing some positioning on the sprites after the first one
there is allso a problem with some codes, if the code is a code indicating that a full line of colors (32 in this case) should be read from the file, some of those colors is wrong, usually around the eys, but its a minor issue for now
31. may 2004
Happy message, I have made a great deal of progress and I have now read all the sprites (thats 4) from a mountin texture, I can skip sprites to extract following sprites in the sprite file, and there are only around 50 codes remaining that I dont know what to do with.
8. june 2004
I have now identified 2 more bytes from the file header:
1. = ?
2. = ?
3. = 1. part of with
4. = 2. part of with, (this byte value) * 256 + (3. bytes value) = width
5. = the position of a subsprite from the top of the sprite
6. = also for positioning a subsprite, same as the width
7. = height 1
8. = height 2, same as width
This along with some minor tweaks in the codes has enabled me to extract allmost all the sprites in my test set without errors.
the
2. june 2005
Phew, i made an update before a year had passes
I have made some progress in the last year and i just kind of forgot to update the webpage
The project isent dead but it has become very difficult to move forward as i dont have any experiance in this kind of thing
I have made a fully working decoder for the sprites in the game, it reads the decrypted sprite files and writes the new sprite as a PNG on the disk. If a sprite contins severals sprites eg. for an animation it writes each frame to the disk:
I have allso automated some of the trivial things do to when trying to decrypt the index but i havent looked much into processing all the data i get.
Finally I have some ideas to get mening out of the music files as i have never really worked with midi, mod or other music formats
Drop me a line if you want to help or have any questions
Known file formats
- .txt - plain text file
- .dat - sometimes plain text file
- .xen - plain text file
- .raw - raw image file format
- .voc - sound file
- .mon sometimes plain text
- .pal - palette file. Not MS pal format but each value is 1/4 of the value it displays with, in .act format
Unknown file formats:
- .vga - animation files, sprites i think
- .dat - unknown
- .pty - savegame file info
- .chr - savegame file info
- .nam - savegame file info
- .fac - character face sprites
- .icn - sprites
- .sky - sky sprites?
- .fwl - floor level?
- .evt - level information, mayb some events
- .mob - some level information?
- .hed - some level information?
- .swl - some level information - maybe sprites
- .srf - some level information - maybe sprites
- .til - probably tiles
- .gnd - probably ground tiles
- .obj - an object of some sort? ;)
- .mon - monster information?
- .att - monster attack information? extracted after .mon