PDA

Ver la versión completa : Alguien tiene experiencia descompilando C++?



IronArthur
25/06/2015, 15:58
Ultimamente ando en modo ingenieria inversa con un juego relativamente viejo, Mechcommander. Por ahora voy relativamente bien sacando el contenido del juego pero me he pegado con un pared con un par de aspectos del juego.

Y por ver si saco algo en claro, me ha dado por intentar descompilar el ejecutable. Evidentemente no intento sacar todo el codigo fuente, ni volver a recompilarlo ni nada, solo intento saber como lee varios ficheros del juego.

Por ahora estoy probando con el IDA + Hex-rays decompiler y el plugin HexRaysCodeXplorer.

La verdad es q yo y el c++ no nos llevamos demasiado bien, pero es q ando perdidisimo.

Por poner un ejemplo:

int __thiscall Palette::loadPalette(Palette *this, struct FitIniFile *a2)
{
Palette *v2; // esi@1
int result; // eax@1
int v4; // edi@2
unsigned __int32 v5; // eax@4
DWORD v6; // edi@4
unsigned __int8 *v7; // eax@4
unsigned __int8 *v8; // ebx@4
UserHeap *v9; // ecx@6
void *v10; // eax@6
char v11; // [sp+Ch] [bp-4Ch]@2

v2 = this;
result = FitIniFile::readIdString(a2, `string', (char *)this + 64, 8u);
if ( !result )
{
a2 = 0;
FullPathFileName::init((FullPathFileName *)&a2, &palettePath, (char *)v2 + 64, `string');
File::File((File *)&v11);
v4 = File::open(&v11, a2, 1, 50);
if ( v4 )
{
File::~File((File *)&v11);
FullPathFileName::~FullPathFileName((FullPathFileN ame *)&a2);
result = v4;
}
else
{
v5 = File::fileSize((File *)&v11);
v6 = v5;
v7 = (unsigned __int8 *)UserHeap::malloc(systemHeap, v5);
v8 = v7;
*((_DWORD *)v2 + 28) = v7;
if ( v7 )
{
File::read((File *)&v11, v7, v6);
PaletteBlock::initRgbData(v2, v8);
v9 = systemHeap;
*((_DWORD *)v2 + 7) = 0;
*((_DWORD *)v2 + 8) = -1;
*((_BYTE *)v2 + 38) = 0;
*((_BYTE *)v2 + 37) = 0;
*((_BYTE *)v2 + 36) = 0;
*((_DWORD *)v2 + 2) = v6;
v10 = UserHeap::malloc(v9, v6);
*((_DWORD *)v2 + 4) = v10;
if ( v10 )
{
File::close((File *)&v11);
File::~File((File *)&v11);
FullPathFileName::~FullPathFileName((FullPathFileN ame *)&a2);
result = 0;
}
else
{
File::~File((File *)&v11);
FullPathFileName::~FullPathFileName((FullPathFileN ame *)&a2);
result = -1411776510;
}
}
else
{
File::~File((File *)&v11);
FullPathFileName::~FullPathFileName((FullPathFileN ame *)&a2);
result = -1411776511;
}
}
}
return result;
}


Tengo un problema importante, no encuentro strings de rutas por el codigo q me ayudaria bastante y realmente no entiendo que significa hacer

*((_DWORD *)v2 + 8) = -1;

Alguna pista, tutorial o plugin que me ayude en algo??

salu2

swapd0
25/06/2015, 16:30
v2 tiene una dirección de memoria, lo convierte a un puntero a entero de 32bits, le suma 8 y lo pone a -1.

seria como hacer.
*ptrv2 = -1;
teniendo ptrv2 apuntando a la dirección que tiene la variable v2, no a la variable v2. Si v2 = 1000, ptrv2 apunta a la dirección 1000...

-----Actualizado-----

Lo de descompilar para portar a otra plataforma vale, pero el código que sale es una kk. No es lo mismo que cuando desensamblas un juego que sabes que esta hecho en ensamblador.

pakoito
25/06/2015, 16:35
Los compiladores de C++ son más que compiladores, generan mucho código, optimizan las líneas moviéndolas de sitio y añadiendo truquis, sustituyen valores por direcciones de memoria, adaptan cosas especificas de la plataforma de destino y al final lo que escupen se parece al origen de casualidad.

