Professional Documents
Culture Documents
Bueno hago este tutorial con el fin de que los interesados en el hacking mediante
inyeccin de DLL tengan una base de donde partir.
Vamos a aprender a hacer DLLs, C++ y un poco de Assembler bsico.
Para esta ocasin en especial, ya que es la primera vez de casi todos los lectores, hice
una aplicacin muy simple en C++ (FuncionOutput.exe) la cual tan solo posee una
funcin de output (muestra texto en pantalla). Si todo va bien, a medida que terminen el
tutorial sabrn por lo menos identificar una funcin simple en cdigo assembler y saber
qu parametros lleva y cmo identificarlos.
IMPORTANTE : La creacin de la DLL se llevar a cabo en Visual C++ 6.0.
Tericamente hacindolo en Dev C++ o Visual C++ 2005 tendra que funcionar de todas
maneras.
IMPORTANTE : Algunas de las direcciones de memorias vistas en este tutorial
pueden ser distintas a las que vea el lector.
IMPORTANTE : Si encuentran algn error de definicin o cualquier tipo de error en
este tutorial posteenlo. De esta forma aprendemos todos.
Conocimientos previos
Necesitas saber :
*Qu son las direcciones de memoria.
*Qu son las instrucciones (programacin - cualquiera que sepa programar sabe esto).
*Qu es un depurador y qu hace.
*Tener por lo menos una base de C o C++.
*Saber qu es una DLL (Librera Dinmica).
*Saber manejar bien el entorno de Windows (ya que el entorno de los deuradores no es
sencillo).
Si necesitas cualquier informacin acerca de las cosas mencionadas recomiendo usar
wikipedia (Excepto por C++. Si no tens una minima idea de C++ no vas a entender
nada).
Software necesario
FuncionOutput.exe : Esta es la aplicacin que vamos analizar. Se tratar de usar una
funcin de la misma sin saber su cdigo fuente (Impresionante no?)
OllyDbg 1.10 : El depurador que usaremos.
InjecTOR : Inyecta la DLL en cualquier aplicacin. Usaremos este programa para
inyectar nuestra DLL (la que crearemos) en FuncionOutput.exe
Comenzando
1) Para comenzar ejecutemos FuncionOutput.
Zona roja : Ac estan las instrucciones con sus respectivas direcciones de memoria.
Zona verde : Ac estan los registros. Qu son los registros?
(EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI) Para ponerlo fcil, vamos a decir que son
parecidos a las variables. Algunos de ellos tienen funciones especficas, como en el caso
de ESP (el cual veremos mas adelante en este tutorial). Las funciones de los otros
registros las iremos viendo en prximos tutoriales. Vamos a poner un ejemplo.
MOV EAX,ECX
MOV EAX, 4
Qu significa MOV?
La instruccin MOV copia.
Importante : Si hago MOV EAX,4 el contenido anterior de EAX no se conserva, se
reemplaza.
Zona azul : Se le denomina DUMP. Se ve el contenido de las direcciones de memoria
(en bytes).
Zona amarilla : Se le denomina STACK (en espaol PILA). Se usa en conjunto con las
instrucciones PUSH y cuando se hace un CALL.
Por ejemplo, para pasar un parmetro a una funcin se utiliza PUSH.
Cuando hago un PUSH de algo, este algo se guarda en el STACK (pila) para luego ser
usado.
Veamos un ejemplo para llamar a una funcin de suma con dos parmetros.
PUSH 5
PUSH 8
CALL 00401050
Equivalente en C++ : Suma(5,8)
Es decir, estoy sumando 5+8.
La suma se podr efectuar gracias a los dos PUSH que hicimos.
Cuando se hace un CALL el procesador guarda la direccin de retorno en el STACK
(automticamente). Es decir, cuando se termine de efectuar la funcin (cuando
encuentre RETN, lo cual significa RETURN) sabr volver a donde estaba gracias al
STACK. Por supuesto, al volver BORRA del stack la direccin de retorno
porque,obviamente, ya volvi y dejarla ah producira un error en el programa. (Es muy
importante controlar el STACK).
Como se darn cuenta en vez de utilizar un nombre luego de CALL utilizamos una cifra
hexadecimal.
00401050 es la direccin hexadecimal de la funcin.
HotKeys (teclas de acceso rpido)
F7 = Avanza de instruccin, y si encuentra un CALL se mete dentro del CALL tambin.
F8 = Avanza de instruccin, y si encuentra un CALL NO se mete.
F9 = Corre el progama.
3 ) Encontrando la direccin de la funcin en FuncionOutput.exe!
Sabemos que ese es un parmetro. Para ver dnde fue utilizada en el cdigo (en las
instrucciones, zona roja) le hacemos doble click, y aparecer lo siguiente :
Arriba del PUSH de la cadena de texto hay un CALL, no es un PUSH por lo tanto
podemos estar casi seguros que la funcin tiene solo un parmetro. El texto.
Entonces estamos seguros.
La funcin CALL tiene un parmetro. La direccin de memoria de la funcin a la que se
llama.
Entonces por lgica esta es la llamada completa a la funcin :
Cdigo:
00401071
> 68 A0D04000
PUSH FuncionO.0040D0A0
; ASCII "Este texto es generado con una funcion, intenten
utilizarla!"
00401076
. E8 05000000
CALL FuncionO.00401080
. 83C4 04
ADD ESP,4
La Linea 1 : Hacemos push (introducimos) el texto en el stack, para que luego pueda ser
usado por la funcin.
La Linea 2 : Llamamos a la funcin (Al llamarla en el stack aparecer una nueva linea
"Return to 0040107B", ya que al finalizar la funcin debe volver a la siguiente
instruccin. Cuando vuelva, "Return to 0040107B" desaparecer del STACK(ya que ya
volvi).
La Linea 3 : Nuestra cadena sigue en la Pila, y ya le pasamos el parmetro a la funcin,
e incluso la funcin ya se ejecut. Por lo tanto hace falta borrarla. Como ya sabemos
ESP apunta a la ltima direccin del dato introducido en el STACK. Al agregarle 4 a
ESP (Con la instruccin ADD) ya no apuntar a nuestra cadena de texto, que es lo que
buscamos.
En resumen, pasamos los parmetros, llamamos a la funcin, y borramos el parmetro
ya usado.
Ya podemos cerrar OllyDbg (En prximos tutoriales aprenderemos mas sobre este
depurador).
Tenemos los siguientes datos :
Direccin de la funcin : 00401080
Parmetros : Texto, por lo tanto char*
4) Creando nuestra DLL
Como dije anteriormente voy a asumir que los lectores ya tienen conocimiento previo
bsico de C/C++.
#include <windows.h>
void main()
{
inyectada.
}
//DllMain - No voy a entrar en detalles. Si el proceso es Attach (Si
fue inyectada)
//Crea un Thread (main)
bool APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID
lpvReserved){
if(dwReason == DLL_PROCESS_ATTACH){
DisableThreadLibraryCalls(hModule);
CreateThread(NULL, 0, (unsigned long(__stdcall*)
(void*))main, NULL, 0, NULL);
}
return true;
}
Bueno, antes de codear lo que queremos que haga, voy a explicar dos instrucciones de
Assembler que utilizaremos (que no vimos anteriormente) :
PUSHAD : Guardan el contenido de los registros en el stack (digamos para hacer un
backup de los registros).
POPAD : Carga el contenido de los registros desde el stack (para cargar el backup).
Son ideales si no se quiere intervenir con la memoria del progama al utilizar sus
funciones.
Tenemos tres datos :
Direccin de la funcin : 00401080
Parmetros : Texto, por lo tanto char*
Datos Extra : Limpiar el STACK sumndole 4 a ESP.
Para definir la funcin le voy a pone de nombre ZOutput, ustedes le pueden poner lo
que quieran.
Para corroborar que funciona sin problemas, voy a hacer que diga "Hola" infinitamente
con intervalos de 1000ms.
Cdigo :
Cdigo:
#include <windows.h>
#define ZOutput 0x00401080
void main()
{
char* t = "Hola";
while(1)
{
//Para utilizar assembler en c++ ponemos __asm
__asm
{
pushad //guardamos los valores de los registros
para no intervenir con el progama
push t//ponemos t en el stack
mov eax, ZOutput//Muevo la direccion de la
funcion a eax
call eax//Llamo a eax (llamo a la funcion)
add esp,4//Limpio el Stack modificando la
ultima direccion introducida
popad//reestablecemos los registros
}
Sleep(1000);
}
}
//DllMain - No voy a entrar en detalles. Si el proceso es Attach (Si
fue inyectada)
//Crea un Thread (main)
bool APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID
lpvReserved){
if(dwReason == DLL_PROCESS_ATTACH){
DisableThreadLibraryCalls(hModule);
CreateThread(NULL, 0, (unsigned long(__stdcall*)(void*))main, NULL, 0,
NULL);
}
return true;
}
Compilamos la DLL.
(En VC++ 6.0 van a Build -- Batch Build y seleccionan Release, luego aprietan Build.)
5) Probando nuestro hack
Cierren todo lo que usamos.
Los compiladores, OllyDbg(si lo tenian abierto).
Abrimos FuncionOutput.
Ahora abrimos InjecTOR (para inyectar nuestra DLL en el proceso FuncionOutput.exe)
Seleccionamos Load Dll y seleccionamos la DLL recien compilada.
Al lado en processes buscamos FuncionOutput.exe y apretamos Inject Dll.
Si todo va bien, deberamos ver :