Consulta acerca de posición/distancia de funciones virtuales en una clase

Iniciado por BloodSharp, 16 Diciembre 2018, 02:14 AM

0 Miembros y 1 Visitante están viendo este tema.

BloodSharp

Buenos noches gente querida del foro, el tema es el siguiente:

Estuve aplicando ingeniería inversa a un programa con el fín de encontrar la ubicación de ciertas funciones virtuales de un objeto de una clase que hereda de por los menos como 4 clases que cada una hereda de una clase anterior, así llegando a la clase principal. Cada clase incluso contiene sus propias funciones virtuales y algunas "sobre-escritas", el tema es que no encuentro la manera de obtener un offset o distancia de dicha función virtual en la tabla de direcciones.

Hice un programa ejemplo que ilustra mi consulta:
Código (cpp) [Seleccionar]
#include <cstdio>

class CAbuelo
{
public:
virtual void Funcion1() {}
virtual void Funcion2() {}
virtual void Funcion3() {}
// ....
virtual void Funcion20() {}
virtual void Funcion21() {}
};

class CPadre : CAbuelo
{
public:
virtual void Funcion22() {}
virtual void Funcion23() {}
// ....
virtual void Funcion45() {}
virtual void Funcion46() {}
virtual void Funcion47() {}
};

class CNieto : CPadre
{
public:
virtual void Funcion48() {}
virtual void Funcion49() {}
virtual void Funcion50() {}
// ....
virtual void Funcion101() {}
virtual void Funcion102() {}
virtual void Funcion103() {}
};

CNieto objNieto;
CNieto *pNieto = &objNieto;

int main()
{
printf("direccion nieto en direccion 0x%X, funcion48 en direccion 0x%X y indice o distancia en %i",
pNieto, &((int)pNieto->Funcion48), indice_de_funcion_virtual_o_distancia(pNieto,Funcion48));
}


Mi consulta sería entonces como poder obtener una salida como la siguiente:
Citardireccion nieto en direccion 0xDEADBAFF, funcion48 en direccion 0xBAFFDEAD y indice o distancia en 48

Estuve buscando en google y lo más cercano fue esto, el problema es que crea una especie de "objeto" el cuál no se como obtiene la dirección base y cada resultado de salida es la dirección siguiente...

EDIT: Vale aclarar que el programa "objeto de estudio" fue compilado con alguna versión antigua de VC como la VC5 o VC6...


B#



MAFUS

Los métodos, internamente, no son miembros de las funciones.

En la memoria, código y datos están en segmentos separados, ya de por sí no pueden pertenecer al mismo objeto.

Después está la forma en que C++ nombra a los métodos. Las clases pueden compartir el mismo nombre en sus métodos y los propios métodos con los mismos nombres pero diferente firma hacen cosas diferentes. El compilador, a la hora de generar la tabla de símbolos y saber a qué método referirse, lo que hace es decorarlos. Partiendo de su nombre  le suma a éste datos de la firma e incluso puede añadir el nombre de la base.

Así se puede modificar un poco tu ejemplo anterior para que veas que, a pesar de que se generan tres objetos CNieto, cada uno con su propio espacio, su método Funcion48 son exactamente el mismo, es decir, sólo hay una copia de ellos en memoria. Lo que nos lleva a concluir que no son miembros propiamente dichos de la clase.

Código (cpp) [Seleccionar]
#include <cstdio>
#include <cstddef>

class CAbuelo
{
public:
virtual void Funcion1() {}
virtual void Funcion2() {}
virtual void Funcion3() {}
// ....
virtual void Funcion20() {}
virtual void Funcion21() {}
};

class CPadre : CAbuelo
{
public:
virtual void Funcion22() {}
virtual void Funcion23() {}
// ....
virtual void Funcion45() {}
virtual void Funcion46() {}
virtual void Funcion47() {}
};

class CNieto : CPadre
{
public:
virtual void Funcion48() {}
virtual void Funcion49() {}
virtual void Funcion50() {}
// ....
virtual void Funcion101() {}
virtual void Funcion102() {}
virtual void Funcion103() {}
};

CNieto objNieto1;
CNieto objNieto2;
CNieto objNieto3;

int main()
{
printf("objNieto1: 0x%p\nobjNieto1.Funcion48(): 0x%p\n",
&objNieto1, &objNieto1.Funcion48);
puts("");
printf("objNieto2: 0x%p\nobjNieto2.Funcion48(): 0x%p\n",
&objNieto2, &objNieto2.Funcion48);
puts("");
printf("objNieto3: 0x%p\nobjNieto3.Funcion48(): 0x%p\n",
&objNieto3, &(objNieto3.Funcion48));
}

BloodSharp

#2
Cita de: MAFUS en 16 Diciembre 2018, 17:20 PMLos métodos, internamente, no son miembros de las funciones.

En la memoria, código y datos están en segmentos separados, ya de por sí no pueden pertenecer al mismo objeto.

Después está la forma en que C++ nombra a los métodos. Las clases pueden compartir el mismo nombre en sus métodos y los propios métodos con los mismos nombres pero diferente firma hacen cosas diferentes. El compilador, a la hora de generar la tabla de símbolos y saber a qué método referirse, lo que hace es decorarlos. Partiendo de su nombre  le suma a éste datos de la firma e incluso puede añadir el nombre de la base.

Así se puede modificar un poco tu ejemplo anterior para que veas que, a pesar de que se generan tres objetos CNieto, cada uno con su propio espacio, su método Funcion48 son exactamente el mismo, es decir, sólo hay una copia de ellos en memoria. Lo que nos lleva a concluir que no son miembros propiamente dichos de la clase.

Gracias por tu respuesta, sin embargo mi consulta era como obtener la posición, distancia o índice en el vector del array de la tabla de direcciones de funciones virtuales... Como dije al principio del primer tema, estoy realizando ingeniería inversa a un programa el cuál encontré un "objeto interesante" al que analizarlo con IDA (en la versión de Linux del programa que tiene toda la data de DWARF) me arroja que hay una clase la cuál tiene funciones virtuales y que deriva de varias clases como mostré en el ejemplo.

El tema es que en Windows el desarrollador no dejó tan abiertamente los datos de depuración como en Linux, además estoy analizando una versión antigua de Windows, que si bién gracias a los datos de linux pude encontrar dichas funciones en Windows mayormente a través de referencias de strings...

Mi objetivo sería ver si las definiciones que yo extraje coinciden con las de Windows y ver posibles modificaciones a lo largo de las distintas versiones, por eso necesito los índices, para comprobar que no haya muchos cambios y además asegurarme que tengo todas las definiciones correctas.


B#