Descompilar C++ para buscar un bug todavía cuela, pero intentar deducir el código o funcionalidad original es un arte al alcance de unos pocos :(

Nada que ver con C# o Java, que los pasas por las herramientas y te lo escupen todo casi como en el original :D

swapd0
25/06/2015, 16:39
Mirando el codigo v2 apunta a un objeto de tipo Palette y en vez de llamar a sus métodos se pone a modificar la memoria directamente, así es complicado sacar algo en claro.

neglox
25/06/2015, 18:42
Como ya te han dicho decompilar C++ es una locura. Son horas y horas de pegarse con el código y llegar a tener pesadillas con él. En concreto la línea de código que comentas está modificando la octava palabra referenciada por v2. Una palabra son 32 bits como ya han comentado.

Si lo que quieres son rutas de ficheros a los que se accede te recomiendo un enfoque diferente.
1.Por una parte usar Process Monitor (Mark Russinovich) para ver un poco el flujo de ficheros que se abren por la aplicación.
2.Hacer hooking a los métodos que parecen tener llamadas con nombres de ficheros para guardar esos datos en un log. https://en.wikipedia.org/wiki/Hooking . Básicamente es interceptar llamadas a métodos de una aplicación para hacer tu lo que te interese (en este caso leer los parámetros donde viene el nombre del fichero) y luego llamar al método original para que la aplicación siga funcionando correctamente. Aviso: no es fácil.

Jurk
25/06/2015, 19:07
Parece un rutina de cargar un fichero con un nombre deternimado, y si no esta, de crear otro. Las rutas: al ser objetos, sus init o contructores seguronque se encargan de pedir al SO la carpeta en la que estan, o en vez de una ruta absoluta seran rutas relativas.Siendo todo el rollo relacionado con las paletas, seguro que la ruta es la de las imagenes y animaciones del juego, o una subcarpeta de esta

IronArthur
26/06/2015, 15:16
Lo primero gracias a todos por la ayuda.
Jurk: El juego tiene varios PAKs donde almacena los datos, pero en la mayor parte de los casos siempre intenta buscar si estan descomprimidos y si no lo encuentra lo busca comprimido.

neglox : El process manager es una maravilla, creo que me va a ayudar mucho porque indica cuantos bytes lee y con que offset, lo que me puede dar muchas pistas de como estan organizados ciertos formatos de ficheros que todavia no entiendo, principalmente los mapas.
http://i.imgur.com/ZqSmbOZ.jpg

Sobre el dichoso objeto V2 que puse de ejemplo, otro plugin del Hex-rays, snowman muestra el codigo algo diferente y genera structs mas descriptivos. vamos que el dicho objeto es un struct, y lo q se hace con el v2+8 al final es acceder a uno de los campos:


struct s0 {
signed char[8] pad8;
int32_t f8;
signed char[4] pad16;
int32_t f16;
signed char[8] pad28;
int32_t f28;
int32_t f32;
signed char f36;
signed char f37;
signed char f38;
signed char[73] pad112;
int32_t f112;
};

Como comprendereis mi mayor problema no son las paletas de colores pq es algo trivial, este LoadPalette era un ejemplo de algo pequeño, de hecho ya muestro la mayor parte de los sprites del juego sin problemas. Lo q todavia no entiendo es como genera los PaintSchemes pq no se donde los guarda, supongo que sera unas FadeTables que creo que con un poco de esfuerzo las puedo sacar pero ni idea como las "pinta"
http://i.imgur.com/f99X1Pt.png

Mi mayor problema con mucho es tema de memoria y almacenaje de los sprites. ALUCINO como gestionan de bien en un juego de Pentium 166Mhz, 3k-12k sprites por unidad del juego y yo con un ordenador 8GB de ram tengo out of memorys por todos los lados.


Luego tengo enigmas de determinadas cosas concretas, por poner un ejemplo por si alguien se aburre. Tenemos un edificio que tiene 2 capas, el edificio en si y la capa inferior que hace de sombra.



[Main Info]
st Name="barnD_a1"
ul NumFrames=16

[Bounds]
l UpperLeftX=-50.0
l UpperLeftY=-60.0
l LowerRightX=50.0
l LowerRightY=20.0

FITend


1a: Tamaño: 321 x 241 Pivote:160 x 120
http://i.imgur.com/p0FbarK.png

2a: Tamaño: 241 x 181 Pivote: 120 36
http://i.imgur.com/2sddTCg.png

A ver si alguien es capaz de sacar la correspondencia de como poner uno encima del otro, pq yo llevo un par de semanas y no lo veo. El archivo aproximadamente encaja en la pos 26,31, pero ni idea como sacarlo con los datos que tengo

http://i.imgur.com/T8ljDWl.png

Ya siento el ladrillo!!!

Salu2

swapd0
26/06/2015, 19:02
Que datos tienes, ¿solo el tamaño de cada sprite y el pivote? según parece el pivote siempre esta en el centro, siendo así es de poco utilidad.

IronArthur
27/06/2015, 11:14
Tengo el tamaño del sprite y el pivote que sirve para construirlo que se utiliza del punto 0,0. Por eso hay referencias negativas.
Mi suposición es que será un cálculo con el campo de Bounds que está en el fichero descriptor que he pegado.

Por cierto el pivote la sombra no esta centrado en el eje y, ésta en el 36 de 181 que tiene de alto.

Salu2