[英]x86 asm access and edit stdcall function argument in a __declspec(naked) function
我使用以下代碼為`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;
}
代碼工作正常,直到我將鈎子函數更改為此
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
函數的第6個參數。
pushad
不會阻止您訪問堆棧。 pushad
將32個字節(8個寄存器,每個4個字節)壓入堆棧,因此, pushad
之后的任何偏移都應該通過添加32來糾正。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.