简体   繁体   English

x86 asm访问并编辑__declspec(裸)函数中的stdcall函数参数

[英]x86 asm access and edit stdcall function argument in a __declspec(naked) function

I made a WOW64 syscall hook for the `NtCreateSection` function using the following code: 我使用以下代码为`NtCreateSection`函数创建了一个WOW64系统调用钩子:

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

The code works fine until I change the hooked function to this 代码工作正常,直到我将钩子函数更改为此

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
    }
}

The problem in my code is that the pushad instruction messes with the esp therefore I can't access the stack anymore and if I don't use pushad/popap the app crashes since I'm messing up with the stack then jumping to the real function address. 我的代码中的问题是pushad指令与esp混淆因此我不能再访问堆栈了如果我不使用pushad/popap应用程序崩溃,因为我搞乱堆栈然后跳转到真实功能地址。 The argument I wanna access and change is the 6th argument of NtCreateSection function . 我想要访问和更改的参数是NtCreateSection 函数的第6个参数。

pushad does not prevent you from accessing the stack. pushad不会阻止您访问堆栈。 pushad pushes 32 bytes (8 registers, 4 bytes each) into the stack, hence, any offset after pushad should be corrected by adding 32. pushad将32个字节(8个寄存器,每个4个字节)压入堆栈,因此, pushad之后的任何偏移都应该通过添加32来纠正。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM