【问题标题】:Delphi problems converting VirtualProtect EAT hook routines from C to DelphiDelphi 问题将 VirtualProtect EAT 挂钩例程从 C 转换为 Delphi
【发布时间】:2012-02-28 15:03:09
【问题描述】:

我正在尝试转换来自 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

我该如何解决这个问题?

【问题讨论】:

  • 能否使用C++-builder编译C++代码并创建delphi接口?
  • 我在此承诺反对并投票结束所有“请转换代码”问题。 OP 显示的努力不够。
  • @Warren 我给你一个虚拟的反对票。 paulohr 对 SO 来说是全新的,应该表现出一些懈怠。更重要的是 paulohr 对所有澄清请求做出了很好的回应,并做出了相当大的努力,见证了转换后的 Delphi 代码。我认为我们应该尝试帮助像保罗这样的人。
  • 嗯,我认为这个问题可以通过编辑来挽救。我修正了标题,所以这不是一个纯粹的转换问题,但也许(如果有人帮助他)一个非常有价值的挂钩代码。
  • 这几乎是同一个人昨天提出的问题的一个骗局:stackoverflow.com/questions/9466704/eat-hook-in-delphi

标签: c++ delphi api hook


【解决方案1】:

您可以利用按顺序写入数组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 指向数组中的第ith 项。每次迭代完成后,inc(functions) 会将指针移至下一项,为下一次迭代做好准备。

我还更正了您的 for 循环。在您的 Delphi 代码中,您执行的一次迭代太多了。

【讨论】:

  • 很高兴你努力回答,但我真的认为不应该鼓励 OP(也不应该鼓励他/她之后的 10K 人)只问“convert me dis C++ codez plz kthxbye” .
  • @WarrenP OP 显然在苦苦挣扎,并且对 C++ 没有深入的了解。当然,我们是来帮忙的。至少我已经尝试稍微解释一下代码,您会看到在上一个问题中,我没有转换代码。至少在 OP 尝试并想出一些错误之前。
  • @paulohr 您的for 循环仍然错误。至于代码是否正确,我还没有足够详细地审查它。我只是试图回答直接的问题以及我碰巧发现的任何其他问题。您应该检查并仔细检查代码。
  • 但是 StackOverflow 是否是一个更好的站点,可以包含 800 万左右的永久记录“将此标头转换为 Delphi”?我的感觉是,如果我们要求 OP 重述他们真正的单一问题(你怎么会像这样,但在帕斯卡里呢?)我们会得到更多的信号,更少的噪音,每个人都会赢。
  • @WarrenP 我个人并不真正关心这样的问题是更好还是更坏。我们即将在 SO 上通过 1000 万个帖子。它充满了各种垃圾!我知道 Jeff 和 Joel 有这样的想法,即 SO 将成为圣人智慧的惊人宝库。可能是这样,但它不可避免地总是包含很多这样的 Q。我宁愿只是帮助别人。
【解决方案2】:

请参考标题为Win32 CodeHook - an open source library for binary code hook and redirect for Win32 Delphi and C++的页面。

可以找到单元源代码CodeHookIntf.pashere

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

我已经在 Delphi XE 中使用了 Emballo 和 DelphiMVP:它有效!

通知Magno Machado Emballo 的作者是 SO 成员。

【讨论】:

    【解决方案3】:

    有时解决问题的最佳方法是实际查看您在 C++ 中尝试执行的操作,然后找到满足您需要的现有库(已转换为 Delphi)。

    例如,您在此处尝试执行的钩子类型已经由MadCodeHook 库完成,这些库由Madshi 提供。它们现在只能在商业上使用,因为它们非常强大,而且他不想启用恶意软件。

    【讨论】:

    • MadCodeHook 挂钩 EAT 还是 IAT?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多