Sie sind auf Seite 1von 9

Existem diferentes formas de realizar tal tcnica, como por exemplo substituir a chamada a uma determinada funo p instruo

JMP contendo um endereo especfico para onde o programa ir saltar. No entanto, vou mostrar uma das mane mais simples e eficientes de implementao: IAT (Import Address Table) Patching.

Antes de mostrar o exemplo, gostaria de esclarecer algumas coisas. Basicamente, API Hooking uma tcnica que cons em interceptar as chamadas API do sistema feitas por um determinado aplicativo. O hooking de API muito usado programas que filtram as funes CreateProcess(), CreateFile() e DeleteFile() por exemplo.

Se voc j escreveu algum programa para Windows, seja ele em C, C++, Delphi, Visual Basic e at mesmo Assembly deve ter utilizado funes como MessageBox, Sleep, FindWindow, CopyFile, dentre outras. Essas funes fazem parte API do Windows e esto presentes em DLLs (kernel32.dll, user32.dll). Quando voc usa uma funo da API, o endereo mesma importado da DLL e armazenado na tabela de endereos de importao (IAT) do executvel. Aps execut-lo sistema ir carreg-lo na memria justamente com as DLL's nas quais esto as funes so importadas por ele. Ne processo, os endereos das funes importadas so obtidos e escritos na tabela para que o aplicativo possa cham-las.

A essncia do IAT Hooking est justamente neste aspecto. Modificando o endereo associado a cada funo importada p um endereo de uma funo definida por ns, podemos fazer com que o programa sempre chame por nossa funo em vez funo original importada.

Ento, declaramos uma funo com o mesmo prottipo e escrevemos seu endereo no lugar do endereo da funo origi Assim, podemos interceptar as chamadas, filtr-las e, opcionalmente, passar os parmetros interceptados funo legtima

Contudo, as funes que iremos declarar para monitorar as chamadas API devem estar no mesmo espao de memria aplicativo alvo para que este ltimo possa acess-las. Por isso, iremos injetar uma DLL no processo contendo uma fun que ser executada imediatamente aps a injeo para realizar o Hook. Contendo, tambm, as nossas funes monitorao.

Bem, isso foi apenas uma pequena introduo sobre API Hooking, sobretudo, IAT Hooking. Antes de visualizar o cdi sugiro que voc procure mais informaes a respeito. Vejamos ento o cdigo de exemplo: DLL.h

#define EXPORT __declspec(dllexport) #define NO_IMPORT_DESCRIPTOR -2 #define MODULE_NOT_FOUND -1

#define FUNCTION_NOT_FOUND #define REPLACE_SUCCESS typedef struct FuncList {

0 1

LPCSTR lpszModuleName; LPCSTR lpszFunctionName; LPVOID lpNewAddress; }* PFUNCLIST; EXPORT int HookFunctions(); EXPORT int ReplaceIATEntries(PFUNCLIST, HMODULE, LPDWORD);

DLL.c
#include #include #include #include #include #include "string.h" "windows.h" "tlhelp32.h" "imagehlp.h" "dll.h" "HookFunctions.h"

#pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"imagehlp.lib") static HINSTANCE hApiHookDLL = 0; struct FuncList Functions[] = { {"kernel32.dll","LoadLibraryA",LoadLibraryAHooked}, {"wsock32.dll","recv",RecvHooked}, {"wsock32.dll","send",SendHooked}, {"ws2_32.dll","recv",RecvHooked}, {"ws2_32.dll","send",SendHooked} }; BOOL APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: hApiHookDLL = hInstance; switch(HookFunctions()) { case -1: MessageBox(0,"Erro ao monitorar as funes especificadas.","Erro",0x10); FreeLibrary(hInstance); break; case 0: MessageBox(0,"Uma ou mais funes no puderam ser monitoradas.","Aviso",0x30);

break; case 1: MessageBox(0,"As funes especificadas esto sendo monitoradas.","OK",0x40); break; } break; case DLL_PROCESS_DETACH: FreeLibrary(hInstance); break; } return TRUE; } ///////////////////////////////////////////////////////////////////////////////////// EXPORT int HookFunctions() { DWORD dwPID, dwHooked, dwNumOfFunctions, dwMatches, i; HANDLE hSnapShot; MODULEENTRY32 mModuleEntry; PFUNCLIST pFuncList; dwPID = GetCurrentProcessId(); hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); if(hSnapShot == INVALID_HANDLE_VALUE) return -1; mModuleEntry.dwSize = sizeof(MODULEENTRY32); if(!Module32First(hSnapShot, &mModuleEntry)) return -1; dwNumOfFunctions = sizeof(Functions) / sizeof(struct FuncList); dwHooked = dwMatches = 0; do { if(mModuleEntry.hModule != hApiHookDLL) { for(pFuncList = Functions, i = 0; i < dwNumOfFunctions; { pFuncList++, i++)

if(ReplaceIATEntries(pFuncList, mModuleEntry.hModule, &dwMatches) == REPLACE_SUCCESS) dwHooked++; } } }while(Module32Next(hSnapShot,&mModuleEntry)); CloseHandle(hSnapShot);

