-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
在模拟X86指令时发生的,我找不到问题所在,希望您能帮助我,谢谢!
下面是我的代码:
DWORD WINAPI EmulationThreadProc(LPVOID lpParameter)
{
int callvm_count = 0, callapi_count = 0;
int callvm_total = 0, callapi_total = 0;
bool ret = uc_arch_supported(UC_ARCH_X86);
if (!ret)
{
return 0;
}
uc_engine* huc;
uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &huc);
if (err != UC_ERR_OK) {
MessageBoxA(hWNd, "初始化Unicorn失败", "", NULL);
return 0;
}
MapProcessMemory(PID, huc);
SetupInitialRegisters(huc, PID);
CallContext ctx;
uc_reg_read(huc, UC_X86_REG_EAX, &ctx.pre_ctx.eax);
uc_reg_read(huc, UC_X86_REG_EBX, &ctx.pre_ctx.ebx);
uc_reg_read(huc, UC_X86_REG_ECX, &ctx.pre_ctx.ecx);
uc_reg_read(huc, UC_X86_REG_EDX, &ctx.pre_ctx.edx);
uc_reg_read(huc, UC_X86_REG_ESI, &ctx.pre_ctx.esi);
uc_reg_read(huc, UC_X86_REG_EDI, &ctx.pre_ctx.edi);
uc_reg_read(huc, UC_X86_REG_EBP, &ctx.pre_ctx.ebp);
//uc_reg_read(huc, UC_X86_REG_ESP, &ctx.pre_ctx.esp);
//uc_reg_read(huc, UC_X86_REG_EFLAGS, &ctx.pre_ctx.EFlags);
uc_hook ret_hook;
uc_hook_add(huc, &ret_hook, UC_HOOK_CODE, (void*)VmRetHook, &ctx, 1, 0);
auto RunSimulation = [&](uint32_t call_addr) {
uc_reg_write(huc, UC_X86_REG_EAX, &ctx.pre_ctx.eax);
uc_reg_write(huc, UC_X86_REG_EBX, &ctx.pre_ctx.ebx);
uc_reg_write(huc, UC_X86_REG_ECX, &ctx.pre_ctx.ecx);
uc_reg_write(huc, UC_X86_REG_EDX, &ctx.pre_ctx.edx);
uc_reg_write(huc, UC_X86_REG_ESI, &ctx.pre_ctx.esi);
uc_reg_write(huc, UC_X86_REG_EDI, &ctx.pre_ctx.edi);
uc_reg_write(huc, UC_X86_REG_EBP, &ctx.pre_ctx.ebp);
//uc_reg_write(huc, UC_X86_REG_ESP, &ctx.pre_ctx.esp);
//uc_reg_write(huc, UC_X86_REG_EFLAGS, &ctx.pre_ctx.EFlags);
ctx.call_addr = call_addr;
uc_reg_write(huc, UC_X86_REG_EIP, &call_addr);
err = uc_emu_start(huc, call_addr, 0, 0, 0);
if (err != UC_ERR_OK) {
CString log;
const char* err_str = uc_strerror(err);
uint32_t current_eip;
uc_reg_read(huc, UC_X86_REG_EIP, ¤t_eip);
uint32_t esp_value;
uc_reg_read(huc, UC_X86_REG_ESP, &esp_value);
log.Format(_T("模拟失败 @ 0x%08X:\n")
_T(" 错误: %hs (代码: 0x%X)\n")
_T(" 当前EIP: 0x%08X\n")
_T(" ESP: 0x%08X\n"),
call_addr,
err_str ? err_str : "未知错误",
err,
current_eip,
esp_value);
OutputDebugString(log);
}
};
callvm_total = callvm.size();
for (uint32_t call_addr : callvm) {
RunSimulation(call_addr);
callvm_count++;
}
callapi_total = callapi.size();
for (uint32_t call_addr : callapi) {
RunSimulation(call_addr);
callapi_count++;
}
CString log;
log.Format(_T("处理完成: callvm=%d/%d, callapi=%d/%d, 丢失=%d"),
callvm_count, callvm_total,
callapi_count, callapi_total,
(callvm_total + callapi_total) - (callvm_count + callapi_count));
AddLogEntry(log);
uc_hook_del(huc, ret_hook);
uc_close(huc);
MessageBoxA(hWNd,"分析完成","",NULL);
return 0;
}
void SetupInitialRegisters(uc_engine* uc, DWORD pid) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) {
return;
}
HANDLE hThread = GetMainThreadHandle(pid);
if (!hThread) {
CloseHandle(hProcess);
return;
}
CONTEXT ctx = GetThreadContext(hThread);
static _NtQueryInformationThread NtQueryInformationThread = NULL;
static bool initialized = false;
if (!initialized) {
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll) {
NtQueryInformationThread = (_NtQueryInformationThread)GetProcAddress(ntdll, "NtQueryInformationThread");
}
initialized = true;
}
THREAD_BASIC_INFORMATION tbi;
ULONG len;
NTSTATUS status = NtQueryInformationThread(
hThread,
(THREADINFOCLASS)0,
&tbi,
sizeof(tbi),
&len
);
//uc_reg_write(uc, UC_X86_REG_FS_BASE, &(uint32_t)tbi.TebBaseAddress); //Whether it is needed ?
uc_reg_write(uc, UC_X86_REG_EAX, &ctx.Eax);
uc_reg_write(uc, UC_X86_REG_EBX, &ctx.Ebx);
uc_reg_write(uc, UC_X86_REG_ECX, &ctx.Ecx);
uc_reg_write(uc, UC_X86_REG_EDX, &ctx.Edx);
uc_reg_write(uc, UC_X86_REG_ESI, &ctx.Esi);
uc_reg_write(uc, UC_X86_REG_EDI, &ctx.Edi);
uc_reg_write(uc, UC_X86_REG_EBP, &ctx.Ebp);
uc_reg_write(uc, UC_X86_REG_ESP, &ctx.Esp);
uint32_t cs = ctx.SegCs;
uint32_t ds = ctx.SegDs;
uint32_t es = ctx.SegEs;
uint32_t fs = ctx.SegFs;
uint32_t gs = ctx.SegGs;
uint32_t ss = ctx.SegSs;
uc_reg_write(uc, UC_X86_REG_CS, &cs);
uc_reg_write(uc, UC_X86_REG_DS, &ds);
uc_reg_write(uc, UC_X86_REG_ES, &es);
uc_reg_write(uc, UC_X86_REG_FS, &fs);
uc_reg_write(uc, UC_X86_REG_GS, &gs);
uc_reg_write(uc, UC_X86_REG_SS, &ss);
uc_reg_write(uc, UC_X86_REG_EFLAGS, &ctx.EFlags);
uc_reg_write(uc, UC_X86_REG_DR0, &ctx.Dr0);
uc_reg_write(uc, UC_X86_REG_DR1, &ctx.Dr1);
uc_reg_write(uc, UC_X86_REG_DR0, &ctx.Dr2);
uc_reg_write(uc, UC_X86_REG_DR1, &ctx.Dr3);
uc_reg_write(uc, UC_X86_REG_DR0, &ctx.Dr6);
uc_reg_write(uc, UC_X86_REG_DR1, &ctx.Dr7);
// 1. FPU控制和状态寄存器
uc_reg_write(uc, UC_X86_REG_FPCW, &ctx.FloatSave.ControlWord);
uc_reg_write(uc, UC_X86_REG_FPSW, &ctx.FloatSave.StatusWord);
uc_reg_write(uc, UC_X86_REG_FPTAG, &ctx.FloatSave.TagWord);
// 2. 浮点错误相关寄存器
uc_reg_write(uc, UC_X86_REG_FIP, &ctx.FloatSave.ErrorOffset);
uc_reg_write(uc, UC_X86_REG_FCS, &ctx.FloatSave.ErrorSelector);
uc_reg_write(uc, UC_X86_REG_FDP, &ctx.FloatSave.DataOffset);
uc_reg_write(uc, UC_X86_REG_FDS, &ctx.FloatSave.DataSelector);
// 3. 浮点寄存器堆(ST0-ST7)
// 每个寄存器在RegisterArea中占10字节(80位)
if (sizeof(ctx.FloatSave.RegisterArea) == SIZE_OF_80387_REGISTERS) {
uc_reg_write(uc, UC_X86_REG_ST0, &ctx.FloatSave.RegisterArea[0]);
uc_reg_write(uc, UC_X86_REG_ST1, &ctx.FloatSave.RegisterArea[10]);
uc_reg_write(uc, UC_X86_REG_ST2, &ctx.FloatSave.RegisterArea[20]);
uc_reg_write(uc, UC_X86_REG_ST3, &ctx.FloatSave.RegisterArea[30]);
uc_reg_write(uc, UC_X86_REG_ST4, &ctx.FloatSave.RegisterArea[40]);
uc_reg_write(uc, UC_X86_REG_ST5, &ctx.FloatSave.RegisterArea[50]);
uc_reg_write(uc, UC_X86_REG_ST6, &ctx.FloatSave.RegisterArea[60]);
uc_reg_write(uc, UC_X86_REG_ST7, &ctx.FloatSave.RegisterArea[70]);
OutputDebugString(_T("浮点数寄存器堆初始化完成\n"));
}
//const uint32_t STACK_SIZE = 0x50000; // 128KB保守堆栈大小
//uint32_t stack_base = 0x2000000; // 栈底地址(4字节对齐)
//uc_err stack_err = uc_mem_map(uc, stack_base, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE);
//uint32_t esp = stack_base + STACK_SIZE;
//uc_reg_write(uc, UC_X86_REG_ESP, &esp);
CloseHandle(hThread);
CloseHandle(hProcess);
}
void MapProcessMemory(DWORD pid, uc_engine* uc )
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (!hProcess) return;
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
const DWORD PAGE_SIZE = sysInfo.dwPageSize;
const ULONG_PTR PAGE_MASK = ~(ULONG_PTR)(PAGE_SIZE - 1);
MEMORY_BASIC_INFORMATION mbi;
ULONG_PTR address = 0;
const uint32_t NULL_AREA_START = 0x00000000;
const uint32_t NULL_AREA_SIZE = 0x10000; // 64KB
if (uc_mem_map(uc, NULL_AREA_START, NULL_AREA_SIZE, UC_PROT_NONE) == UC_ERR_OK) {
std::vector<uint8_t> zeros(NULL_AREA_SIZE, 0);
uc_mem_write(uc, NULL_AREA_START, zeros.data(), zeros.size());
}
while (VirtualQueryEx(hProcess, (LPCVOID)address, &mbi, sizeof(mbi))) {
ULONG_PTR base = (ULONG_PTR)mbi.BaseAddress;
ULONG_PTR regionStart = base & PAGE_MASK;
ULONG_PTR regionEnd = (base + mbi.RegionSize + PAGE_SIZE - 1) & PAGE_MASK;
size_t regionSize = regionEnd - regionStart;
if (regionSize == 0 ||
mbi.State != MEM_COMMIT ||
(mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS))) {
address = regionEnd;
continue;
}
if (uc_mem_map(uc, regionStart, regionSize, UC_PROT_ALL) == UC_ERR_OK) {
const size_t BLOCK_SIZE = 4096;
std::vector<uint8_t> buffer(BLOCK_SIZE);
for (ULONG_PTR offset = 0; offset < regionSize; offset += BLOCK_SIZE) {
size_t toRead = min(BLOCK_SIZE, regionSize - offset);
if (ReadProcessMemory(hProcess, (LPCVOID)(regionStart + offset),
buffer.data(), toRead, NULL)) {
uc_mem_write(uc, regionStart + offset, buffer.data(), toRead);
}
}
}
address = regionEnd;
}
CloseHandle(hProcess);
}
我直接映射的整个进程空间,寄存器相关是直接在线程上下文中获取的,我不知道是否是模拟环境构建错误,还是我落下了重要的未设置的重点。
下面是vs输出的错误,它会一直发生。
模拟失败 @ 0x004401F2:
错误: Unhandled CPU exception (UC_ERR_EXCEPTION) (代码: 0x15)
当前EIP: 0x00AE0BE3
ESP: 0x0019F83C
模拟失败 @ 0x004AB76D:
错误: Read from non-readable memory (UC_ERR_READ_PROT) (代码: 0xD)
当前EIP: 0x005D9274
ESP: 0x0019EAB8
模拟失败 @ 0x004B28F5:
错误: Invalid memory write (UC_ERR_WRITE_UNMAPPED) (代码: 0x7)
当前EIP: 0x00998342
ESP: 0x0019E6CC
模拟失败 @ 0x004ABA5A:
错误: Read from non-readable memory (UC_ERR_READ_PROT) (代码: 0xD)
当前EIP: 0x005D9274
ESP: 0x0019D1A4
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
0x004330DE 处(位于 AT.exe 中)引发的异常: 0xC0000005: 写入位置 0x08A21000 时发生访问冲突。
................
请帮助我看一看到底是什么原因,谢谢!