Подключая apis экспортируется dll - PullRequest
0 голосов
/ 25 октября 2018

У меня есть приложение, запущенное другим процессом, который загружает некоторые DLL (с ​​большим количеством экспортируемых функций) и вызывает их через некоторое время после запуска.Так как здесь мы не можем использовать традиционную перехват API (заменяя указатель на функцию) и я не использую trampoline (потому что для получения длины инструкции требуется дизассемблер), я написал код для исправления файла dll, поэтому все экспортируемые функции будутначать с кодов операций «бесконечного перехода»: {0xEB, 0xFE}.

Последовательность действий:

  1. файл DLL исправления
  2. процесс запуска, который в конечном итоге вызоветнаше приложение
  3. открывает дескриптор процесса для нашего приложения
  4. перечисляет потоки, чтобы найти IP-адрес, на котором застрял процесс
  5. , теперь мы можем присоединить отладчик и выполнить один шаг через функцию, или мыможет "пропустить" его

Вот код для "пропуска" функции:

extern "C" void asm_proc();

#define PATCH_SIZE      2

UCHAR g_Patch[PATCH_SIZE] = { 0xEB, 0xFE };

void SkipFunction(FUNCTION_ITEM *func, HANDLE hProcess, HANDLE hThread)
{
    CONTEXT lcContext;
    UCHAR *ReturnAddress;
    UCHAR *TargetAddress;
    UCHAR *BlockAddress;
    DWORD ProcSize;
    UCHAR Ret;

    Ret = 0xC3;
    ProcSize = 14;

    lcContext.ContextFlags = CONTEXT_ALL;
    if (!GetThreadContext(hThread, &lcContext)) DbgRaiseAssertionFailure();

    BlockAddress = (UCHAR*)VirtualAllocEx(hProcess, NULL, sizeof(ReturnAddress) + ProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    TargetAddress = BlockAddress + sizeof(ReturnAddress);

    ReadProcessMemoryEx(hProcess, lcContext.Rsp, (UCHAR*)&ReturnAddress, sizeof(ReturnAddress));
    WriteProcessMemoryEx(hProcess, lcContext.Rsp, (UCHAR*)&TargetAddress, sizeof(TargetAddress));

    WriteProcessMemoryEx(hProcess, (DWORD64)BlockAddress, (UCHAR*)&ReturnAddress, sizeof(ReturnAddress));
    // disable incremental linking to make it work
    WriteProcessMemoryEx(hProcess, (DWORD64)TargetAddress, (UCHAR*)asm_proc, ProcSize);

    WriteProcessMemoryEx(hProcess, func->Rip, func->OriginalBytes, PATCH_SIZE);

    while (TRUE)
    {
        Sleep(100);

        lcContext.ContextFlags = CONTEXT_ALL;
        if (!GetThreadContext(hThread, &lcContext)) DbgRaiseAssertionFailure();

        if (lcContext.Rip == (DWORD64)(TargetAddress + 12)) break;
    }

    WriteProcessMemoryEx(hProcess, func->Rip, g_Patch, PATCH_SIZE);

    WriteProcessMemoryEx(hProcess, (DWORD64)(TargetAddress + 12), &Ret, sizeof(Ret));

    VirtualFreeEx(hProcess, BlockAddress, 0, MEM_RELEASE);
}

И asm_proc код функции:

PUBLIC asm_proc

.code

asm_proc PROC
    call $+5
    pop rcx
    sub rcx, 13
    push qword ptr [rcx]
    jmp $
asm_proc ENDP

END

func-> Rip содержит ip-адрес исправленной функции func-> OriginalBytes содержит байты исходной функции в том виде, в каком они появились в исходном файле dll

В основном мы выделяемпамяти с VirtualAllocEx, скопируйте наш код и оригинальный адрес возврата, подставьте адрес возврата в стек и введите бесконечный цикл, чтобы мы могли снова исправить функцию.Этот подход должен работать для однопотокового перехвата (мне не нужно обрабатывать несколько потоков).

Однако иногда приложение просто падает, когда мы «пропускаем» функцию, и я не понимаю, почему это происходит.Что вы можете сказать по этому поводу?Что здесь не так?Спасибо.

...