Доступ к x86 asm и редактирование аргумента функции stdcall в функции __declspec (naked) - PullRequest
3 голосов
/ 15 июня 2019

Я сделал хук системного вызова WOW64 для функции `NtCreateSection`, используя следующий код:

#include "Funcs.h"
#include <cstdio>
#include <Windows.h>

const int PAGE_SIZE = 0x1000;
const int SYSCALL_INTERCEPT = 0x4A;
const int NUM_WOW64_BYTES = 0x9;

using pNtCreateSection =
NTSTATUS (NTAPI*)(PHANDLE SectionHandle, ULONG DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes,
                  PLARGE_INTEGER MaximumSize, ULONG PageAttributess, ULONG SectionAttributes, HANDLE FileHandle);
pNtCreateSection NtCreateSection = nullptr;

DWORD_PTR dwWow64Address = 0;
LPVOID lpJmpRealloc = nullptr;
ULONG SectionAttributes;

void __declspec(naked) NtCreateSectionHook()
{
    __asm
    {
        pushad
    }

    fprintf(stderr, "NtCreateSectionHook called !\n");

    __asm
    {
        popad
        jmp lpJmpRealloc
    }
}

DWORD_PTR __declspec(naked) GetWow64Address()
{
    __asm
    {
        mov eax, dword ptr fs:[0xC0]
        ret
    }
}

void __declspec(naked) Wow64Trampoline()
{
    __asm
    {
        cmp eax, SYSCALL_INTERCEPT
        jz NtCreateSectionHook
        jmp lpJmpRealloc
    }
}

LPVOID CreateNewJump(const DWORD_PTR dwWow64Address)
{
    lpJmpRealloc = VirtualAlloc(nullptr, PAGE_SIZE, MEM_RESERVE | MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);

    (void)memcpy(lpJmpRealloc, (const void *)dwWow64Address, NUM_WOW64_BYTES);

    return lpJmpRealloc;
}

void EnableWow64Redirect(const DWORD_PTR dwWow64Address, const LPVOID lpNewJumpLocation)
{
    unsigned char trampolineBytes[] =
    {
        0x68, 0xDD, 0xCC, 0xBB, 0xAA,       /*push 0xAABBCCDD*/
        0xC3,                               /*ret*/
        0xCC, 0xCC, 0xCC                    /*padding*/
    };

    memcpy(&trampolineBytes[1], &lpNewJumpLocation, sizeof(DWORD_PTR));
    WriteJump(dwWow64Address, trampolineBytes, sizeof trampolineBytes);
}

void WriteJump(const DWORD_PTR dwWow64Address, const void *pBuffer, size_t ulSize)
{
    DWORD dwOldProtect = 0;
    (void)VirtualProtect(reinterpret_cast<LPVOID>(dwWow64Address), PAGE_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    (void)memcpy(reinterpret_cast<void *>(dwWow64Address), pBuffer, ulSize);
    (void)VirtualProtect(reinterpret_cast<LPVOID>(dwWow64Address), PAGE_SIZE, dwOldProtect, &dwOldProtect);
}

int main(int argc, char *argv[])
{
    const auto hModule = GetModuleHandle(L"ntdll.dll");
    NtCreateSection = reinterpret_cast<pNtCreateSection>(GetProcAddress(hModule, "NtCreateSection"));

    dwWow64Address = GetWow64Address();

    const auto lpNewJumpLocation = CreateNewJump(dwWow64Address);
    EnableWow64Redirect(dwWow64Address, static_cast<LPVOID>(Wow64Trampoline));

    //Test syscall
    HANDLE hSection;
    NtCreateSection(&hSection, SECTION_ALL_ACCESS, nullptr, nullptr, PAGE_EXECUTE_READWRITE, SEC_COMMIT | SEC_NOCHANGE, nullptr);

    getchar();

    return 0;
}

Код работает нормально, пока я не изменю подключенную функцию на эту

void __declspec(naked) NtCreateSectionHook()
{
    __asm
    {
        pushad
        mov eax, [esp + 28]
        mov SectionAttributes, eax
    }

    fprintf(stderr, "NtCreateSectionHook called !\n");

    if ((SectionAttributes & SEC_NOCHANGE) != 0)
    {
        fprintf(stderr, "SEC_NOCHANGE found !\n");
    }

    __asm
    {
        popad
        jmp lpJmpRealloc
    }
}

Проблема в моем коде состоит в том, что инструкция pushad портится с esp, поэтому я больше не могу получить доступ к стеку, и если я не использую pushad/popap, приложение вылетает, так как явозиться со стеком, а затем перейти к реальному адресу функции.Аргумент, который я хочу получить и изменить, является шестым аргументом NtCreateSection function .

1 Ответ

3 голосов
/ 15 июня 2019

pushad не мешает вам получить доступ к стеку. pushad помещает в стек 32 байта (8 регистров по 4 байта в каждом), следовательно, любое смещение после pushad должно быть исправлено путем добавления 32.

...