2016-04-16 9 views
2

Ich lerne, um Haken für Windows API zu schreiben und für Übung schreibe ich einen Haken für pDeleteFileA Funktion. Wenn die Funktion aufgerufen wird, werde ich vor dem Löschen der Datei prüfen, ob der Dateiname "testfile.txt" lautet. Wenn ja, wird eine Nachricht angezeigt, anstatt sie zu löschen. Wenn sie etwas anderes aufgerufen hat, wird die Datei gelöscht.Windows API Hook C++

Ich habe bereits Code geschrieben und der Code kompiliert ohne Fehler, aber wenn ich versuche, 'testfile.txt' zu löschen, wird es gerade gelöscht. Vielleicht könnte mir jemand einen Hinweis geben, was ich falsch mache oder was ich nicht mache?

Hier ist mein Code so weit:

#include <Windows.h> 

struct hook_t{// a datatype to store information about our hook 
    bool isHooked = false; 
    void* FunctionAddress = operator new(100); 
    void* HookAddress = operator new(100); 
    char Jmp[6] = { 0 }; 
    char OriginalBytes[6] = {0}; 
    void* OriginalFunction = operator new(100); 
}; 

namespace hook { 
    bool InitializeHook(hook_t* Hook, char* Module, char* Function, void* HookFunction) { 
     HMODULE hModule; 
     DWORD OrigFunc, FuncAddr; 
     byte opcodes[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0xe9, 0x00, 0x00, 0x00, 0x00}; 
     if (Hook->isHooked) { 
      return false; 
     } 

     hModule = GetModuleHandleA(Module); 
     if (hModule == INVALID_HANDLE_VALUE) { 
      Hook->isHooked = false; 
      return false; 
     } 

     Hook->Jmp[0] = 0xe9; 
     *(PULONG)&Hook->Jmp[1] = (ULONG)HookFunction - (ULONG)Hook->FunctionAddress - 5; 
     memcpy(Hook->OriginalBytes, Hook->FunctionAddress, 5); 
     Hook->OriginalFunction = VirtualAlloc(0, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 
     if (Hook->OriginalFunction == NULL) { 
      return false; 
     } 
     memcpy(Hook->OriginalFunction, Hook->OriginalBytes, 5); 
     OrigFunc = (ULONG)Hook->OriginalFunction + 5; 
     FuncAddr = (ULONG)Hook->OriginalFunction + 5; 
     *(LPBYTE)((LPBYTE)Hook->OriginalFunction + 5) = 0xe9; 
     *(PULONG)((LPBYTE)Hook->OriginalFunction + 6) = (ULONG)FuncAddr; 
     Hook->isHooked = true; 
     return true; 

    }//end InitializeHook 

    bool InsertHook(hook_t* Hook) { 
     DWORD op; 
     if (!Hook->isHooked) { 
      return false; 
     } 
     VirtualProtect(Hook->FunctionAddress, 5, PAGE_EXECUTE_READWRITE, &op); 
     memcpy(Hook->FunctionAddress, Hook->Jmp, 5); 
     VirtualProtect(Hook->FunctionAddress, 5, op, &op); 
     return true; 
    } 

    bool Unhook(hook_t* Hook) { 
     DWORD op; 
     if (!Hook->isHooked) { 
      return false; 
     } 
     VirtualProtect(Hook->FunctionAddress, 5, PAGE_EXECUTE_READWRITE, &op); 
     memcpy(Hook->FunctionAddress, Hook->OriginalBytes, 5); 
     VirtualProtect(Hook->FunctionAddress, 5, op, &op); 
     Hook->isHooked = false; 
     return true; 
    } 

    bool FreeHook(hook_t* Hook) { 
     if (Hook->isHooked) { 
      return false; 
     } 
     VirtualFree(Hook->OriginalFunction, 0, MEM_RELEASE); 
     memset(Hook, 0, sizeof(hook_t*)); 
     return true; 
    } 

}//end namespase 

========================================================================== 

#define _CRT_SECURE_NO_WARNINGS 

#include "apihook.h" 
#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 

using namespace hook; 

//define the function to be hooked 
typedef BOOL(WINAPI* pDeleteFileA)(LPCSTR lpFileName);//in this case this will be delete file a 

pDeleteFileA pDeleteFile;//instance of it 
hook_t* Hook = new hook_t(); 

//this function will replace the original API function in the process 
BOOL WINAPI HookDeleteFileA(LPCSTR lpFileName) { 
    //we can do here whatever we want before the original API function is called 
    //for example disable deleting of a certain file 
    if (strstr(lpFileName, "testfile")) {//checks if parameter contains a string 
     //disable deleting of this file 
     SetLastError(ERROR_ACCESS_DENIED); 
     MessageBoxA(0, "You can't delete this file!", "error", 0); 
     return false; 
    } 
    return pDeleteFile(lpFileName);//if parameter does not contain our string, call the original API function 
} 

void StartRoutine() { 
    pDeleteFile = (pDeleteFileA)&Hook->OriginalFunction; 
    //the pDeleteFileA is located in "kernel32.dll" 
    InitializeHook(Hook, "kernel32.dll", "DeleteFileA", HookDeleteFileA); 
    InsertHook(Hook);//spawn the hook to the current process 
} 

BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) { 
    switch (dwReason) { 
    case DLL_PROCESS_ATTACH: 
     printf("API Hook Attached!");//notify 
     StartRoutine(); 
     break; 
    case DLL_PROCESS_DETACH: 
     Unhook(Hook);//unhook the hook 
     FreeHook(Hook);//remove the hook from memory 
    } 
} 

