Проблемы Delphi при преобразовании подпрограмм ловушки EAT VirtualProtect из C в Delphi - PullRequest
3 голосов
/ 28 февраля 2012

Я пытаюсь преобразовать этот код, пришедший с форума 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, в частности в «functions» var.

Это мой НЕПРАВИЛЬНЫЙ код, преобразованный в Delphi:

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

Как я могу это исправить?

Ответы [ 3 ]

4 голосов
/ 28 февраля 2012

Вы можете воспользоваться тем, что пишете в массив 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 th в массиве. Когда каждая итерация выполнена, inc(functions) перемещает указатель на следующий элемент, готовый к следующей итерации.

Я также исправил ваш for цикл. В вашем Delphi-коде вы выполняете одну итерацию слишком много.

1 голос
/ 28 февраля 2012

Пожалуйста, обратитесь к этой странице под названием Win32 CodeHook - библиотека с открытым исходным кодом для перехвата двоичного кода и перенаправления для Win32 Delphi и C ++ .

Вы можете найти исходный код устройства CodeHookIntf.pas здесь .

DelphiMVP представляет собой демонстрационный пример с использованием CHook.dll .

Я использовал Emballo и DelphiMVP с Delphi XE: это работает!

Уведомление Магно Мачадо Автор Emballo является членом SO.

0 голосов
/ 28 февраля 2012

Иногда лучший способ решить проблему - это посмотреть, что вы пытаетесь делать в C ++, и найти существующую библиотеку (уже преобразованную в Delphi), которая делает то, что вам нужно.

Например, виды перехвата, которые вы пытаетесь сделать здесь, уже сделаны MadCodeHook библиотеками, которые предоставляются Madshi здесь. Теперь они доступны только на коммерческой основе, потому что они очень мощные, и он не хочет включать вредоносное ПО.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...