使用 API 挂钩 "Access Violation writing location 0x0000000000" 的反 dll 注入

Anti dll Injection with API Hooking "Access Violation writing location 0x0000000000"

当在我的程序中调用 LdrLoadDll api 时,我正在使用 JMP 指令技术尝试绕行进行反 Dll 注入。我找到了一个完美运行的 Delphi 代码,但是此代码的 VC++ 2013 版本因

而崩溃

"Access Violation writing location 0x0000000000"

如下所示。

那么,我该如何解决这个麻烦呢?有人可以帮我吗?

提前致谢。

Delphi版本:

procedure hook(target, newfunc:pointer); 
var 
  jmpto:dword; 
    OldProtect: Cardinal; // old protect in memory 
begin 
  jmpto:=dword(newfunc)-dword(target)-5; 
  VirtualProtect(target, 5, PAGE_EXECUTE_READWRITE, @OldProtect); 
  pbyte(target)^:=$e9; 
  pdword(dword(target)+1)^:=jmpto; 
end; 

procedure myLdrLoadDll(PathToFile:PAnsiChar; Flags:variant; ModuleFileName:PAnsiChar; var ModuleHandle:THandle); 
begin 
  MessageBox(0, 'I have blocked your attempt to inject a dll file!!', 'WARNING!', MB_OK); 
  ModuleHandle:=0; 
end; 

procedure Main; 
begin 
Hook(GetProcAddress(GetModuleHandle('ntdll.dll'), 'LdrLoadDll'), @myLdrLoadDll); 
end; 

begin 
end.

正在尝试翻译 VC++ 2013 版:

 BOOL TrampolineAPI(HMODULE hModule, LPCWSTR DllName, LPCSTR ProcName, DWORD dwReplaced)
    {
        DWORD dwReturn;
        DWORD dwOldProtect;
        DWORD dwAddressToHook = (DWORD)GetProcAddress(GetModuleHandle(DllName), ProcName);
        BYTE *pbTargetCode = (BYTE *)dwAddressToHook;
        BYTE *pbReplaced = (BYTE *)dwReplaced;
        VirtualProtect((LPVOID)dwAddressToHook, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        *pbTargetCode++ = 0xE9;   // My trouble is here
        *((signed int*)(pbTargetCode)) = pbReplaced - (pbTargetCode + 4);
        VirtualProtect((LPVOID)dwAddressToHook, 5, PAGE_EXECUTE, &dwOldProtect);
        dwReturn = dwAddressToHook + 5;
        FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
        return TRUE;
    }

    void WINAPI Replaced(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
    {
        printf("Invasion!!");
    }



    int _tmain(int argc, _TCHAR* argv[])
    {

        while (true)
        {
 TrampolineAPI(GetModuleHandle(0), (LPCWSTR)"ntdll.DLL","LdrLoadDLL"(DWORD)Replaced);


        }


        return 0;
    }

您遇到的至少一个问题是 ANSI 和 Unicode 字符串的混合。

在 Win32 中,您会发现两种类型的编码 - Unicode(2 字节字符)和 ANSI(1 字节字符)。您将遇到的 ANSI 字符串类型是 LPSTRLPCSTR 等。宽字符 Unicode 类型是 LPWSTRLPCWSTR

Win32 中还有两种类型的函数 - 例如,GetModuleHandleAGetModuleHandleW。确定使用哪一个的方法很简单:

#ifdef UNICODE
#define GetModuleHandle GetModuleHandleW
#else
#define GetModuleHandle GetModuleHandleA
#endif //!UNICODE

在您的特定情况下,您将使用 ANSI 编码的字符串常量转换为宽字符 Unicode 字符串。这是未定义的行为。将主函数中的 TrampolineAPI(...); 更改为以下内容:

TrampolineAPI(GetModuleHandle(0), L"ntdll.DLL", "LdrLoadDLL", (DWORD)Replaced);

L"ntdll.DLL" 是定义宽字符串常量的方式。这也避免了类型转换。

我还建议在整个程序中使用相同的字符串编码。这将要求您还将 TrampolineAPI 的签名更改为

BOOL TrampolineAPI(HMODULE hModule, LPCWSTR DllName, LPCWSTR ProcName, DWORD dwReplaced) { ... }

并将main中的调用更改为

TrampolineAPI(GetModuleHandle(0), L"ntdll.DLL", L"LdrLoadDLL", (DWORD)Replaced);