Lo primero que se debe hacer es definir que se quiere obtener (esto puede ser una variable o función de dicho módulo del cual no se tengan referencias para llegar), para hacerlo se puede hacer uso de ingeniería inversa (o sea, desensamblar el módulo).
Veamos un ejemplo (en nuestro propio módulo con el fin de visualizarlo): creamos un simple programa con una sola función:
Código
#include <windows.h> char titulo[]="titulo"; char mensaje[]="un mensaje"; void funcionascanear(void){ MessageBox(0,mensaje,titulo,0); } int main(void){ funcionascanear(); return 0; }
abrimos nuestro programa con ollydbg y buscamos nuestra función:
Código
004012D0 /$ 55 PUSH EBP 004012D1 |. 89E5 MOV EBP, ESP 004012D3 |. 83EC 18 SUB ESP, 18 004012D6 |. C74424 0C 00000000 MOV DWORD PTR SS:[ESP+C], 0 ; | 004012DE |. C74424 08 00204000 MOV DWORD PTR SS:[ESP+8], generico.0>; |ASCII "titulo" 004012E6 |. C74424 04 07204000 MOV DWORD PTR SS:[ESP+4], generico.0>; |ASCII "un mensaje" 004012EE |. C70424 00000000 MOV DWORD PTR SS:[ESP], 0 ; | 004012F5 |. E8 86080000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA 004012FA |. 83EC 10 SUB ESP, 10 004012FD |. C9 LEAVE 004012FE \. C3 RETN
en base a este código ASM crearemos un "patron" que nos lleve a dicha función (nuestro objetivo en este caso será modificar el mensaje)
Citar
55 PUSH EBP
89E5 MOV EBP, ESP
83EC 18 SUB ESP, 18
C74424 0C 00000000 MOV DWORD PTR SS:[ESP+C], 0 ; |
C74424 08 00204000 MOV DWORD PTR SS:[ESP+8], generico.0>; |ASCII "titulo"
C74424 04 07204000 MOV DWORD PTR SS:[ESP+4], generico.0>; |ASCII "un mensaje"
C70424 00000000 MOV DWORD PTR SS:[ESP], 0 ; |
E8 86080000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
83EC 10 SUB ESP, 10
C9 LEAVE
C3 RETN
89E5 MOV EBP, ESP
83EC 18 SUB ESP, 18
C74424 0C 00000000 MOV DWORD PTR SS:[ESP+C], 0 ; |
C74424 08 00204000 MOV DWORD PTR SS:[ESP+8], generico.0>; |ASCII "titulo"
C74424 04 07204000 MOV DWORD PTR SS:[ESP+4], generico.0>; |ASCII "un mensaje"
C70424 00000000 MOV DWORD PTR SS:[ESP], 0 ; |
E8 86080000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
83EC 10 SUB ESP, 10
C9 LEAVE
C3 RETN
lo que está en rojo será nuestro patrón (se lo puede complicar más, y es preferible, pero para nuestro ejemplo servirá), por lo tanto generamos una función que lo detecte:
Código
char *findmsgbypattern(){ unsigned char *p; //dirección inicio / fin del escaneo for(p=0x00401000;p<0x00401FFF;p++){ //nuestro patron if(p[0]==0x55&&p[1]==0x89&&p[3]==0x83&&p[6]==0xC7&&p[14]==0xC7&&p[22]==0xC7){ //dirección de la variable tomada del código return (char *)*(void**)&p[26]; } } return NULL; }
Un detalle a destacar de la función es que &p[26] nos devolverá la dirección de memoria de la instrucción, pero no de la variable, entonces mediante el *(void**) obtendremos la verdadera dirección.
Ahora ya podemos escanear nuestro código, y en caso de encontrar nuestra variable modificarla:
Código
#include <windows.h> char titulo[]="titulo"; char mensaje[]="un mensaje"; void funcionascanear(void){ MessageBox(0,mensaje,titulo,0); } char *findmsgbypattern(){ unsigned char *p; //dirección inicio / fin del escaneo for(p=0x00401000;p<0x00401FFF;p++){ //nuestro patron if(p[0]==0x55&&p[1]==0x89&&p[3]==0x83&&p[6]==0xC7&&p[14]==0xC7&&p[22]==0xC7){ //dirección de la variable tomada del código return (char *)*(void**)&p[26]; } } return NULL; } int main(void){ char *msg=findmsgbypattern(); if(msg) funcionascanear(); return 0; }
Solo cabe aclarar que en el caso de modificar un string la variable original debe ser de un tamaño adecuado para nuestra modificación.
S2
PD: El ejemplo fue compilado con Mingw (GCC), es casi seguro que no funcione en otros compiladores (VC, etc), para hacerlo funcionar hay que rearmar el patrón.
PD2: Existen librerías que permiten buscar patrones de forma más sencilla, como por ejemplo (formato olly):
Código
findpattern(dirinicio,dirfin,"XX????XX??????XX????XX");
pero lo que hacen al fin y al cabo es lo mismo.