I am attempting to amend some strings in an old DOS game (FIFA International Soccer), specifically the names of players.In the past it hasn't been too hard to pull off such a task on post-DOS games as either the strings are easy to track down in the executable or a data file.  However, for this DOS game I am stuck.I have scanned through the game files and the executable with a hex-editor but cannot find the strings.  The game includes a english.dat file which does contain readable localised strings.  However, this file only contains names for in game headers and menu options as opposed to the player names I am seeking.  The other files consist of localised strings for other languages, graphics and sounds.I have used a debug build of DOSBOX to perform a memory dump using the following command:memdumpbin 180:0 1000000I got the command from here: http://www.vogons.org/viewtopic.php?t=9635In the memory dump I can find the strings I wish to change.What is the best way of linking this information to find the source of the strings?  I assume that these strings are somehow encrypted or compressed in the executable, although it could be in another obscure game file.  If the strings are compressed/encrypted perhaps there is a common method for pulling this data out of the executable.I have IDA5 (free version) installed and would be happy using this as part of process.  My operating system is Windows 8 / 64 bit.Also, to be clear - I want to modify the strings at source (i.e. in the file) and not in memory.
How can I find the source of a string in an old DOS game?
disassembly;debugging;strings;dos
This program uses the PharLap DOS extender, as can be seen in its MZ header. The 32-bit executable program starts at offset 18A0, per offset within header of relocation table (see http://www.program-transformation.org/Transform/PcExeFormat), and at that position you can see the correct signature P3. According to the header info, the executable's length is 0x95851, which is another hint this is correct. Near the end of this part, starting at 18A0, you can see a text string  Hello EA, and at the next 32-byte page the signature MZ that indicates another executable is embedded. So this large part must contain the main executable.Browsing the file with a simple hex editor at my preferred width of 16 hex characters, I noticed a recurring pattern when doing page-downs (a good way to get a 'sense' of what sort of data a file contains). I saw the pattern repeated every 2 lines, and when I set the display width to 32, the pattern was evident. Executable formats always start with a fixed header, and are usually followed by lots of zeroes for padding, so I suspected the repeating pattern may be the XOR key. A simple C program confirmed this; I did not know where to start with decoding but the first non-all-zeroes multiple of 32 seemed a good guess: offset 0x1AA0. Decoding from there proved the hunch to be correct:00000 : Y...r9..n3.>..-.A@I.7P........h4..a1.P(s.......x. rG..f...X.+..00040 : ..a|D.P(.b..A...x......f3..F..h4....a.P(...........o7..f3..F2...00080 : .@@@@@@...@@BLASTER=@ULTRASND=@GOLD=@mvsound.sys@DEVICEdevice@@@000C0 : @@@@@@@@@@@.......ULTRAMID@@@@@@@@@@@@@@@ ..@.@@@@@@.........@.@00100 : .@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@.@@.@@@@..@@...@@@..@@......&...00140 : ./....8....C....N....X...@c.@@ m....y...................C.......00180 : .PCSPKR.ADV@MT32MPU.ADV@ADLIB.ADV@ADLIBG.ADV@SBFM.ADV@SBFM.ADV@S001C0 : BP1FM.ADV@SBP2FM.ADV@PASFM.ADV@PASOPL.ADV@TANDY.ADV@GF1MIDI.ADV@00200 : CUST_MID.ADV@SBP2FM.ADV@SBAWE32.ADV@@@@ALGDIG.ADV@SBDIG.ADV@SBDI00240 : G.ADV@SBPDIG.ADV@SBPDIG.ADV@PASDIG.ADV@PASDIG.ADV@@GF1DIGI.ADV@C(etc.)so the next step was scroll down to near the end of this part and see what was there. Disaster! Rather than readable texts, all I saw was random data -- yet still with clear patterns.But 'an executable' is not one contiguous long chunk of data. It's common to see it divided up into separate sections for executable code, initialized data, uninitialized data, relocations and so on. The sections all start at an aligned address when loaded into memory, but not necessarily in the file itself, or with the same 'memory page' size. Therefore, it may be possible that the XOR encryption restarts at the start of new section. The PharLap header should contain information on where each section starts and ends (and if you are going to attempt to adjust the program, you should look into this), but to confirm the XOR key is the same all I had to do is adjust the starting position. Starting one position further, no success, but 2 positions further on I noticed this piece of data:890C0 : B.@.L.@^W.@.a.@^l.@.v.@^..@...@ @ @ @ @ @ @ @~FIFA International89100 :  Soccer@ @PC Version by@~The Creative Assembly@ @~Lead Programme89140 : r@ @Tim Ansell@ @ @ @~Programmers@ @Adrian Panton@Clive Gratton@89180 :  @ @~Lead Artist@ @Will Hallsworth@ @ @ @~Additional Artwork@ @A891C0 : lan Ansell@ @ @ @~Original Music@Composed, Produced@and Performe89200 : d by@Ray Deefholts@for ~HFC Music@ @Additional Drum@Programming 89240 : and@Assistance@ @Tim Ansell@ @~Sound Effects@ @Bill Lusty@ @ @ @89280 : ~Producer@ @Kevin Buckner@ @ @ @~Associate Producer@ @Nick Golds(etc.)That was the proof I needed: the data section does use the same XOR key. Next: testing all possibilities from 0 to 31 and see if something turns up. Only at +30 that turned out to work, just as I was going to give up:782C0 : ..@...@,..@..Algeria@Ali Mehdaoui Igail@Mohammed Said@Abdel Dahb78300 : i@Hamid Ahkmar@Nagar Baltuni@Omar Mahjabi@Ali Cherif@Hamar Mahbo78340 : ud@Khered Adjali@Imahd Tasfarouk@Alamar Sahid@Mahmar Ahboud@Akha78380 : r Binnet@Mouhrad Dahlib@Mahied Amruk@Lakhar Diziri@Amaar Azir@Mu783C0 : stafa Farai@Akmar Bahoud@Ahmad Said@Taraki Aziz@Argentina@Alfio (etc.)So each individual section in the executable is encrypted with a 32-byte XOR key; this XOR key is the same for all sections; it starts a-new per section.The C program below will decrypt the entire file and you have to adjust the starting position manually. To edit the file, you have to:Read up on PharLap's sections.Decrypt each section individually.Write all into a new file.Adjust what you want.Encrypt the sections again (it's a XOR key, so this uses the exact same algorithm).Copy the encrypted file back into the main executable.A note on #4: you mentioned changing the names of the players. Since it's a zero-terminated list of names, you can assume there is a list of pointers to these names somewhere else. That means you can only change the individual characters of a name -- not make it longer. If you want to adjust all names freely, you must find the list of pointers and adjust that as well.(Preliminary updates)The XOR encoding does not use sections. Instead, it seems like every block starts with a word determining its length, and possibly 1 or 2 next words (possibly (again) to set the XOR key starting position). Not conclusive so far.Executables are abundant with zeroes. If you count the number of zeroes in each 32-byte chunk, XORed against all 32 possible positions, and print out the XOR position with the highest number of them, you can see successive lists of the same 'best' guess. That shows there are longer and shorter sections XORed with the same key and may help determining the length algorithm.#include <stdio.h>#include <stdlib.h>unsigned char encrypt[32] = {    0x23, 0x91, 0xC8, 0xE4, 0x72, 0x39, 0x9C, 0xCE,    0x67, 0x33, 0x99, 0xCC, 0xE6, 0x73, 0xB9, 0x5C,    0x2E, 0x17, 0x8B, 0x45, 0xA2, 0x51, 0xA8, 0x54,    0x2A, 0x95, 0xCA, 0x65, 0x32, 0x19, 0x8C, 0x46};int main(int argc, char *argv[]){    FILE *f;    int i, c, d = 0;    f = fopen (../Downloads/fifa/fifa.exe, rb);    if (!f)    {        printf (yeah no such file\n);        return 0;    }    /* reasonable assumption for start: */    fseek (f, 0x1aa0, SEEK_SET);    /* adjust per section! this position is valid for the names only */    fseek (f, 30, SEEK_CUR);    c = 0;    printf (%05X : , d);    do    {        d++;        i = fgetc (f);        if (i == EOF) break;        i ^= encrypt[c & 31];        if (i >= ' ' && i <= '~') putchar (i); else if (i) putchar ('.'); else putchar ('@');        if (++c >= 64)        {            c = 0;            printf (\n);            printf (%05X : , d);        }    } while (d < 0x95851);    fclose (f);    return 0;}