I'm using the JMP instruction tecnique for try make a Anti-Dll Injection with detour when LdrLoadDll api is called inside my program. I found a Delphi code that works perfectly, but this VC++ 2013 version for this code, crashes with a
"Access Violation writing location 0x0000000000"
with showed below.
So, how I can solve this trouble? Someone can help me please?
Thanks in advance.
Delphi version:
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.
Trying translate for VC++ 2013 version:
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;
}
At least one problem you are having is a mix between ANSI and Unicode strings.
In Win32, there are two types of encodings you'll find - Unicode (2-byte characters) and ANSI (1-byte characters). String types you'll encounter for ANSI are LPSTR
, LPCSTR
, etc. Wide character Unicode types are LPWSTR
, LPCWSTR
, etc.
There are also two types of functions in Win32 - for instance, GetModuleHandleA
, and GetModuleHandleW
. The way you determine which one is used is easy:
#ifdef UNICODE
#define GetModuleHandle GetModuleHandleW
#else
#define GetModuleHandle GetModuleHandleA
#endif //!UNICODE
In your particular case, you are casting a string constant with ANSI encoding to a wide-character Unicode string. This is undefined behavior. Change TrampolineAPI(...);
in your main function to the following:
TrampolineAPI(GetModuleHandle(0), L"ntdll.DLL", "LdrLoadDLL", (DWORD)Replaced);
The L"ntdll.DLL"
is how you define a wide-character string constant. This also avoids the typecast.
I would also recommend using the same string encoding throughout your program. This would require you to also change the signature of TrampolineAPI to
BOOL TrampolineAPI(HMODULE hModule, LPCWSTR DllName, LPCWSTR ProcName, DWORD dwReplaced) { ... }
And change the call in main to
TrampolineAPI(GetModuleHandle(0), L"ntdll.DLL", L"LdrLoadDLL", (DWORD)Replaced);