SlicK Posted October 19, 2007 Report Posted October 19, 2007 IAT Patching Tutorial by SlicK [slick(at)rstcenter.com]Daca v-ati mai interesat de API hooking inainte probabil ati auzit de IAT si IAT Patching, in acest tutorialvoi incerca sa explic si sa imlementez aceasta tehnica nu foarte complexa dar foarte eficienta.Bazele acestei tehnici se bazeaza pe faptul ca execulabilele si dll'urile pe 32 de biti sunt contruite pe formatul PE(Portable executable). Aceste fisiere contin cateva parti logice numite sectiuni, fiecare sectiune avand uncontinut specific. Sectiunea de interes pentru IAT Patching se numeste ".idata", aceasta contine o tabela speciala numita"Import Address Table"(IAT) esentiala pentru toate fisierele care folosesc librarii dinamice (dll'uri).La rularea unui executabil, dynamic loaderul(parte din kernel) mapeaza fisierul in memorie conform headerului PE, loaderul "priveste" in apoi IAT pentru a vedea daca fisierul foloseste librarii aditionale, daca da le mapeaza si pe acesteain memorie. Loaderul cauta apoi toate functiile importate de catre fisier dupa nume sau dupa ordinal in fiecare librarie sile scrie offestul in IAT. Practic un executabil nu are nevoie sa stie offsetul global pentru fiecare functie importatain parte stiind doar adresa din IAT unde loaderul scrie acel offset, Deci de fiecare data cand fisierul apeleaza o functiedintr-o librarie acesta va apela adresa din IAT unde loaderul a scris adresa acelei functii.IAT Patchingul reprezinta modificarea acelui offeset in IAT cu un altul reprezentand o functie personala care practic vaintercepta fiecare call catre acel API importat putand returna un alt rezultat.Destul cu teoria, sa trecem la implementare.Prima conditie pentru IAT Patching este ca functia interceptoare trebuie sa fie in spatiua de memorie al procesului care ocheama, pentru aceasta voi injecta un dll in acel proces care va patchui deasemenea si IAT'ul. Acesta va citi headerul PEal fisierului aflat in memorie iterand prin toate sectiunile pana cand va gasi sectiunea .idata(adresa de inceput si marimea) apoi va citi cate 4 octeti(marimea unui offset) odata pana cand va gasi adresa functieicare va fi patchuita rescriind aceasta adresa cu adresa functiei interceptoare continuta in dll.O sa sar peste partea cu injectarea unui dll in alt proces pentru ca exista sufient de multe tutoriale.In urmatorul exemplu de dll voi intercepta API'ul GetTickCount astfel incat sa returneze un alt rezultat.(compilat cu Dev-Cpp)======= START iat.cpp ====#include <windows.h>#define PEADDR 0x00400000 // inceputul headerului PE la 99% din executabileDWORD WINAPI FakeGetTickCount(void); // functia interceptoareDWORD APIOffset(LPSTR pszLibName,LPSTR pszFunkName); // returneaza adresa globala pentru un APIDWORD WINAPI Main(LPVOID); // multitrheadingextern "C" BOOL WINAPI DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved) // entry pointul in dll{ if(reason==DLL_PROCESS_ATTACH) { MessageBox(NULL,"Attached to process","Injected dll",MB_OK); // optional CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&Main,NULL,0,NULL); // cream threadul } return(TRUE);}DWORD WINAPI FakeGetTickCount(void) //functia interceptoare trebuie sa fie definita la fel ca functia interceptata (DWORD WINAPI GetTickCount(void)){ return(1000); // returnam mereu acelasi rezultat}DWORD WINAPI Main(LPVOID){ DWORD dwSearch=APIOffset("kernel32","GetTickCount"); // adresa functiei interceptate DWORD dwReplace=(DWORD)*FakeGetTickCount; // adresa functiei interceptoare DWORD dwPid=GetCurrentProcessId(); // Process id'ul procesului curent HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid); if(hProcess!=NULL) { IMAGE_DOS_HEADER image_dos_header; IMAGE_NT_HEADERS image_nt_headers; IMAGE_SECTION_HEADER image_section_header[20]; if(ReadProcessMemory(hProcess,(LPVOID)PEADDR,&image_dos_header,sizeof(IMAGE_DOS_HEADER),NULL)) // citim headerul DOS { if(ReadProcessMemory(hProcess,(LPVOID)(PEADDR+image_dos_header.e_lfanew),&image_nt_headers,sizeof(IMAGE_NT_HEADERS),NULL)) // citim headerul NT { DWORD dwRO_first_section=image_dos_header.e_lfanew+sizeof(IMAGE_NT_HEADERS); DWORD SectionNum=image_nt_headers.FileHeader.NumberOfSections; if(ReadProcessMemory(hProcess,(LPVOID)(PEADDR+dwRO_first_section),&image_section_header,SectionNum*sizeof(IMAGE_SECTION_HEADER),NULL)) // citim headerul sectiunilor { for(int i=0;i<SectionNum;i++) // iteram prin toate sectiunile { if(!strcmp((char *)image_section_header[i].Name,".idata")) // cand gasim sectiunea ".idata" { DWORD dwIDAddr=PEADDR+image_section_header[i].VirtualAddress; // inceputul sectiunii DWORD dwIDSize=image_section_header[i].Misc.VirtualSize; // dimensiunea sectiunii DWORD dwOldProtect; if(VirtualProtect((LPVOID)dwIDAddr,dwIDSize,PAGE_READWRITE,&dwOldProtect)) // ne asiguram ca avem permisiuni de citire si scriere { DWORD dwVAddr=0; BOOL bFound=FALSE; for(int i=0;i<dwIDSize;i+=4) // citim cate 4 octeti odata pana gasim adresa functie interceptate { if(ReadProcessMemory(hProcess,(LPVOID)dwIDAddr,&dwVAddr,4,NULL)) { if(dwVAddr==dwSearch) { bFound=TRUE; break; } } dwIDAddr+=4; } if(bFound==TRUE) { if(WriteProcessMemory(hProcess,(LPVOID)dwIDAddr,&dwReplace,4,NULL)) // inlocuim adresa functiei interceptate cu adresa functiei interceptoare { MessageBox(NULL,"IAT Patched","Injected dll",MB_OK); //optional } } } } } } } } CloseHandle(hProcess); } ExitThread(0);}DWORD APIOffset(LPSTR pszLibName,LPSTR pszApiName){ DWORD dwRet=0; HMODULE hmLib=LoadLibrary(pszLibName); if(hmLib!=NULL) { FARPROC fpApi=GetProcAddress(hmLib,pszApiName); if(fpApi!=NULL) { dwRet=(DWORD)fpApi; } FreeLibrary(hmLib); } return(dwRet);}========== END ==========Am atasat si o arhiva care contine sursa dll'ului,dll'ul compilat,un mic program de test si un program pentru injectarea dll'uluiDownload: http://rootb0x.com/0X0/iatp.rarCam atat cu acest tutorial, sper ca nu a fost greu de citit si inteles. Quote
alien Posted October 20, 2007 Report Posted October 20, 2007 cam greu de disecat tot codu asta. Am inteles ce face. Merge si pe xp nu? Nu inteleg totushi la ce ma ajuta. Nu inteleg care este procesul in care injectez functia? si dc functia FakeGetTickCount returneaza 1000 tot timpu?editaaaaaa stai ca m-am prins. test.exe dupa injectare va afisa numa 1000. da mai am o intrebare. de ex cum fac sa injectez un cod intr-o functie din yahoo messenger sa zicem? cum afu numele functiei? Quote
SlicK Posted October 20, 2007 Author Report Posted October 20, 2007 Dupa cum am scris si acolo IAT Patching functioneaza doar cand executabilul importa functia dintr-un dll iar numele functiilor din dll'uri le poti afla cu "DumpBin" de exemplu.Utilizarile sunt extrem de multe pentru ca pe langa faptul ca poti modifica valoarea returnata primesti si parametrii pe care programul ii paseaza functiei. Quote