int main() { 

    HMODULE hModule = GetModuleHandleA("kernel32.dll"); 

    //The reason code that indicates why the DLL entry-point function is being called. 
    //This parameter can be one of the following values: 
    //DLL_PROCESS_ATTACH 1: 
    //The DLL is being loaded into the virtual address space of the current process 
    //as a result of the process starting up or as a result of a call to LoadLibrary. 
    //DLL_PROCESS_DETACH 0: 
    //The DLL is being unloaded from the virtual address space of the calling process 
    //because it was loaded unsuccessfully or the reference count has reached zero 
    //(the processes has either terminated or called FreeLibrary one time for each time it called LoadLibrary). 
    DWORD dwReason = DLL_PROCESS_ATTACH; 


    //If fdwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads 
    //If fdwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if FreeLibrary has been called or the DLL load 
    //failed and non-NULL if the process is terminating. 
    LPVOID lpReserved = NULL; 

    DllMain(hModule, dwReason, lpReserved); 

    return 0; 
} 
+0

Hängen Sie Ihren eigenen Prozess ein und löschen Sie die Datei im Explorer? –

+0

Ja, das ist mein erster Haken, also wenn ich es falsch mache, könntest du mir einen Rat geben? – Nikolaj

+0

Ja, das wird nicht funktionieren. Sie haben DeleteFileA für Ihren eigenen Prozess angehängt, sodass der Explorer selbst diese DLL geladen haben sollte, was natürlich nicht passieren wird. Was passiert mit DllMain in main() exe Einstiegspunkt? – bunglehead

Antwort

3

Jeder Prozess hat seinen eigenen Adressraum.

Jeder Prozess lädt seine DLLs separat und verfügt über separaten Speicher. Wenn Sie also versuchen, Speicher zu überschreiben, überschreiben Sie nur eine Kopie der DLL, die in Ihren Prozess geladen wird. Dies geschieht aus Stabilitäts- und Sicherheitsgründen.

Um Speicher zu schreiben und Code in einem anderen Prozess auszuführen - Sie müssen DLL Injection verwenden, Wiki hat einen guten Überblick über Szenarien und Methoden.

Sie müssen also Ihren Code in DLL, dann laden Sie diese DLL in Zielprozess. Dann überschreibt Ihre DLL in ihrem DLLMain die Funktion für diesen Prozess (den Hook-Code). Es bedeutet auch, dass der Hook-Code im Kontext des Hooked-Prozesses ausgeführt wird, sodass MessageBox oder printf möglicherweise nicht wie erwartet funktioniert.

Ich empfehle auch, zweiten PC mit Remote-Debug oder VM zu verwenden, da Hooking-System-Prozesse Instabilität verursachen können.

Edit: einige weitere Hinweise. Sie versuchen, haken DeleteFileA, die ASCII-Version ist und neuere Software wird stattdessen DeleteFileW verwenden.

Edit2: auch können Sie nicht 32-Bit-DLL in 64-Bit-Prozess laden und umgekehrt.