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



我使用JMP指令技术,当LdrLoadDll api在我的程序中被调用时,尝试绕道进行反dll注入。我发现一个Delphi代码,工作完美,但这个vc++ 2013版本的这个代码,崩溃与

"访问违规写入位置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);

相关内容

  • 没有找到相关文章

最新更新