if(!dwMatches) return -1; if(dwHooked == dwMatches) return 1; else return 0; } ///////////////////////////////////////////////////////////////////////////////////// EXPORT int ReplaceIATEntries(PFUNCLIST pFuncList, HMODULE hModuleBase, LPDWORD lpMatches) { LPCSTR DWORD HANDLE lpszModuleName; dwSize, dwOld; hProcess;

PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pThunk; PROC * pfnFunc, pfnTarget; hProcess = GetCurrentProcess(); pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(hModuleBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &dwSize); if(!pImportDesc) return NO_IMPORT_DESCRIPTOR; while(pImportDesc->Name) { lpszModuleName = (LPSTR)((LPBYTE)hModuleBase + pImportDesc->Name); if(!_strcmpi(lpszModuleName, pFuncList->lpszModuleName)) break; pImportDesc++; } if(!pImportDesc->Name) return MODULE_NOT_FOUND; pThunk = (PIMAGE_THUNK_DATA)((LPBYTE) hModuleBase + pImportDesc->FirstThunk); while(pThunk->u1.Function) { pfnFunc = (PROC*)&pThunk->u1.Function; pfnTarget = GetProcAddress(GetModuleHandle(pFuncList->lpszModuleName), pFuncList->lpszFunctionName); if(pfnFunc && pfnTarget && *pfnFunc == pfnTarget) { if(lpMatches) (*lpMatches)++; if(VirtualProtect(pfnFunc, sizeof(pfnFunc), PAGE_EXECUTE_READWRITE, &dwOld) && (WriteProcessMemory(hProcess, pfnFunc, &pFuncList->lpNewAddress, sizeof(LPVOID), { return REPLACE_SUCCESS;

NULL)))

pThunk++; } return FUNCTION_NOT_FOUND; } /////////////////////////////////////////////////////////////////////////////////////

HookFunctions.h
HINSTANCE WINAPI LoadLibraryAHooked(LPCSTR); int WINAPI SendHooked(SOCKET, const char *, int, int); int WINAPI RecvHooked(SOCKET, char *, int, int);

HookFunctions.c
#include #include #include #include #include "stdio.h" "string.h" "windows.h" "HookFunctions.h" "DLL.h"

/////////////////////////////////////////////////////////////////////////////// HINSTANCE WINAPI LoadLibraryAHooked(LPCSTR lpszModuleName) { HINSTANCE hModule = LoadLibraryA(lpszModuleName); if(!hModule) return NULL; HookFunctions(); } return hModule;

/////////////////////////////////////////////////////////////////////////////// int WINAPI RecvHooked(SOCKET sock, char * buffer, int { struct sockaddr_in addr; int bytes, size; char * IP; FILE * fp; bytes = recv(sock,buffer,len,flags); if(bytes == -1) return -1; if(getpeername(sock,(struct sockaddr*)&addr,&size) == 0) { if(addr.sin_addr.s_addr != inet_addr("127.0.0.1")) { fp = fopen("c:\\log.txt","a+"); len, int flags)

if(fp) { IP = inet_ntoa(addr.sin_addr); fputs("**********************************************************\n",fp); fprintf(fp,"-> Dados recebidos\n\n[+] Origem: %s\n",IP); fputs("**********************************************************\n\n",fp); fwrite(buffer,1,bytes,fp); fputs("\n\n",fp); fclose(fp); } } } return bytes; } /////////////////////////////////////////////////////////////////////////////// int WINAPI SendHooked(SOCKET sock, const char * buffer, int { struct sockaddr_in addr; int bytes, size; char * IP; FILE * fp; bytes = send(sock,buffer,len,flags); if(bytes == -1) return -1; if(getpeername(sock,(struct sockaddr*)&addr,&size) == 0) { if(addr.sin_addr.s_addr != inet_addr("127.0.0.1")) { fp = fopen("c:\\log.txt","a+"); if(fp) { len, int flags)

IP = inet_ntoa(addr.sin_addr); fputs("**********************************************************\n",fp); fprintf(fp,"->Dados enviados\n\n[+] Destino: %s\n",IP); fputs("**********************************************************\n\n",fp); fwrite(buffer,1,bytes,fp); fputs("\n\n",fp); fclose(fp); } } } return bytes; } ///////////////////////////////////////////////////////////////////////////////

No exemplo, interceptamos as funes send() e recv() da biblioteca do WinSock. Cada chamada a uma destas funes f com que o programa abra o arquivo c:\log.txt, armazene os dados enviados/recebidos nele e repasse os parmetros s fun verdadeiras. Observe a seguinte linha:

if(addr.sin_addr.s_addr != inet_addr("127.0.0.1"))

Bem, resolvi incluir algo assim no cdigo apenas para mostrar como podemos fazer um filtro simples na funo. No caso o endereo associado ao socket no for o de loopback, loga-se a chamada funo ;) Exemplo:

Para injetar a DLL no processo acima, eu utilizei um DLL Injector escrito em Delphi. O cdigo fonte e o executvel mesmo foi postado no seguinte tpico: http://www.darkers.com.br/forum/index.php/topic,8644.0.html Download do source + binrio da DLL: http://one.xthost.info/darkside17/projetos/c-cpp/Api_Hooking/Api_Hooking.rar []'s Dark_Side
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

Page (Tutoriais) (Papers) (E-Zines) (Videos) (Pagina Principal)

Das könnte Ihnen auch gefallen