0

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

“访问冲突写入位置 0x0000000000”

如下所示。

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

提前致谢。

德尔福版本:

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;
    }
4

1 回答 1

1

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

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

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

#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);
于 2015-10-26T19:26:31.543 回答