Skip to content

Instantly share code, notes, and snippets.

@klecko
Created October 23, 2019 22:13
Show Gist options
  • Save klecko/ecadd39d406deba7640638e217d274f1 to your computer and use it in GitHub Desktop.
Save klecko/ecadd39d406deba7640638e217d274f1 to your computer and use it in GitHub Desktop.
/*
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