簡體   English   中英

Delphi將VirtualProtect EAT鈎子例程從C轉換為Delphi的問題

[英]Delphi problems converting VirtualProtect EAT hook routines from C to Delphi

我正在嘗試轉換這個來自CHook論壇的代碼,發布這個EAT掛鈎的代碼:

#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);
}

從c ++到Delphi,但我在var聲明中遇到問題,特別是“函數”var。

這是我的Delphi轉換的INCOMPLETE代碼:

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;

嘗試分配給functions[i]導致編譯錯誤:

[DCC Error]: E2016 Array type required

我怎樣才能解決這個問題?

您可以利用以下順序寫入數組functions並增加指針而不是使用數組索引。

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;

這里的技巧是每次循環循環functions指向數組中的 i項。 當每次迭代完成時, inc(functions)將指針前進到下一個項目,為下一次迭代做好准備。

我還糾正了你的for循環。 在Delphi代碼中,執行一次迭代太多了。

請參閱這個名為Win32 CodeHook的頁面- 一個用於二進制代碼鈎子和Win32 Delphi和C ++重定向的開源庫

您可以在此處找到CodeHookIntf.pas單元的源代碼。

DelphiMVP是一個使用CHook.dll的示例演示。

我用Delphi XE開發了Emballo和DelphiMVP:它有效!

注意Emballo的作者Magno Machado是SO成員。

有時,解決問題的最佳方法是實際查看您在C ++中嘗試做的事情,並找到滿足您需求的現有庫(已經轉換為Delphi)。

例如,你在這里嘗試做的掛鈎類型已經由MadCodeHook庫完成, MadCodeHook庫由Madshi在這里提供。 它們現在只能在商業上使用,因為它們非常強大,並且他不想啟用惡意軟件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM