.text:0041D608 push offset password
.text:0041D60D push offset user_name
.text:0041D612 jz short loc_41D640
.text:0041D614 movzx ecx, byte_46254C[eax]
.text:0041D61B push ecx
.text:0041D61C push edx
.text:0041D61D lea eax, unk_4624CC[eax]
.text:0041D623 push eax
.text:0041D624 push offset name_dll
.text:0041D629 lea ecx, [esp+3968h+CmdLine]
.text:0041D630 push offset aSSDDSS ; "%s %s %d %d %s %s"
.text:0041D635 push ecx ; char *
.text:0041D636 call _sprintf
Yes login and password are passed on the command line in plain text ...
Sunday, July 14, 2013
Dark Age of Camelot : Credentials plain text
After login screen, the login.dll executable will launch game.dll, with the function ShellExecute, but :
Saturday, July 13, 2013
Dark Age of Camelot : Connection
Today I wanted to understand the protocol for sending credentials to Dark Age of Camelot server.
Here is the schema :
When a client connect on a DAOC server, he will receive the following packet :
DAOC client (client.dll), use a old version of libtomcrypt, here is an implementation of the code used for generating the buffer used to send the rc4 key to the server.
Here is the schema :
[ 0000] 1B 1B 00 08 00 65 00 00 00 11 00 00
Format
[ 0000] 1B 1B : Version
[ 0002] 00 08 : Size
[ 0004] 00 65 : Message Type
[ 0006] 00 00 : Unknow
[ 0008] 00 11 : Version Client ?(0x11)
[ 000A] 00 00 : Unknow_02
All the further communications will be encrypted using a rc4 key generated by the client :
v0 = 0;
do
key[v0++] = rand();
while ( v0 < 59 );
This key is then RSA encrypted and exchanged with the server.DAOC client (client.dll), use a old version of libtomcrypt, here is an implementation of the code used for generating the buffer used to send the rc4 key to the server.
unsigned char daoc_pub[] =
{
0x91, 0x00, 0x00, 0x00, 0x01, 0xC1, 0x00, 0x00, 0x00, 0x02, 0x15, 0xB3,
0x4E, 0xAF, 0x3A, 0x93, 0xA3, 0xC7, 0x4A, 0x6A, 0xFD, 0x69, 0x55, 0x45,
0x1D, 0x38, 0x6A, 0x8D, 0xA1, 0xDF, 0x70, 0x1F, 0x84, 0x93, 0x23, 0xE7,
0x95, 0x7F, 0xFD, 0xC5, 0x78, 0xCD, 0x42, 0x58, 0x71, 0x6B, 0xA4, 0xB5,
0x4D, 0xDD, 0xF1, 0xC6, 0xB9, 0xAE, 0xF2, 0x41, 0x65, 0xF7, 0xD9, 0x4D,
0x9C, 0xC5, 0xD6, 0xEE, 0x0D, 0x98, 0xFC, 0x23, 0x7E, 0x94, 0x84, 0xE2,
0xD1, 0x27, 0x8C, 0x67, 0xFC, 0xB6, 0x2C, 0x5D, 0xD6, 0x60, 0xA6, 0xA9,
0xC3, 0xA5, 0x04, 0x11, 0xFF, 0xFE, 0x9B, 0x90, 0x27, 0x69, 0x6A, 0x60,
0x1D, 0x89, 0x6F, 0xFD, 0x55, 0x96, 0x4A, 0xEA, 0x97, 0x34, 0x8F, 0x69,
0x79, 0xBF, 0x93, 0x26, 0x18, 0xB4, 0x7C, 0x7C, 0xD5, 0xAD, 0x0B, 0xC9,
0xC5, 0xB7, 0x8F, 0x06, 0xB4, 0x37, 0x67, 0x94, 0xE0, 0x2A, 0x7E, 0x38,
0x2F, 0x28, 0x60, 0x8A, 0xDC, 0x89, 0x7D, 0x08, 0xDD, 0xBE, 0x38, 0x34,
0xF5, 0x78, 0xD8, 0x81, 0x58, 0x9C, 0x2B, 0x03, 0x1A, 0xE0, 0xE3, 0xF3,
0x19, 0xE3, 0x63, 0x81, 0xE3, 0x7C, 0xE0, 0x5D, 0xBC, 0x8E, 0x9C, 0xDC,
0x93, 0x74, 0x24, 0xE0, 0xF4, 0x96, 0x65, 0xFA, 0x90, 0x21, 0x06, 0x03,
0xD2, 0x5A, 0xC3, 0x51, 0xBF, 0x5D, 0x03, 0xB2, 0xCD, 0xD3, 0xF1, 0x6E,
0xCB, 0xB0, 0x25, 0x71, 0x4B, 0xC6, 0x00, 0x44, 0x7A, 0xE7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01
};
void daoc_rsa_encrypt_key(unsigned char *buf, int inlen,
unsigned char *output, unsigned long *outlen)
{
rsa_key key;
int prng_idx;
prng_state statesprng;
int res;
unsigned char rsa_in[196];
unsigned long y, rsa_size;
if (rsa_import(daoc_pub, sizeof (daoc_pub), &key) != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_import() failed\n");
exit(EXIT_FAILURE);
}
prng_idx = find_prng("sprng");
if (prng_idx == -1)
{
fprintf(stderr, "[-] find_prng() failed\n");
exit(EXIT_FAILURE);
}
y = 193;
res = rsa_pad(buf, inlen, rsa_in, &y, prng_idx, &statesprng);
if (res != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_pad() failed : %d\n", res);
exit(EXIT_FAILURE);
}
rsa_size = *outlen - 2;
res = rsa_exptmod(rsa_in, y, output + 2, &rsa_size, PK_PUBLIC, &key);
if (res != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_exptmod() failed : %d\n", res);
exit(EXIT_FAILURE);
}
*output = 0;
*(output + 1) = rsa_size;
*outlen = rsa_size + 2;
}
The client will send the rc4 key block encrypted with rsa, with the following type of packet :
[ 0000] 1B 1B : Version
[ 0002] 00 C7 : Size
[ 0004] 01 54 : Message Type (ROL8(340))
[ 0006] 00 : Checksum (NULL because sym key is not yet set)
[ 0007] 00 : Sequence number of the paquet
[ 0008] 00 C1 : Size encrypted RSA key
[ 000A] XX XX : RSA encrypted key
...
Then the client can communicate the credentials of the user using the following paquet : [ 0000] 1B 1B : Version
[ 0002] 00 1D : Size
[ 0004] 01 2C : Message Type (ROL8(300))
[ 0006] 21 : Checksum
[ 0007] 01 : Sequence number of the paquet
[ 0008] 00 06 : Name Size
[ 000A] XX XX : Str_Name[Name Size]
[ 00XX] 00 02 : Password Size
[ 00XX] XX XX : Str_Password[Password Size]
[ 00XX] 00 09 : Unknow
[ 00XX] 00 : Unknow_02
This paquet will be encrypted using rc4 algorithm and the key generated, but not on all paquet ! It will start at position 0x0006.
Creating library signatures for IDA
C:\ida\flair61\bin\win>pcf tomcrypt.lib
tomcrypt.lib: skipped 25, total 566
C:\ida\flair61\bin\win>sigmake.exe tomcrypt.pat tomcrypt
tomcrypt.sig: modules/leaves: 541/485, COLLISIONS: 3
See the documentation to learn how to resolve collisions.
Resolve collisions and it's ok (collisions problems can be found in file *.exc)
Thursday, July 11, 2013
IDA : Add structur
Declaring field of structure when they are big is a pain in the ass into IDA, idapython to the rescue !
name = "WHATEVERYOUWANT"
size = 4242
struc_id = GetStrucIdByName(name)
DelStruc(struc_id)
struct = AddStrucEx(-1, name, 0)
for i in xrange(0, size / 4):
AddStrucMember(struct, "field_" + str(i), i * 4, 0x20000400, -1, 4)
if (size % 4) != 0:
AddStrucMember(struct,"field_" + str(size / 4),(size / 4) * 4,0x000400,-1,size % 4)
Wednesday, July 10, 2013
Age Of Empires III : Resources anti-cheat
If one day, you try to scan the memory of age3.exe for finding your resources like wood, or food, you will not find them in memory, because they use a lame "anti-cheat" technique.
All the value are xored with those different "secret" dword :
All the value are xored with those different "secret" dword :
.data:00BBE74C Key_XOR_Resources dd 2848AC4Fh ; // GOLD
.data:00BBE750 dd 94F83A35h ; // WOOD
.data:00BBE754 dd 8BD84C3Fh ; // meat
.data:00BBE758 dd 0AB12FBAFh ; ??
.data:00BBE75C dd 20B35BCAh ; ??
.data:00BBE760 dd 0F9ABC42Ah ; // XP
.data:00BBE764 dd 0B1A1CFDAh ; // LEVEL
.data:00BBE768 dd 0F2E48210h
Wednesday, July 3, 2013
Anno 1602
This post is an introduction to the game Anno 1602, that I'm going to study during the next blog post.
Anno 1602: Creation of a New World is a game with both real time strategyand city building elements, developed by Max Design. It's a game like "Caesar", "Colonization", "Constructor", "Exploration".
This is game is an Abandonware, so you can download it for free.
PS C:\> Get-ChildItem "C:\Games\ANNO 1602 Version Gold" -Include *.* -Recurse | Select-Object Extension | Sort-Object -Property Extension -Unique
Extension
---------
.BSH
.cod
.COL
.dat
.dll
.EXE
.GAD
.INC
.pdf
.rtf
.SCP
.smk
.szm
.szs
.WAV
.ZEI
- .BSH
- .cod
- .COL
- .dat
- .dll
- .EXE
- .GAD
- .INC
- .rtf
- .SCP
- .smk
- .szm
- .szs
- .WAV
- .ZEI
Tuesday, July 2, 2013
Desperados : Wanted Dead or Alive - .sxt files
List of files with extension .sxt :
PS F:\> $Dir = get-childitem -recurse F:\Game\Infogrames\Desperados\Game
PS F:\> $List = $Dir | where {$_.extension -eq ".sxt"}
PS F:\> $List | ft fullname | Format-Table
FullName
--------
F:\Game\Infogrames\Desperados\Game\Data\Interface\Debriefing\GameOver1.sxt
F:\Game\Infogrames\Desperados\Game\Data\Interface\Debriefing\GameOver2.sxt
F:\Game\Infogrames\Desperados\Game\Data\Interface\Debriefing\Victory.sxt
Example : GameOver2.xst
Size file : 13 954 bytes (0x3682)
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 23 01 7E 00 01 00 00 00 76 36 00 00 78 9C ED 7D #.~.....v6..xϒ}
00000010 4D 74 1A 67 9A 2E 63 50 95 8C ED 44 E9 F4 9C A3 Mt.gš.cP•ŒíDéôœ£
Format specification :
+0x00 : Width = 0x0123
+0x02 : Height = 0x007E
+0x04 : IsCompressed = 0x00000001
+0x08 : SizeCompressedData = 0x00003676
Then the data are simply image in 16 bits format, view this POST for more info.GameOver1.sxt
GameOver2.sxt
Victory.sxt
Desperados : Wanted Dead or Alive - RDO Resource
Inside .res file there is 'RDO ' (0x204F4452, notice the space at the end) entry resources.
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (7 <> 5)
Few extracted images :
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (7 <> 5)
Pseudo-Code
unknow = read(4)
if (magic_number == 0x204F4452):
a = read(4)
b = read(4)
for i in xrange(0, 7):
if ((1 << i) & b):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16bits image.Few extracted images :
Desperados : Wanted Dead or Alive - SLID Resource
Inside .res file there is 'SLID' (0x44494C53).
Those resources are exactly the same things as NPTF.
Few extracted images :
Those resources are exactly the same things as NPTF.
Few extracted images :
Desperados : Wanted Dead or Alive - NPTF Resource
Inside .res file there is 'NPTF' entry resources.
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (6 <> 5)
Few extracted images :
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (6 <> 5)
Pseudo-Code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x4E545442):
a = read(4)
b = read(4)
for i in xrange(0, 6):
if ((1 << i) & b):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16bits image.Few extracted images :
Desperados : Wanted Dead or Alive - WAVE Resource
Inside .res file there is 'WAVE' (0x45564157) entry resources.
Those resources can be managed like TEXT, the only difference is that string are not of type wchar_t.
Those resources can be managed like TEXT, the only difference is that string are not of type wchar_t.
WAVE specification
+0x00 : Unknow_00 (Maybe index)
+0x04 : Nb entry Text
+0x06 : Size Entry
+0x08 : Buffer [Size Entry]
Pseudo-Code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x45564157):
unknow = read(4)
nb_TEXT_entry = read(2)
for i in xrange(0, nb_TEXT_entry ):
size_str = read(2)
str = read(size_str)
Few extracted path :
Dialogues\Phase1.wav
Dialogues\Phase2.wav
Dialogues\Phase3.wav
Dialogues\Phase4.wav
Dialogues\Phase5.wav
Dialogues\Phase6.wav
Dialogues\Phase7.wav
Dialogues\Phase8.wav
Dialogues\Phase9.wav
Dialogues\PhaseFake.wav
Desperados : Wanted Dead or Alive - TEXT Resource
Inside .res file there is 'TEXT' (0x54584554) entry resources.
TEXT specification
+0x00 : Unknow_00 (Maybe index)
+0x04 : Nb entry Text
+0x06 : Size Entry
+0x08 : wchar_t Buffer [Size Entry]
Pseudo-Code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x54584554):
unknow = read(4)
nb_TEXT_entry = read(2)
for i in xrange(0, nb_TEXT_entry ):
size_str = read(2)
str = read(size_str * 2)
Few extracted strings :
Bonjour vous tes avec le professeur Oscar Toffel pour votre 746ime leon de patois
Entrainez vous rptez la phrase qui suit puis enregistrez vous sur K7 et envoyez la nous donc.
Le meilleur accent il gagnera un disque.
Attention rptez aprs moi.
Truc incomprhensible, si vous comprenez envoyez moi une carte postale.
Allez ! Encore une fois pour voir.
Oh lalala ca c'est donc pas facile.
Tais toi donc et bosse un petit peu ! Rptes cette phrase non di diou
Allez la balle est dans votre camp maintenant, a vous de jouer. Bonne Chance.
Je vais pouvoir rcuprer mon matriel.
J'ai laiss mes clefs dans la cariole, peut tre qu'en crochetant la porte...
Attention ! Sam ! Derriere-toi il y a un crocodile !
Je vais essayer de l'endormir l'aide de mes fioles.
Est-ce que c'est vraiment efficace ? Je suis curieux de voir a...
Je vais te faire un pansement, un bisou sur le bobo et tout ira bien.
A quoi sert le porte manteau qu'il y a dans ton sac ?
Ca sert a tromper les cowboys qui veulent ma peau.
Pour les fioles, je peux mme endormir une cible lointaine.
Debout Sam ! Il est temps de se remettre en route mais auparavant, montres moi de quoi tu es capables.
Peut-tu faire exploser prcisement ton baton de dynamite de l'autre ct de la rivire ?
Belle chute.. On ferait mieux de le ligoter avant de le cacher.
Arrtes, on en aura peut-tre besoin plus tard, pour piger les ennemis ou effrayer les chevaux.
Le chemin est bloqu... ...je m'en occupe, je vais tout dblayer...
WAHAHAHAHAHAHAHAHAHAH !
Nous voila, devant La Fortezza, la prison la plus sure de cet tat.
Et c'est ici ou ils ont emprisonne Sanchez. Mais on va le dlivrer...
Je ne comprends pas: On a fait pas mal d'efforts pour trouver ce bandit et pour le mettre sous les verroux.
Mais maintenant tu dis que l'on va le liberer de nouveau. Il est tout coup devenus ton pote, ou quoi?
Desperados : Wanted Dead or Alive - CUR Resource
Inside .res file there is 'CUR ' (notice the space at the end) entry resources.
Those resources can be managed like PICC.
Few extracted images :
Those resources can be managed like PICC.
Pseudo-Code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x20525543):
unknow_1 = read(4)
unknow_2 = read(2)
unknow_3 = read(2)
unknow_4 = read(2)
unknow_5 = read(2)
nb_CUR_entry = read(4)
for i in xrange(0, nb_CUR_entry ):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16 bits image.Few extracted images :
Desperados : Wanted Dead or Alive - BTTN Resource
Inside .res file there is 'BTTN' entry resources.
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (4 <> 5)
Few extracted images :
Those resources can be managed like PICC, this type is like TOLG but notice the loop iteration (4 <> 5)
Pseudo-Code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x4654504E):
a = read(4)
b = read(4)
for i in xrange(0, 4):
if ((1 << i) & b):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16bits image.Few extracted images :
Desperados : Wanted Dead or Alive - TOGL Resource
Inside .res file there is 'TOGL' entry resources.
Those resources can be managed like PICC, but with few differences.
Few extracted images :
Those resources can be managed like PICC, but with few differences.
Pseudo-code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x4C474F54):
a = read(4)
b = read(4)
for i in xrange(0, 5):
if ((1 << i) & b):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16 bits image.Few extracted images :
Desperados : Wanted Dead or Alive - PIC Resource
Inside .res file there is 'PIC ' (notice the space at the end) entry resources.
Those resources can be managed like PICC.
The only difference is this resource got only one entry.
Few extracted images :
Those resources can be managed like PICC.
The only difference is this resource got only one entry.
Pseudo-code
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x20434950):
unknow = read(4)
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Data is still 16 bits image.Few extracted images :
Desperados : Wanted Dead or Alive - PICC Resource
Inside .res file there is 'PICC' entry resources.
PICC specification
+0x00 : Unknow
+0x04 : Nb PICC entry
+0x08 : Entry Data (view class CResEntry)
CResEntry
An entry can be represented by this structure : 00000000 CResEntry struc ; (sizeof=0xC)
00000000 Width dw ?
00000002 Height dw ?
00000004 IsCompressed dd ?
00000008 SizeFile dd ?
0000000C CResEntry ends
If the field IsCompressed is set to 1, data are compressed using zlib version 1.1.3.Pseudo-Code to read PICC
magic_number = read(4)
unknow = read(4)
if (magic_number == 0x43434950):
unknow = read(4)
nb_PICC_entry = read(4)
for i in xrange(0, nb_PICC_entry):
width = read(4)
height = read(4)
is_compressed = read(4)
size = read(4)
data = read(size)
if is_compressed == 1:
data = zlib.decompress(data)
Then the data are simply image in 16 bits format, you can convert it into 24 bits, with the following pseudo-code : void setRGB(png_byte *ptr, unsigned char r,
unsigned char g, unsigned char b)
{
ptr[0] = r;
ptr[1] = g;
ptr[2] = b;
}
...
int x, y;
for (y = 0 ; y < height ; y++)
{
for (x = 0 ; x < width ; x++)
{
int a;
unsigned short *tab;
unsigned short color;
a = = (x + (y * width)) * 2;
tab = (unsigned short*)(buffer + a);
color = *tab;
setRGB(&(row[x * 3]),
(color >> 11 << 8) / 32,
(((color >> 5) & 0x3F) << 8) / 64,
((color & 0x1F) << 8) / 32);
}
png_write_row(png_ptr, row);
}
Monday, July 1, 2013
Desperados : Wanted Dead or Alive - Extracted Resources
Desperados : Wanted Dead or Alive - .res / .RES files
List of files with extension .res or .RES :
Method to open .res file :
ArchiveVersion must be equal to 0x100 (256).
Format can be equal to :
PS F:\> $Dir = get-childitem -recurse F:\Game\Infogrames\Desperados\Game
PS F:\> $List = $Dir | where {$_.extension -eq ".res"}
PS F:\> $List | ft fullname | Format-Table
FullName
--------
F:\Game\Infogrames\Desperados\Game\Data\Interface\DEFAULT.RES
F:\Game\Infogrames\Desperados\Game\Data\Interface\Texts.res
F:\Game\Infogrames\Desperados\Game\Data\Sounds\Expressions\Expressions.res
Method to open .res file :
005D8270 ReadResFile proc near
File format specification
+0x00 : Magic Number
+0x04 : Archive Version
+0x08 : Nb Entry
+0x0C : Format
+0x10 : Unknow_0
....
Magic number must be equal to 0x53455253 ('SERS').ArchiveVersion must be equal to 0x100 (256).
Format can be equal to :
- 0x45564157 ('EVAW') : 0x005D96A0 WaveResFile proc near
- 0x43434950 ('CCIP') : 0x005D8D50 PiccResFile proc near
- 0x44494C53 ('DILS') : 0x005DA0E0 SlidResFile proc near
- 0x20525543 (' RUC') : 0x005D9CA0 CurResFile proc near
- 0x20434950 (' CIP') : 0x005D8A10 PicResFile proc near
- 0x204F4452 (' ODR') : 0x005DA800 RdoResFile proc near
- 0x4E545442 ('NTTB') : 0x005DA470 BttnResFile proc near
- 0x4654504E ('FTPN') : 0x005D8630 NptfResFile proc near
- 0x4C474F54 ('LGOT') : 0x005DAB90 ToglResFile proc near
- 0x54584554 ('TXET') : 0x005D90B0 TextResFile proc near
Refer to other articles to understand each entry type.
Sunday, June 30, 2013
Desperados : Wanted Dead or Alive - Files Extension
All files extensions find inside game folder :
PS > Get-ChildItem -recurse F:\Game\Infogrames\Desperados\Game\* | Select-Object Extension | Sort-Object Extension | Get-Unique -asString
Extension
---------
.cfg
.cpg
.dat
.dll
.dvd
.dvf
.dvm
.exe
.fnt
.fxg
.log
.map
.pak
.res
.RES
.sbk
.scb
.stf
.sxt
.tmp
.wav
- .cfg
- .cpg
- .dat
- .dll
- .dvd
- .dvf
- .dvm
- .exe
- .fnt
- .fxg
- .log
- .map
- .pak
- .res / .RES
- .sbk
- .scb
- .stf
- .sxt
- .tmp
- .wav
Saturday, June 29, 2013
Desperados : Wanted Dead or Alive - Debug String
Inside the binary you can find "debug" strings, which are not related to the game Desperados...
If you know the game "Death Valley" or have more informations please leave a comment, thx.
If you know the game "Death Valley" or have more informations please leave a comment, thx.
C:\\Projets\\Death Valley\\DVArmsTrader.cpp
C:\\Projets\\Death Valley\\DVArmsTrader.cpp
C:\\Projets\\Death Valley\\DVArtificialBonhomie.cpp
C:\\Projets\\Death Valley\\DVArtificialBonhomie.cpp
C:\\Projets\\Death Valley\\DVArtificialIntelligence.cpp
C:\\Projets\\Death Valley\\DVArtificialIntelligence.cpp
C:\\Projets\\Death Valley\\DVArtificialMalignity.cpp
C:\\Projets\\Death Valley\\DVArtificialMalignity.cpp
C:\\Projets\\Death Valley\\DVBeacon.cpp
C:\\Projets\\Death Valley\\DVCampaign.cpp
C:\\Projets\\Death Valley\\DVCharacterProfile.cpp
C:\\Projets\\Death Valley\\DVCooper.cpp
C:\\Projets\\Death Valley\\DVCustomSaveGame.cpp
C:\\Projets\\Death Valley\\DVDialogue.cpp
C:\\Projets\\Death Valley\\DVDialogue.cpp
C:\\Projets\\Death Valley\\DVDoc.cpp
C:\\Projets\\Death Valley\\DVDrawManager.cpp
C:\\Projets\\Death Valley\\DVDynamicSaveGame.cpp
C:\\Projets\\Death Valley\\DVDynamicSaveGame.cpp
C:\\Projets\\Death Valley\\DVElement.cpp
C:\\Projets\\Death Valley\\DVElementActor.cpp
C:\\Projets\\Death Valley\\DVElementActorAnimal.cpp
C:\\Projets\\Death Valley\\DVElementActorAnimal.cpp
C:\\Projets\\Death Valley\\DVElementActorHorse.cpp
C:\\Projets\\Death Valley\\DVElementActorHorse.cpp
C:\\Projets\\Death Valley\\DVElementActorHuman.cpp
C:\\Projets\\Death Valley\\DVElementActorNPC.cpp
C:\\Projets\\Death Valley\\DVElementActorNPC.cpp
C:\\Projets\\Death Valley\\DVElementFX.cpp
C:\\Projets\\Death Valley\\DVElementMobile.cpp
C:\\Projets\\Death Valley\\DVElementObject.cpp
C:\\Projets\\Death Valley\\DVElementObject.cpp
C:\\Projets\\Death Valley\\DVElementProjectile.cpp
C:\\Projets\\Death Valley\\DVElementProjectile.cpp
C:\\Projets\\Death Valley\\DVElementTarget.cpp
C:\\Projets\\Death Valley\\DVEngine.cpp
C:\\Projets\\Death Valley\\DVEngine.cpp
C:\\Projets\\Death Valley\\DVFastFindGrid.cpp
C:\\Projets\\Death Valley\\DVFastFindGrid.cpp
C:\\Projets\\Death Valley\\DVFirearm.cpp
C:\\Projets\\Death Valley\\DVFrameHolder.cpp
C:\\Projets\\Death Valley\\DVGame.cpp
C:\\Projets\\Death Valley\\DVGraphicConfig.cpp
C:\\Projets\\Death Valley\\DVGroundMark.cpp
C:\\Projets\\Death Valley\\DVHikingGuide.cpp
C:\\Projets\\Death Valley\\DVJane.cpp
C:\\Projets\\Death Valley\\DVKeyConfig.cpp
C:\\Projets\\Death Valley\\DVKung.cpp
C:\\Projets\\Death Valley\\DVLine.cpp
C:\\Projets\\Death Valley\\DVLoadingScreen.cpp
C:\\Projets\\Death Valley\\DVMenu.cpp
C:\\Projets\\Death Valley\\DVMinimap.cpp
C:\\Projets\\Death Valley\\DVOrder.cpp
C:\\Projets\\Death Valley\\DVPatch.cpp
C:\\Projets\\Death Valley\\DVPath.cpp
C:\\Projets\\Death Valley\\DVPathFinder.cpp
C:\\Projets\\Death Valley\\DVPlayerProfileManager.cpp
C:\\Projets\\Death Valley\\DVPositionInterface.cpp
C:\\Projets\\Death Valley\\DVPowderMark.cpp
C:\\Projets\\Death Valley\\DVPowderMark.cpp
C:\\Projets\\Death Valley\\DVPsychoanalyst.cpp
C:\\Projets\\Death Valley\\DVPsychoanalyst.cpp
C:\\Projets\\Death Valley\\DVSanchez.cpp
C:\\Projets\\Death Valley\\DVSaveGameManager.cpp
C:\\Projets\\Death Valley\\DVScript.cpp
C:\\Projets\\Death Valley\\DVSector.cpp
C:\\Projets\\Death Valley\\DVSequence.cpp
C:\\Projets\\Death Valley\\DVSequenceElement.cpp
C:\\Projets\\Death Valley\\DVSequenceManager.cpp
C:\\Projets\\Death Valley\\DVSequenceManager.cpp
C:\\Projets\\Death Valley\\DVShadowPolygon.cpp
C:\\Projets\\Death Valley\\DVSound.cpp
C:\\Projets\\Death Valley\\DVSound.cpp
C:\\Projets\\Death Valley\\DVSoundCache.cpp
C:\\Projets\\Death Valley\\DVSoundCache.cpp
C:\\Projets\\Death Valley\\DVSoundCacheEntry.cpp
C:\\Projets\\Death Valley\\DVSoundConfig.cpp
C:\\Projets\\Death Valley\\DVSoundGeometry.cpp
C:\\Projets\\Death Valley\\DVSoundSource.cpp
C:\\Projets\\Death Valley\\DVSoundSourceClock.cpp
C:\\Projets\\Death Valley\\DVSoundSourceManager.cpp
C:\\Projets\\Death Valley\\DVSprite.cpp
C:\\Projets\\Death Valley\\DVTitBit.cpp
C:\\Projets\\Death Valley\\DVUIRendererAlphaConstantCustom.cpp
C:\\Projets\\Death Valley\\DVUIRendererCustom.cpp
C:\\Projets\\Death Valley\\DVWill.cpp
C:\\Projets\\Death Valley\\Launcher.cpp
C:\\Projets\\Death Valley\\SBFramePannelFX.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBDrawManager.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBEvent.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBFile.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBFont.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBGeoBoundingBox2D.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBGeoPoint2D.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBInput.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBPicture.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBResourceManager.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBThreadedInput.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBUIInputFieldText.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBUIRenderer.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBUIRendererInputField.cpp
C:\\Projets\\Death Valley\\SBLIBNG\\SBUIRendererListbox.cpp
C:\\Projets\\Death Valley\\SBLibNG/SBWidgetInputField.h
C:\\Projets\\Death Valley\\SBProfiler.cpp
C:\\Projets\\Death Valley\\dvelementactorpc.cpp
If you are bored of the MessageBox about the CD, nop this : .text:005B5215 push edi
.text:005B5216 call eax ; dword_693224
Friday, June 28, 2013
Desperados : Wanted Dead or Alive - Profiles file
This first blog post about the game "Desperados : Wanted Dead or Alive" will describe file format of saved game.
The main file can be found in the directory : "\Data\Savegame" under the name : "Profiles".
All this work was made with version 1.0 of the game.
Magic number must be equal to 0x50524F46 ('PROF').
Version in our case is 0x305 (773).
At offset 0x10 start the first profile entry.
The size of this class is 0xBC (188) :
Method for reading profile entry can be found at this address :
Method to read shortcut configuration :
Then come the number of saved games, and entry of each saved game.
The main file can be found in the directory : "\Data\Savegame" under the name : "Profiles".
All this work was made with version 1.0 of the game.
File format specification :
+0x00 : Magic Number
+0x04 : Version
+0x08 : Unknow_00
+0x0C : Number of profile's entry
+0x10 : Profiles entry
...
Magic number must be equal to 0x50524F46 ('PROF').
Version in our case is 0x305 (773).
At offset 0x10 start the first profile entry.
CProfile
The constructor of the class CProfile can be found at this address : 00548EF0 ; void *__thiscall ctor_CProfile(CProfile *this)
The size of this class is 0xBC (188) :
.text:0054A3BD push 0BCh
.text:0054A3C2 call ??2@YAPAXI@Z ; operator new
Method for reading profile entry can be found at this address :
005496D0 ; char __thiscall ReadProfile(CProfile *this, CFile *a2)
Profile entry specification :
+0x00 : Numero of directory entry
+0x04 : Current mission
+0x08 : Number of mission accomplished
+0x0C : Time elapsed
+0x10 : Shortcut config number 1
+0xXX : Shortcut config number 2
+0xXX : Sound configuration
+0xXX : Video configuration
+0xXX : Name of the player
+0xXX : Unknow_00
+0xXX : Number of saved games
+0xXX : Saved game entry
Method to read profile :
005496D0 ; char __thiscall ReadProfile(CProfile *this, CFile *a2)
Numero of directory entry
Numero of directory entry describe the number of the folder ("Profile_%d") associated with the profile, for example directory "Profile_01", saved game file associated with the profile are saved here.Shortcut config
Shortcut config is like a serialized class of type CShortcutConfig, the size of this member can change, there is 2 configuration for the shortcuts.Method to read shortcut configuration :
005105F0 ; char __thiscall ReadProfileShortcutConfig(CShortcutConf *this, CFile *a2)
Sound configuration
Sound configuration is a class of type CSoundConfig : 00000000 CSoundConf struc ; (sizeof=0xC)
00000000 field_0 dw ?
00000002 field_2 dw ?
00000004 field_4 dw ?
00000006 field_6 dw ?
00000008 field_8 dw ?
0000000A field_A db ?
0000000B field_B db ?
0000000C CSoundConf ends
Method to read sound configuration :00585D10 ; char __thiscall ReadProfileSoundConfig(CSoundConf *this, CFile *a2)
Video configuration is a class of type CVideoConfig :
00000000 CVideoConf struc ; (sizeof=0xC)
00000000 Animation db ?
00000001 Shadow db ?
00000002 Angle db ?
00000003 Effect db ?
00000004 CResolution CVideoReso ?
0000000C CVideoConf ends
0000000C
00000000 ; -----------------------------------
00000000
00000000 CVideoReso struc ; (sizeof=0x8)
00000000 reso_X dd ?
00000004 reso_Y dd ?
00000008 CVideoReso ends
Method to read video configuration :0050CBE0 ; char __thiscall ReadProfileVideoConfig(CVideoConf *this, CFile *a2)
Name of player
Name of player is stored under a structure : +0x00 : SizeName
+0x04 : wchar_t [SizeName]
Then come the number of saved games, and entry of each saved game.
CFile
And for those wondering about the class CFile :00000000 CFile struc ; (sizeof=0x58)
00000000 stream dd ? ; offset
00000004 mode_read dd ?
00000008 SizeFile dd ?
0000000C field_C dd ?
00000010 ArchiveVersion dd ?
00000014 error_status dd ?
00000018 field_18 CString ?
00000028 field_28 dd ?
0000002C field_2C dd ?
00000030 field_30 dd ?
00000034 field_34 dd ?
00000038 field_38 dd ?
0000003C field_3C dd ?
00000040 lpCreationTime _FILETIME ?
00000048 lpLastAccessTime _FILETIME ?
00000050 lpLastWriteTime _FILETIME ?
Subscribe to:
Posts (Atom)