kernel32 hook
-
Folgendes: Ich möchte gern einen Funktionshook für kernel32.dll z.b. machen und weiß jetzt nicht genau wie es am klügsten wäre... klar gibt es ne variante wie es glaub ich systemweit geht (recht kompliziert mit PE format auslesen) doch will ich genau einen Prozess "überwachen".
So bevor ich da ne riesige flameware starte kann ich euch beruhigen es geht darum dem internet explorer zu hindern irgendwelche viren reinzulassen. Die idee ist das alle befehle die etwas ausführen können (CreateProzessA...) vorher abgefangen werden und ich das dann verhindern kann. Wäre meiner Meinung nach ne recht kluge Virenprotection!So meine idee und frage zugleich wäre folgendes:
Kann man nicht einfach ne kernel32.dll schreiben und sie dann ins hauptverzeichniss kopieren und dann nimmt die exe die funktionen von dieser... ich weiß nur das es einen CounterStrike cheat gab wo man die opengl32.dll einfach in den ordner von der exe hineinkopiert hat und schon konnte der cheat alles mögliche steuern (da er irgendwie statt der normalen aufgerufen wurde). 1. Frage wäre ob das bei der kernel von der theorie her auch ginge!
2. Wie funktioniert das trickreiche system das er automatisch (bei dieser opengl32) nur ein paar funktionen neu implementiert und den rest recht schnell weiterleitet... zur not wenn 1) funktioniert dann könnte man zur not auch eine file von irgendwo suchen wo alle funktionen aufgelistet sind mit allen parametern oder gibts da ne schnellere methode via asm... denn das problem sind dann ja die parameter am stack nur kommt dann ja noch die rücksprungadresse und ich weiß das ich das schonmal so probiert hab aber ned zambracht hab. Kann zwar jetzt asm ein bisschen besser aber ich bin ma ned sicher was man alles machen darf und wie genau alles aufgebaut ist..
Für antworten und ein bisschen asm hilfe wäre ich dankbar!
(Nur für die flamer unter uns: Ich spiel kein cs im internet und bescheiß auch niemanden und es ist mir auch genau scheißegal, ich halte nix von kopierten cheats und auch bei selbstgemachten hält sich meine bewunderung meist in grenzen... das hat mich eher immer vom system her interessiert wie er etwas auf den bildschirm zaubern konnte obwohl opengl lief (auch bei fraps); also ned flamen es geht mir hier echt um antworten und ich würd dieses tool gerne verwirklichen!
Danke für eure hilfe
cu Manuelh87
-
Es ist denk ich einfacher wenn du das auf die andere weise machst. Dazu gibts auch ne menge zeug im netz. Ich hab sowas auch schonmal gemacht. Im Prinzip sind es nur 2 funktionen die du brauchst:
einmal um eine dll in den prozess zu laden brauchst do sowas in der art:
bool ForceLibrary(HANDLE hProcess, char *szDllPath) { if(!szDllPath || !szDllPath) return false; HANDLE hLoadLibraryAThread; LPTHREAD_START_ROUTINE pfnLoadLibraryA; HMODULE hKernel = GetModuleHandle("KERNEL32.dll"); LPVOID pRemoteMem; pfnLoadLibraryA = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel, "LoadLibraryA"); if(!pfnLoadLibraryA){ printf("Couldn't get LoadLibraryA Address.\n"); return false; } pRemoteMem = VirtualAllocEx(hProcess, 0, strlen(szDllPath)+1, MEM_COMMIT, PAGE_READWRITE); if(!pRemoteMem){ printf("Allocating Space failed.\n"); return false; } if(!WriteProcessMemory(hProcess, pRemoteMem, szDllPath, strlen(szDllPath)+1, NULL)){ printf("Writing Dll Path to Ram failed.\n"); return false; } hLoadLibraryAThread = CreateRemoteThread(hProcess, NULL, 0, pfnLoadLibraryA, pRemoteMem, 0, NULL); if(!hLoadLibraryAThread){ printf("Couldn't create remote Thread.\n"); return false; } WaitForSingleObject(hLoadLibraryAThread, INFINITE); if(!VirtualFreeEx(hProcess, pRemoteMem, NULL, MEM_RELEASE)){ printf("Couldn't free Memory.\n"); return false; } return true; }und einmal sowas hier wenn die dll geladen ist um die funktion zu hook:
size_t strnlen(char *s, size_t Size) { u_int i; for (i=0; s[i] && i<Size; i++) ; return i; } bool StrCaseCmp(char *s1, char *s2, size_t Size) { size_t ls1 = strnlen(s1, Size), ls2 = strnlen(s2, Size); if(ls1 != ls2) return false; for(u_int i = 0; i < ls1 && i < Size; i++) { if(tolower(*s1) == tolower(*s2)){ s1++; s2++; continue; } return false; } return true; } DWORD VaToRva(DWORD Base, DWORD Offset) { return Base + Offset; } bool PatchIAT(char *szDllName, char *szFktToPatch, DWORD AddressOfNewFkt, DWORD *AddressOfOldFkt) { HMODULE hModule = GetModuleHandle(NULL); DWORD OrgAdressOfFunctionToPatch = (DWORD)GetProcAddress(GetModuleHandle((char*)szDllName), szFktToPatch); if(!OrgAdressOfFunctionToPatch){ return false; } PIMAGE_DOS_HEADER pDOSHeader = NULL; PIMAGE_NT_HEADERS pNTHeaders = NULL; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = NULL; DWORD BaseAddress = (DWORD)hModule; pDOSHeader = (PIMAGE_DOS_HEADER)BaseAddress; if(pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE){ return false; } pNTHeaders = (PIMAGE_NT_HEADERS)VaToRva(BaseAddress, pDOSHeader->e_lfanew); __try{ if(pNTHeaders->Signature != IMAGE_NT_SIGNATURE){ return false; } } __except(EXCEPTION_EXECUTE_HANDLER){ return false; } __try{ pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)VaToRva ( BaseAddress, pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress ); if(!pImportDescriptor){ return false; } } __except(EXCEPTION_EXECUTE_HANDLER){ return false; } while(pImportDescriptor->Name) { if(StrCaseCmp(szDllName, (char*)VaToRva(BaseAddress, pImportDescriptor->Name), strlen(szDllName))) { DWORD *pThunk = (PDWORD)VaToRva(BaseAddress, pImportDescriptor->FirstThunk); while(*pThunk) { if(*pThunk == OrgAdressOfFunctionToPatch) { DWORD dwProtectionBackup; if(!VirtualProtect(pThunk, sizeof pThunk, PAGE_EXECUTE_READWRITE, &dwProtectionBackup)) return false;; *AddressOfOldFkt = *pThunk; __try{ *pThunk = AddressOfNewFkt; } __except(EXCEPTION_EXECUTE_HANDLER){ return false; } if(!VirtualProtect(pThunk, sizeof pThunk, dwProtectionBackup, &dwProtectionBackup)) return false; if(*pThunk != OrgAdressOfFunctionToPatch && *pThunk == AddressOfNewFkt) { return true; } } pThunk++; } } pImportDescriptor++; } return false; }
-
Danke für die antwort und den code (code ist sehr verständlich im gegensatz zu dem den ich gefunden hab
) werds mal so probieren... kann ja überprüfen ob es im richtigen prozess ist oder nicht..(oder wie ist das jetzt mit abfangen?? eigentlich wird doch die handle für alle user der kernel32 verändert oder.. gibts da nicht probleme??) na ich test halt mal einfach... danke jedenfalls für die hilfe... vielleicht werd ich ja den internet explorer noch heute ein stück sicherer machen... weiß aber gar nicht ob er irgendwas verhindern kann aber ich denk mal der versuch ist es wert...
cu manuelh87
-
hm ok ich werd das vielleicht doch noch mal bischen erklaern muessen. Du brauchst eine exe die den prozess (in deinem fall den internet explorer) startet oder wenn er schon gestartet ist, ausfindig macht.
In der exe musst du dann in den adressraum des prozesses eine dll hinein laden, die deinen eigenen code enthaelt, denn du kannst einen anderen prozess nicht sagen das er mal eben code aus deinem prozess ausfuehren soll! (weil jeder prozess einen eigenen virtuellen adressraum besitzt) Diese dll wird aber jetzt von windows in den adressraum des prozesses (zb internet explorer) mittels ForceLibrary(...) eingefuegt und kann somit beliebigen (eigenen) code im adressraum des zb internet explorer ausfuehren lassen!
Nun musst du wissen das jeder prozess eine eigene tabelle hat in der steht an welcher stelle welche funktion zu finden ist (das gilt nur fuer funktionen in dlls!). Diese stelle sucht dir die funktion PatchIAT. Du musst ihr dazu den namen der dll geben in der du meinst das diese funktion ist (szDllName, also "Kernel32.dll") und den namen der funktion die du suchst(szFktToPatch, also in deinem Fall "CreateProcessA" oder "CreateProcessW"). Wenn PatchIAT (diese tabelle heisst uebrigens import adress table - kurz IAT) deine funktion gefunden hat ueberschreibt sie die adresse zur orginalen funktion mit der adresse die du ihr gegeben hast. Auserdem gibt sie dir vorher noch die adresse der orginal funktion, damit du die moeglichkeit hast diese noch aufzurufen und sie nicht verlohren geht.
Also lange reder kurzer sinn: du gibst ihr die adresse deiner "Fake" funktion (AddressOfNewFkt) (die im uebrigen exakt die gleichen parameter und "call conventions" haben muss wie die urspruengliche) und erhaelst gleichzeitig die adresse der orginal funktion (*AddressOfOldFkt)Zum test kannst du ja mal einfach eine MessageBox aufrufen wenn der ie CreateProcess benutzen will
Also noch etwas code (nur ausm kopf also diesmal nicht copy&paste geeignet
)//So koennte die exe aussehen wenn sie den ie startet und dann ForceLibrary aufruft: STARTUPINFO StartInfo = { 0 }; // <-ausfuellen PROCESS_INFORMATION ProcInfo = { 0 }; // <- wird con createProcess ausgefuellt CreateProcess(/*argumente ausfuellen/*, &ProcInfo); // auf fehler pruefen ForceLibrar(ProcInfo.hProcess, "C:\\Absoluten\\Pfad\\zu\\deiner\\Dll.dll") // auf fehler pruefen //endeund die dll koennte so aehnlich aussehen:
FARPROC (WINAPI *OrgCreatePRocessA)(HMODULE hModule, LPCSTR lpProcName); // Funktions pointer zur orginal funktion, parameter stimmen nicht FARPROC WINAPI FakeCreatePRocessA(HMODULE hModule, LPCSTR lpProcName) // deine "fake" oder "hook" funktion { MessageBox(NULL, "CreateProcessA wird aufgerufen!", "Info", MB_OK); return OrgCreateProcessA(/*parameter weiter geben*/); // die Orginal funktion aufrufen um das programm nicht zu veraendern } BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD dwReason, LPVOID pReserved) { switch(dwReason) { case DLL_PROCESS_ATTACH: DWORD OrgAddressOfCreatePRocessA; PatchIAT("Kernel32.dll", "CreateProcessA", (DWORD)FakeCreatePocess, &OrgAddressOfCreateProcessA); OrgCreateProcess = (FARPROC (WINAPI *)(HMODULE, /* Parameter stimmen nicht*/LPCSTR))OrgAddressOfCreatePRocess; break; case DLL_PROCESS_DETACH: break; } return dwReason; }
-
das geht auch alles etwas einfacher
--> http://research.microsoft.com/sn/detours/
-
naja so kompliziert is das meiner meinung nach nicht. Aber diese detours lib ist bestimmt auch nicht schlecht
-
Ne ist schon okay so... ich find den code eh gut und nicht zu schwer... waren nur ein paar grundsätzliche sache die ich nicht wusste... aber du hast jetzt alle fragen beantwortet.. (mir war nicht klar das jeder prozess einen eigenen table hat..) das mit dem adressraum hab ich gewusst und hab mich jetzt eben gefragt ob ich da dann nen fehler produzier wenn irgend ein andrer prozess verusucht createprozess aufzurufen.. aber danke für die aufklärung.. sonst alles okay hatte nur leider keine zeit daran zu arbeiten funktioniert aber sich hoff ich...
cu Manuelh87