Created
October 23, 2019 22:13
-
-
Save klecko/ecadd39d406deba7640638e217d274f1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Ejemplo de uso de la librería detours para el hooking de funciones. | |
En este caso hookeamos la función sendto del módulo winsock de windows, que se encarga | |
de enviar un paquete en protocolo udp (es el que usa el target). | |
Para encontrar la función usaremos sigscanning, que nos permite buscar en memoria | |
un patrón de bytes generado por un plugin de OLLYDBG. | |
[EXPLICACIÓN DETOUR] | |
En esta imagen se ve muy bien: | |
http://www.malwaretech.com/wp-content/uploads/2015/01/CodeFlow.png | |
Consiste en sobreescribir las primeras instrucciones de una función por | |
un jmp a nuestro código (en este caso sendto_hook), de manera que cuando | |
el proceso llame a la función, lo primero que haga sea saltar a nuestra función. | |
Al haber sobreescrito las primeras instrucciones, debemos reescribirlas en otro | |
lugar, seguidas de un jmp al resto de la función. Esto se llama trampoline. | |
Ahí es donde empezará la función original. El cliente llamará a su función | |
que saltará a la nuestra, donde ejecutaremos nuestro código, y finalmente | |
llamaremos a la función original (en el trampoline). | |
Todo esto lo hace la librería detours de manera automática. | |
*/ | |
#include <Windows.h> | |
#include <iostream> | |
#include <vector> | |
#include <string> | |
#include "detours.h" | |
#include "sigscan.h" | |
#pragma comment(lib, "detours.lib") | |
using namespace std; | |
FILE* pCout; | |
FILE* pCin; | |
typedef int (WINAPI *sendto_t)(SOCKET s, const char *buf, int len, int flags, const sockaddr *to, int tolen); | |
sendto_t original_sendto; | |
int WINAPI sendto_hook(SOCKET s, const char *buf, int len, int flags, const sockaddr *to, int tolen) { | |
// Hook de la función sendto. Es la dirección a la que salta el primer jmp de sendto. | |
cout << "Sending packet: " << buf << endl; | |
// Llamo a original_sendto, que comienza en el trampoline, donde están las instrucciones | |
// que había sobreescrito el jump. | |
return original_sendto(s, buf, len, flags, to, tolen); | |
} | |
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { | |
if (dwReason == DLL_PROCESS_ATTACH) { | |
//Consola | |
AllocConsole(); | |
freopen_s(&pCout, "CONOUT$", "w", stdout); | |
freopen_s(&pCin, "CONIN$", "r", stdin); | |
//Busqueda de funciones | |
SigScan scanner; | |
void* sendto_addr = (void*)scanner.FindPattern("WS2_32.dll", "\x8B\xFF\x55\x8B\xEC\x83\xEC\x14\x53\x56\x8B\x35\x00\x00\x00\x00\x33\xDB\x57\xBF\x00\x00\x00\x00\x3B\xF7\x0F\x85\x00\x00\x00\x00\x39\x1D\x00\x00\x00\x00\x74\x1E\xFF\x35\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00\x89\x45\xF8", "xxxxxxxxxxxx????xxxx????xxxx????xx????xxxx????xx????xxx"); | |
cout << hex << "Found sendto function at " << (DWORD)sendto_addr << endl; | |
/* En este momento sendto_addr tiene la dirección de la función sendto, | |
encontrada por el sigscan. Esta dirección se la pasaremos a la librería | |
detours por referencia, de manera que haga lo de poner un jmp, crear el | |
trampoline, y escribir la dirección de este en sendto_addr. | |
*/ | |
//Detours | |
DetourTransactionBegin(); | |
DetourUpdateThread(GetCurrentThread()); | |
DetourAttach(&sendto_addr, sendto_hook); //establece sendto_addr a la dirección del trampoline | |
DetourTransactionCommit(); | |
/* | |
Ahora la función sendto original comienza en otra dirección, en el trampoline. | |
Pero el proceso seguirá llamando a la dirección anterior, que ahora tiene un jump | |
a nuestro código. De esta manera tenemos el hook y además podemos llamar a la función original. | |
*/ | |
cout << "Detour commited! Now sendto function is at " << (DWORD)sendto_addr << endl; | |
/* | |
Guardo sendto_addr (dirección del trampoline) como original_sendto, declarado como | |
puntero a función con la misma cabecera que sendto (tipo sendto_t) | |
Ahora original_sendto es una función con los mismos argumentos que sendto, cuyo inicio | |
es en el trampoline. | |
*/ | |
original_sendto = (sendto_t)sendto_addr; | |
} | |
else if (dwReason == DLL_PROCESS_DETACH) { | |
cout << "bye!" << endl; | |
fclose(pCout); | |
fclose(pCin); | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment