问题
I'm trying to convert this code which came from CHook forum posting this code which does EAT hooking:
#include <Windows.h>
#include <Psapi.h>
#include <string>
#if PSAPI_VERSION == 1
#pragma comment(lib, "Psapi.lib")
#endif
template <typename DestType, typename SrcType>
DestType* ByteOffset(SrcType* ptr, ptrdiff_t offset)
{
return reinterpret_cast<DestType*>(reinterpret_cast<unsigned char*>(ptr) + offset);
}
bool eat_hook(void* old_function, void* new_function)
{
HMODULE hModule;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)old_function, &hModule);
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS NtHeader = ByteOffset<IMAGE_NT_HEADERS>(DosHeader, DosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != NtHeader->Signature)
{
MessageBox(0, "Bad NT header signature", "Error", 0);
return false;
}
PIMAGE_EXPORT_DIRECTORY ExportDirectory = ByteOffset<IMAGE_EXPORT_DIRECTORY>(DosHeader,
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
DWORD* functions = ByteOffset<DWORD>(DosHeader, ExportDirectory->AddressOfFunctions);
for (size_t i = 0; i < ExportDirectory->NumberOfFunctions; ++i)
{
if (functions[i] == (DWORD)old_function - (DWORD)hModule)
{
DWORD oldProtection;
if (!VirtualProtect(functions + i, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &oldProtection))
{
MessageBox(0, "VirtualProtect failed", "Error", 0);
return false;
}
functions[i] = reinterpret_cast<DWORD>(new_function) - reinterpret_cast<DWORD>(DosHeader);
if (!VirtualProtect(functions + i, sizeof(DWORD), oldProtection, &oldProtection))
{
MessageBox(0, "VirtualProtect failed", "Error", 0);
return false;
}
return true;
}
}
return false;
}
bool iat_hook(void* old_function, void* new_function)
{
HMODULE hModule;
DWORD sizeNeeded;
if (0 == EnumProcessModules(GetCurrentProcess(), &hModule, sizeof(hModule), &sizeNeeded))
{
MessageBox(0, "EnumProcessModules failed", "Error", 0);
return false;
}
PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS NtHeader = ByteOffset<IMAGE_NT_HEADERS>(DosHeader, DosHeader->e_lfanew);
if (IMAGE_NT_SIGNATURE != NtHeader->Signature)
{
MessageBox(0, "Bad NT header signature", "Error", 0);
return false;
}
PIMAGE_IMPORT_DESCRIPTOR ImportDirectory = ByteOffset<IMAGE_IMPORT_DESCRIPTOR>(DosHeader,
NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (size_t i = 0; ImportDirectory[i].Characteristics; ++i)
{
PIMAGE_THUNK_DATA thunk = ByteOffset<IMAGE_THUNK_DATA>(hModule, ImportDirectory[i].FirstThunk);
PIMAGE_THUNK_DATA origThunk = ByteOffset<IMAGE_THUNK_DATA>(hModule, ImportDirectory[i].OriginalFirstThunk);
for (; origThunk->u1.Function; origThunk++, thunk++)
{
if (thunk->u1.Function == (DWORD)old_function)
{
DWORD oldProtection;
if (!VirtualProtect(&thunk->u1.Function, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &oldProtection))
{
MessageBox(0, "VirtualProtect failed", "Error", 0);
return false;
}
thunk->u1.Function = reinterpret_cast<DWORD>(new_function);
if (!VirtualProtect(&thunk->u1.Function, sizeof(DWORD), oldProtection, &oldProtection))
{
MessageBox(0, "VirtualProtect failed", "Error", 0);
return false;
}
return true;
}
}
}
return false;
}
bool hook(void* old_function, void* new_function)
{
return eat_hook(old_function, new_function) && iat_hook(old_function, new_function);
}
From c++ to Delphi, but I'm with problems at var declarations, specifically the "functions" var.
This is my Delphi-converted INCOMPLETE code:
function eat_hook(old_function, new_function:pointer):boolean;
var
Module: HMODULE;
DosHeader: PImageDosHeader;
NtHeaders: PImageNtHeaders;
ExportDirectory: PImageExportDirectory;
functions: PDWORD;
i: size_t;
oldProtection: DWORD;
begin
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, pointer(old_function), Module);
DosHeader := PImageDosHeader(Module);
NTHeaders := PImageNtHeaders(DWORD(DOSHeader) + DWORD(DOSHeader^._lfanew));
if IMAGE_NT_SIGNATURE <> NtHeaders.Signature then begin
MessageBox(0, 'Bad NT header signature', 'Error', 0);
exit;
end;
ExportDirectory := PImageExportDirectory(PAnsiChar(DosHeader) + NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
functions := PDWORD(PAnsiChar(DosHeader)+dword(ExportDirectory.AddressOfFunctions));
for i:=0 to ExportDirectory.NumberOfFunctions do begin
if not VirtualProtect(functions, sizeof(dword), PAGE_EXECUTE_READWRITE, @oldProtection) then begin
MessageBox(0, 'VirtualProtect failed', 'Error', 0);
exit;
end;
functions[i] := DWORD(new_function) - DWORD(DosHeader);
if not VirtualProtect(pointer(functions), sizeof(dword), oldProtection, @oldProtection) then begin
MessageBox(0, 'VirtualProtect failed', 'Error', 0);
exit;
end;
end;
end;
The line which attempts to assign to functions[i]
results in a compilation error:
[DCC Error]: E2016 Array type required
How can I fix this?
回答1:
You can take advantage of the fact that you are writing to the array functions
in sequential order and increment the pointer rather than use array indexing.
functions := PDWORD(PAnsiChar(DosHeader)+dword(ExportDirectory.AddressOfFunctions));
for i := 0 to ExportDirectory.NumberOfFunctions-1 do begin
if not VirtualProtect(functions, sizeof(dword), PAGE_EXECUTE_READWRITE, @oldProtection) then begin
MessageBox(0, 'VirtualProtect failed', 'Error', 0);
exit;
end;
functions^ := DWORD(new_function) - DWORD(DosHeader);
if not VirtualProtect(functions, sizeof(dword), oldProtection, @oldProtection) then begin
MessageBox(0, 'VirtualProtect failed', 'Error', 0);
exit;
end;
inc(functions);
end;
The trick here is that each time round the loop functions
points to the ith item in the array. When each iteration is done the inc(functions)
advances the pointer on to the next item, ready for the next iteration.
I also corrected your for
loop. In your Delphi code you performing one iteration too many.
回答2:
Please refer to this page entitled Win32 CodeHook - an open source library for binary code hook and redirect for Win32 Delphi and C++.
You can find the source code of the unit CodeHookIntf.pas here.
DelphiMVP is an sample demo using CHook.dll.
I have harnessed Emballo and DelphiMVP with Delphi XE: it works!
Notice Magno Machado the author of Emballo is a SO member.
回答3:
Sometimes the best way to approach the problem is to actually look at what you're trying to do in C++ and find the existing library (already converted to Delphi) that does what you need.
For example, the kinds of hooking you're trying to do here, are already done by MadCodeHook
libraries, which are provided by Madshi here. They are now only available commercially, because they are very powerful, and he doesn't want to enable malware.
来源:https://stackoverflow.com/questions/9484319/delphi-problems-converting-virtualprotect-eat-hook-routines-from-c-to-delphi