Denkfehler bei meinem Hook?
-
Einen wunderschönen Montagmittag allen miteinander!
Da ich die Basics der WINApi inzwischen durch habe, dachte ich mir ich fange mal mit den Detouren von Funktionen an. Da ich kein Buch fand (wer eins kennt bitte melden :)) hab ich das anhand verschiedener Internet-Tutorials gemacht. Das Problem ist nun, dass es einfach nicht funktionieren will. Hab mir mein "Opferprogramm" und die Dll mit der Zielfunktion selbst geschrieben. Sie ist denkbar einfach:void DLL_EXPORT function1() { MessageBox(NULL, "Message", "Dll", MB_OK); }
Hab mir im Programm noch einen Button gemacht, der die Funktion aufruft, funktioniert alles. (DLL_EXPORT ist passend definiert...)
Meine Hook-Dll (kann man das so nennen?) sieht nun wie folgt aus:
void FakeFun() { MessageBox(0, "FakeFun", "", MB_OK); } void* DetourFunc(PBYTE, const PBYTE, const int); typedef void (*OriginalFunc)(void); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { //my::Dll dll(DLL_PATH("DetourOpferDll.dll")); switch (fdwReason) { case DLL_PROCESS_ATTACH: // attach to process //my::DetourFunc(reinterpret_cast<PBYTE>(dll.GetProcAddress<void (*) (void)>("function1")), (PBYTE)FakeFun, 5); OriginalFunc f; f = (OriginalFunc)DetourFunc((PBYTE)0x702411e4, (PBYTE)FakeFun, 5); break; } return true; // succesful } void* DetourFunc(PBYTE src, const PBYTE dst, const int len) { PBYTE jmp = (PBYTE)malloc(len+5); DWORD dwback; VirtualProtect(src, len, PAGE_READWRITE, &dwback); memcpy(jmp, src, len); jmp+=len; jmp[0] = 0xe9; *(PDWORD)(jmp+1) = (DWORD)(src+len-jmp)-5; src[0] = 0xe9; *(PDWORD)(src+1) = (DWORD)(dst-src)-5; VirtualProtect(src, len, dwback, &dwback); return (jmp-len); }
Passende Header (windows.h) sind auch inkludiert, hab einfach nur das wesentliche rauskopiert.
Die Addresse stimmt lt. IDA Pro auch und hab sie mir auch mit GetProcAddress mal vom "Opferprogramm" ausgeben lassen. Stimmt alles überein.
Hab dann das Opferprogramm gestartet und die Dll mit dem DllInjector, den mir hier letztens jemand empfahl injected. Wenn ich nun wieder auf den Button drücke wird aber immernoch die normale Funktion ausgeführt. Warum funktioniert das nicht so, wie ich es mir denke? Hab ich einen kompletten Denkfehler drin oder mal wieder nur irgendetwas kleines vergessen?PS: Hab die Dll mit der "Opferfunktion" auch schon auf verschiedene Weise vom "Opferprogramm" laden lassen (per Compiler, per LoadLibrary)
Danke im Voraus
-
*push* - Hat niemand eine Idee? :s
-
kA, schau erstens mal ob die dll geladen ist (procexp), dann schau was nach dem inject an der originalfunktion für op codes stehen (ollydbg).
Ggf. greife besser auf MS detours zurück (seit 3.0 keine detoured.dll mehr nötig).
Zum injecten hat sich die CreateRemoteThread methode bewährt.
-
Entschuldige bitte die späte Antwort, hab in letzter Zeit einfach viel um die Ohren.
Hab mir mal ProcExp angeschaut und runtergeladen, die Dll wird von meinem Zielprozess defintiv geladen bzw. vom Injector korrekt injected.
Aber mit OllyDbg kann ich an der Addresse der Funktion keine Veränderung finden und auch IDA Pro zeigt mir immernoch die Alte Funktion an dieser Stelle.Hab auch schon versucht diverse andere einfache Funktionen nach demselben Schema zu hooken (z.B. Sleep) hat aber ebenso wenig funktioniert.
Hab mir auch mal Microsoft Detours angeschaut aber es mit CodeBlocks leider nicht zum Laufen bekommen. Gibt auch kein gutes Turorial im Inet, welches erklärt, wie man das nun eigentlich einrichtet.
-
Lass mal testweise den folgenden Code am Anfang von deinem Injector Programm ausführen und starte alles mit Adminrechten:
bool EnableDebugPrivilege() { TOKEN_PRIVILEGES priv; HANDLE hThis, hToken; LUID luid; hThis = GetCurrentProcess(); OpenProcessToken(hThis, TOKEN_ADJUST_PRIVILEGES, &hToken); LookupPrivilegeValue(0, "seDebugPrivilege", &luid); priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0); CloseHandle(hToken); CloseHandle(hThis); return true; }
-
Funktioniert auch nicht... Wenn jemand Zeit hat, poste ich hier einfach mal meinen gesamten Quellcode:
DetourOpferprogramm.exe:
main.cpp
#include <dll.h> #include <windows.h> LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); void (*pFunction1)(void); char szClassName[ ] = "MyApp"; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) { HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; if (!RegisterClassEx (&wincl)) return 0; hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "DetourOpferprogramm.exe", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); ShowWindow (hwnd, nCmdShow); UpdateWindow(hwnd); /**DLL Load**/ try { my::Dll d(DLL_PATH("DetourOpferDll.dll")); //DLL_PATH formatiert das um, damit der Pfad stimmt pFunction1 = d.GetProcAddress<void(*)(void)>("function1"); } catch(std::string& mes) { MessageBox(hwnd, "Fehler", mes.c_str(), MB_OK); } /**DLL loaded**/ while (GetMessage (&messages, NULL, 0, 0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return messages.wParam; } LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HINSTANCE hInst = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE); switch (message) /* handle the messages */ { case WM_ACTIVATE: HWND hBut; hBut = CreateWindow("button", "Push to Execute function1()", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 200, 200, 250, 50, hwnd, (HMENU)1, hInst, 0); break; case WM_COMMAND: if (LOWORD(wParam) == 1) { pFunction1(); } break; case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }
DetourOpferDll.dll
main.cpp
#include <windows.h> BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return TRUE; // succesful } void __declspec(dllexport) function1() { MessageBox(NULL, "Message ausser Dll", "Dll", MB_OK); }
TaeterDll1.dll
main.cpp
#include <windows.h> void FakeFun() { MessageBox(0, "FakeFun", "", MB_OK); } void* DetourFunc(BYTE*, const BYTE*, const int); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { static void (*pFakeFun) (void) = FakeFun; switch (fdwReason) { case DLL_PROCESS_ATTACH: DetourFunc((PBYTE)0x663811e4, (PBYTE)pFakeFun, 5); break; } return true; // succesful } void *DetourFunc(BYTE *src, const BYTE *dst, const int len) // credits to gamedeception { BYTE *jmp = (BYTE*)malloc(len+5); DWORD dwback; VirtualProtect(src, len, PAGE_READWRITE, &dwback); memcpy(jmp, src, len); jmp += len; jmp[0] = 0xE9; *(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5; src[0] = 0xE9; *(DWORD*)(src+1) = (DWORD)(dst - src) - 5; VirtualProtect(src, len, dwback, &dwback); return (jmp-len); }
DllInjector.exe:
#include <windows.h> #include <iostream> #include <TlHelp32.h> #include <fstream> #include <conio.h> #include <string> using namespace std; void GetDebugPrivileges(); bool EnableDebugPrivilege(); unsigned GetProcessIdByProcessName( string AppName ); bool CheckIfRequiredDataExist( string AppName, string DLL_NAME ); int main() { string AppName; string DLL_NAME; GetDebugPrivileges(); // Damit bekommt man Debug Previlegien die eigenen Anwendung bekommt dadurch mehr rechte EnableDebugPrivilege(); cout<<"Process name of target application "; cin>>AppName; cout<<"Name of your DLL file: "; cin>>DLL_NAME; bool ret = CheckIfRequiredDataExist( AppName, DLL_NAME ); // Prüft ob die Zielanwendung und die DLL Datei existieren if ( ret == true) { cout<<"Press any key to exit"<<endl; getch(); return 0; } DWORD ID = GetProcessIdByProcessName( AppName ); HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, false, ID); if( ProcessHandle == 0 ) { cout<<"OpenProcess error code: " << GetLastError() << endl; cout<<"Press any key to exit"<<endl; getch(); return 0; } void *addr = VirtualAllocEx(ProcessHandle, 0, strlen(DLL_NAME.c_str() ) , MEM_COMMIT, PAGE_EXECUTE_READWRITE); ret = WriteProcessMemory(ProcessHandle, (void*)addr, (void*)DLL_NAME.c_str(), strlen(DLL_NAME.c_str()), 0); if( ret == false ) { cout<<"WriteProcessMemory error code: " << GetLastError() <<endl; cout<<"Press any key to exit"<<endl; getch(); return 0; } HANDLE ThreadHandle =CreateRemoteThread(ProcessHandle, 0, 0, (LPTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA"), addr, 0, 0); if( ThreadHandle==NULL ) { cout<<"CreateRemoteThread error code: " << GetLastError() << endl; cout<<"Press any key to exit"<<endl; getch(); return 0; } WaitForSingleObject(ThreadHandle, INFINITE); bool free = VirtualFreeEx(ProcessHandle, addr, strlen(DLL_NAME.c_str()), MEM_DECOMMIT); if( free == false ) { cout<<"CreateRemoteThread error code: " << GetLastError() << endl; cout<<"Press any key to exit"<<endl; getch(); return 0; } cout<<"Press any key to exit"<<endl; getch(); return 0; } bool CheckIfRequiredDataExist( string AppName, string DLL_NAME ) { bool error = false; ifstream AppFile (AppName.c_str() ); ifstream DLLFile (DLL_NAME.c_str() ); if ( ! AppFile.good() ) { cout<<"The file: " << AppName << " does not exist."<<endl; cout<<"(The DLL Injector must be in the same folder like your target application !"<<endl; error = true; } if ( ! AppFile.good() ) { cout<<"The DLL file: " << DLL_NAME << " does not exist."<<endl; error = true; } return error; } unsigned GetProcessIdByProcessName( string AppName ) { bool ProcessExists = false; HANDLE snap; PROCESSENTRY32 lppe; snap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if ( snap == INVALID_HANDLE_VALUE ) { cout<<"Couldnt make a snapshot, error code: " << GetLastError() << endl; return 0; } lppe.dwSize = sizeof(PROCESSENTRY32); Process32First( snap, &lppe ); do { if( ! strcmp(lppe.szExeFile, AppName.c_str() ) ) { cout<<lppe.szExeFile << " Process ID: " << lppe.th32ProcessID << endl; ProcessExists = true; break; } } while ( Process32Next ( snap , &lppe ) == 1 ) ; if ( ProcessExists == false ) { return 0; } return lppe.th32ProcessID; } void GetDebugPrivileges() { HANDLE TokenHandle; bool OpenTokenBool = OpenProcessToken( GetCurrentProcess() ,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,& TokenHandle ); if ( OpenTokenBool==false ) { cout<<"OpenProcessToken error code: "<< GetLastError()<<endl; return ; } TOKEN_PRIVILEGES TokPrev; LUID_AND_ATTRIBUTES LUIDAttrib; TokPrev.PrivilegeCount=1; TokPrev.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; bool LookUpBool = LookupPrivilegeValue(0, "SeDebugPrivilege", &TokPrev.Privileges[0].Luid ); if ( LookUpBool==false ) { cout<<"LookupPrivilegeValue error code: "<< GetLastError()<<endl; return ; } bool adjust = AdjustTokenPrivileges( TokenHandle,false, &TokPrev, sizeof(TOKEN_PRIVILEGES),0,0 ); if ( adjust==false ) { cout<<"AdjustTokenPrivileges error code: "<< GetLastError()<<endl; return ; } } bool EnableDebugPrivilege() { TOKEN_PRIVILEGES priv; HANDLE hThis, hToken; LUID luid; hThis = GetCurrentProcess(); OpenProcessToken(hThis, TOKEN_ADJUST_PRIVILEGES, &hToken); LookupPrivilegeValue(0, "seDebugPrivilege", &luid); priv.PrivilegeCount = 1; priv.Privileges[0].Luid = luid; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0); CloseHandle(hToken); CloseHandle(hThis); return true; }
Der DllInjector ist übrignes nicht von mir, ich will mich hier nicht mit fremden Blumen schmücken! Genauso wenig wie die DetourFunc.
Entschuldigt vielmals den Monster langen Post, konnte leider keine Spoilers finden...
-
Und die fixe Adresse 0x663811e4? Die Funktion ist bei jedem Start des Opferprogramms genau dort?
-
Laut IDA Pro, wenn ich die Dll disassamble, ja.
function1 .text 663811E4 0000002F R . . . B . .
(die Hexadezimalzahl dahinter ist übrigens die Länge)
Wo könnte ich sehen, ob diese Addresse statisch ist?
-
Die Adresse im Prozessspeicher, nicht in der Dll-Datei... hole sie mit GetProcAddress.
-
In Zeile 29 hast Du ein Bug! -> taeter.dll
-
-lb schrieb:
In Zeile 29 hast Du ein Bug! -> taeter.dll
Mal so aus Neugier: Was ist denn der Fehler genau?
-
Also wenn man denn Hook startet passiert nichts. Die MsgBox wird scheinbar gehookt, doch es passiert nichts. Wenn man die calladdresse zu Msgbox nimmt funktioniert es, doch nach der gehookten Funktion stürzt das Opferprogramm ab. Irgendetwas schein nicht zu Funktionieren.!?
-
Ich bin Matrix... schrieb:
Einen wunderschönen Montagmittag allen miteinander!
Da ich die Basics der WINApi inzwischen durch habe, dachte ich mir ich fange mal mit den Detouren von Funktionen an. Da ich kein Buch fand (wer eins kennt bitte melden :)) hab ich das anhand verschiedener Internet-Tutorials gemacht. Das Problem ist nun, dass es einfach nicht funktionieren will. Hab mir mein "Opferprogramm" und die Dll mit der Zielfunktion selbst geschrieben. Sie ist denkbar einfach:void DLL_EXPORT function1() { MessageBox(NULL, "Message", "Dll", MB_OK); }
Hab mir im Programm noch einen Button gemacht, der die Funktion aufruft, funktioniert alles. (DLL_EXPORT ist passend definiert...)
Meine Hook-Dll (kann man das so nennen?) sieht nun wie folgt aus:
void FakeFun() { MessageBox(0, "FakeFun", "", MB_OK); } void* DetourFunc(PBYTE, const PBYTE, const int); typedef void (*OriginalFunc)(void); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { //my::Dll dll(DLL_PATH("DetourOpferDll.dll")); switch (fdwReason) { case DLL_PROCESS_ATTACH: // attach to process //my::DetourFunc(reinterpret_cast<PBYTE>(dll.GetProcAddress<void (*) (void)>("function1")), (PBYTE)FakeFun, 5); OriginalFunc f; f = (OriginalFunc)DetourFunc((PBYTE)0x702411e4, (PBYTE)FakeFun, 5); break; } return true; // succesful } void* DetourFunc(PBYTE src, const PBYTE dst, const int len) { PBYTE jmp = (PBYTE)malloc(len+5); DWORD dwback; VirtualProtect(src, len, PAGE_READWRITE, &dwback); memcpy(jmp, src, len); jmp+=len; jmp[0] = 0xe9; *(PDWORD)(jmp+1) = (DWORD)(src+len-jmp)-5; src[0] = 0xe9; *(PDWORD)(src+1) = (DWORD)(dst-src)-5; VirtualProtect(src, len, dwback, &dwback); return (jmp-len); }
Passende Header (windows.h) sind auch inkludiert, hab einfach nur das wesentliche rauskopiert.
Die Addresse stimmt lt. IDA Pro auch und hab sie mir auch mit GetProcAddress mal vom "Opferprogramm" ausgeben lassen. Stimmt alles überein.
Hab dann das Opferprogramm gestartet und die Dll mit dem DllInjector, den mir hier letztens jemand empfahl injected. Wenn ich nun wieder auf den Button drücke wird aber immernoch die normale Funktion ausgeführt. Warum funktioniert das nicht so, wie ich es mir denke? Hab ich einen kompletten Denkfehler drin oder mal wieder nur irgendetwas kleines vergessen?PS: Hab die Dll mit der "Opferfunktion" auch schon auf verschiedene Weise vom "Opferprogramm" laden lassen (per Compiler, per LoadLibrary)
Danke im Voraus
Komisch wie Du das machst, aber ehrlich gesagt ist mir das auch shit egal. Aber ich denke das Funktioniert nicht ganz (Kurz überflogen). Wenn Du die src Addr mit einem relativen jump zu deiner Funktion überschrieben hast musst Du sie auch sichern. Bevor dass Du die Originalfunktion wieder aufrufst in FakeFun, musst Du die Originaladresse wieder herstellen mit den zuvor gesicherten bytes, da Du sonnst in einer Endlosschleife bist und somit gar nichts zu Gesicht bekommst.
-
-
Tipi der freundliche Tipp schrieb:
Unterstützt aber nur x86! Für x64 braucht man eine Liz.
-
Hallo, da mich auch das Thema Hooks interessiert habe ich mich damit auch mal etwas beschäftigt.
Ich habe hier ein gutes Tutorial gefunden wo das ganze erklärt wird. Nachdem anschauen von dem Tutorial habe ich mir ein einfaches test Programm geschrieben und mal geschaut ob das auch funktioniert und ich kann mich nicht beklagen funktioniert ohne Problem.
Hier ist der Link zu dem Tutorial:
http://www.vivid-abstractions.net/downloads/InDem Present/Hooking Tutorial.htmDa such mal nach Hook dann siehste auch den kompletten Quelltext
http://www.vivid-abstractions.net/category/programming/tutorials/Der Autor ist hier auch im Forum registriert fällt mir gerade ein.^^
Naja danke nochmal an Patrickssj6 das er sich die Arbeit gemacht hat.