update & fix logic bug
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define LOG_LEVEL 0
|
#define LOG_LEVEL 1
|
||||||
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
@@ -164,8 +164,8 @@ class cFixImprot : public peconv::t_function_resolver {
|
|||||||
for (const auto& module : m_sandbox->m_moduleList) {
|
for (const auto& module : m_sandbox->m_moduleList) {
|
||||||
// 检查模块名是否匹配
|
// 检查模块名是否匹配
|
||||||
if (_stricmp(module->name, lib_name) == 0) {
|
if (_stricmp(module->name, lib_name) == 0) {
|
||||||
// 遍历模块的导出函数
|
// 遍历该模块的导出函数
|
||||||
for (const auto& exp : m_sandbox->m_exportFuncDict) {
|
for (const auto& exp : module->export_function) {
|
||||||
// 检查函数名是否匹配
|
// 检查函数名是否匹配
|
||||||
if (strcmp(exp->name, func_name) == 0) {
|
if (strcmp(exp->name, func_name) == 0) {
|
||||||
auto newBase = reinterpret_cast<FARPROC>(
|
auto newBase = reinterpret_cast<FARPROC>(
|
||||||
@@ -177,18 +177,24 @@ class cFixImprot : public peconv::t_function_resolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果没有找到精确匹配的模块名,尝试在所有模块中查找该函数
|
||||||
for (const auto& module : m_sandbox->m_moduleList) {
|
for (const auto& module : m_sandbox->m_moduleList) {
|
||||||
for (const auto& exp : m_sandbox->m_exportFuncDict) {
|
for (const auto& exp : module->export_function) {
|
||||||
// 检查函数名是否匹配
|
// 检查函数名是否匹配
|
||||||
if (strcmp(exp->name, func_name) == 0) {
|
if (strcmp(exp->name, func_name) == 0) {
|
||||||
auto newBase = reinterpret_cast<FARPROC>(
|
auto newBase = reinterpret_cast<FARPROC>(
|
||||||
module->base + exp->function_address);
|
module->base + exp->function_address);
|
||||||
printf("fix import: %s => %llx \n", func_name, newBase);
|
printf("fix import (fallback): %s found in %s => %llx \n",
|
||||||
|
func_name, module->name, newBase);
|
||||||
// 返回在模拟器中的虚拟地址
|
// 返回在模拟器中的虚拟地址
|
||||||
return newBase;
|
return newBase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Warning: Could not resolve import: %s from library: %s\n",
|
||||||
|
func_name, lib_name);
|
||||||
//__debugbreak();
|
//__debugbreak();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -253,16 +259,22 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
m_usedModuleBase = DLL_MODULE_BASE;
|
m_usedModuleBase = DLL_MODULE_BASE;
|
||||||
}
|
}
|
||||||
// 创建新模块
|
// 创建新模块
|
||||||
auto newModule = CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE), moduleBase, moduleBase);
|
auto newModule =
|
||||||
|
CreateModuleInfo(dllName, AlignSize(m_usedModuleBase, PAGE_SIZE),
|
||||||
|
moduleBase, moduleBase);
|
||||||
|
|
||||||
m_usedModuleBase += PAGE_SIZE + newModule->size;
|
m_usedModuleBase += PAGE_SIZE + newModule->size;
|
||||||
m_moduleList.push_back(newModule);
|
m_moduleList.push_back(newModule);
|
||||||
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name,
|
printf("push `%s` module to vm base: %llx vm size: %llx\n", newModule->name,
|
||||||
newModule->base, newModule->size);
|
newModule->base, newModule->size);
|
||||||
uc_mem_map(m_ucEngine, newModule->base, newModule->size,
|
if (uc_mem_map(m_ucEngine, newModule->base, newModule->size,
|
||||||
UC_PROT_READ | UC_PROT_EXEC);
|
UC_PROT_READ | UC_PROT_EXEC) != UC_ERR_OK) {
|
||||||
uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase,
|
throw std::runtime_error("Failed to map module");
|
||||||
newModule->size);
|
}
|
||||||
|
if (uc_mem_write(m_ucEngine, newModule->base, (void*)moduleBase,
|
||||||
|
newModule->size) != UC_ERR_OK) {
|
||||||
|
throw std::runtime_error("Failed to write data to map module");
|
||||||
|
}
|
||||||
if (peconv::relocate_module((BYTE*)moduleBase, newModule->size,
|
if (peconv::relocate_module((BYTE*)moduleBase, newModule->size,
|
||||||
newModule->base) == false) {
|
newModule->base) == false) {
|
||||||
throw std::runtime_error("Failed to relocate module");
|
throw std::runtime_error("Failed to relocate module");
|
||||||
@@ -274,8 +286,8 @@ auto Sandbox::PushModuleToVM(const char* dllName, uint64_t moduleBase) -> void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase, uint64_t realModuleBase,
|
auto Sandbox::CreateModuleInfo(const char* dllName, uint64_t moduleBase,
|
||||||
uint64_t bufferAddress)
|
uint64_t realModuleBase, uint64_t bufferAddress)
|
||||||
-> std::shared_ptr<struct_moudle> {
|
-> std::shared_ptr<struct_moudle> {
|
||||||
// 解析PE头
|
// 解析PE头
|
||||||
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(bufferAddress);
|
auto* dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(bufferAddress);
|
||||||
@@ -574,6 +586,13 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
m_teb32.ProcessEnvironmentBlock = static_cast<ULONG>(m_pebBase);
|
m_teb32.ProcessEnvironmentBlock = static_cast<ULONG>(m_pebBase);
|
||||||
m_teb32.NtTib.StackBase = static_cast<ULONG>(m_stackBase);
|
m_teb32.NtTib.StackBase = static_cast<ULONG>(m_stackBase);
|
||||||
m_teb32.NtTib.StackLimit = static_cast<ULONG>(m_stackSize);
|
m_teb32.NtTib.StackLimit = static_cast<ULONG>(m_stackSize);
|
||||||
|
// 初始化NT_TIB结构的其余部分
|
||||||
|
m_teb32.NtTib.Self =
|
||||||
|
static_cast<ULONG>(m_tebBase); // 关键:设置Self指针指向TEB本身
|
||||||
|
m_teb32.NtTib.ExceptionList = 0xFFFFFFFF; // 初始异常链表指向特殊值
|
||||||
|
m_teb32.NtTib.Version = 0;
|
||||||
|
m_teb32.NtTib.FiberData = 0;
|
||||||
|
m_teb32.NtTib.ArbitraryUserPointer = 0;
|
||||||
|
|
||||||
// 设置堆
|
// 设置堆
|
||||||
m_peb32.ProcessHeap = static_cast<ULONG>(m_heapBase);
|
m_peb32.ProcessHeap = static_cast<ULONG>(m_heapBase);
|
||||||
@@ -591,6 +610,7 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
// 对于32位,我们需要设置FS段寄存器指向TEB
|
// 对于32位,我们需要设置FS段寄存器指向TEB
|
||||||
SegmentSelector fs = {0};
|
SegmentSelector fs = {0};
|
||||||
fs.fields.index = 3;
|
fs.fields.index = 3;
|
||||||
|
// 不需要设置present和dpl,因为SegmentSelector结构体中没有这些字段
|
||||||
uc_reg_write(m_ucEngine, UC_X86_REG_FS, &fs.all);
|
uc_reg_write(m_ucEngine, UC_X86_REG_FS, &fs.all);
|
||||||
|
|
||||||
// 设置FS基址MSR
|
// 设置FS基址MSR
|
||||||
@@ -598,6 +618,19 @@ auto Sandbox::SetupVirtualMachine() -> void {
|
|||||||
msr.rid = static_cast<uint32_t>(Msr::kIa32FsBase);
|
msr.rid = static_cast<uint32_t>(Msr::kIa32FsBase);
|
||||||
msr.value = m_tebBase;
|
msr.value = m_tebBase;
|
||||||
uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr);
|
uc_reg_write(m_ucEngine, UC_X86_REG_MSR, &msr);
|
||||||
|
|
||||||
|
// 确保TEB中关键字段被正确初始化
|
||||||
|
// 特别是FS:18h (0x18)处应该指向自身
|
||||||
|
// 根据Native_Struct.h中X32TEB定义,偏移0x18处是SelfTeb
|
||||||
|
uint32_t self_teb_ptr = static_cast<uint32_t>(m_tebBase);
|
||||||
|
// 在NT_TIB中设置SelfTeb (offset 0x18)
|
||||||
|
uc_mem_write(m_ucEngine, m_tebBase + 0x18, &self_teb_ptr,
|
||||||
|
sizeof(uint32_t));
|
||||||
|
|
||||||
|
// 确保TEB中的ProcessEnvironmentBlock字段指向PEB
|
||||||
|
uint32_t peb_ptr = static_cast<uint32_t>(m_pebBase);
|
||||||
|
// 偏移0x30处是ProcessEnvironmentBlock
|
||||||
|
uc_mem_write(m_ucEngine, m_tebBase + 0x30, &peb_ptr, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
// 映射新的内存区域
|
// 映射新的内存区域
|
||||||
size_t envSize =
|
size_t envSize =
|
||||||
@@ -635,8 +668,8 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
|
|||||||
throw std::runtime_error("Failed to initialize Unicorn");
|
throw std::runtime_error("Failed to initialize Unicorn");
|
||||||
}
|
}
|
||||||
// 一定要确保他是第一个.
|
// 一定要确保他是第一个.
|
||||||
auto newModule =
|
auto newModule = CreateModuleInfo(
|
||||||
CreateModuleInfo("huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase,
|
"huoji.exe", m_peInfo->RecImageBase, m_peInfo->RecImageBase,
|
||||||
reinterpret_cast<uint64_t>(m_peInfo->peBuffer));
|
reinterpret_cast<uint64_t>(m_peInfo->peBuffer));
|
||||||
_ASSERTE(m_moduleList.size() == 0);
|
_ASSERTE(m_moduleList.size() == 0);
|
||||||
m_moduleList.push_back(newModule);
|
m_moduleList.push_back(newModule);
|
||||||
@@ -842,8 +875,8 @@ auto Sandbox::GetEnvString() -> std::vector<wchar_t> {
|
|||||||
L"PROMPT=$P$G",
|
L"PROMPT=$P$G",
|
||||||
L"SystemDrive=C:",
|
L"SystemDrive=C:",
|
||||||
L"SystemRoot=C:\\Windows",
|
L"SystemRoot=C:\\Windows",
|
||||||
L"TEMP=C:\\Users\\User\\AppData\\Local\\Temp",
|
L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
|
||||||
L"TMP=C:\\Users\\User\\AppData\\Local\\Temp",
|
L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
|
||||||
L"USERDOMAIN=DESKTOP",
|
L"USERDOMAIN=DESKTOP",
|
||||||
L"USERNAME=User",
|
L"USERNAME=User",
|
||||||
L"USERPROFILE=C:\\Users\\User",
|
L"USERPROFILE=C:\\Users\\User",
|
||||||
|
|||||||
@@ -235,10 +235,12 @@ class Sandbox {
|
|||||||
auto GetImpFuncDict() -> std::vector<std::shared_ptr<moudle_import>> {
|
auto GetImpFuncDict() -> std::vector<std::shared_ptr<moudle_import>> {
|
||||||
return m_impFuncDict;
|
return m_impFuncDict;
|
||||||
}
|
}
|
||||||
auto GetLastImpRead() -> std::pair<uint64_t, std::shared_ptr<moudle_import>> {
|
auto GetLastImpRead()
|
||||||
|
-> std::pair<uint64_t, std::shared_ptr<moudle_import>> {
|
||||||
return m_lastImpRead;
|
return m_lastImpRead;
|
||||||
}
|
}
|
||||||
auto SetLastImpRead(uint64_t address, std::shared_ptr<moudle_import> imp) -> void {
|
auto SetLastImpRead(uint64_t address, std::shared_ptr<moudle_import> imp)
|
||||||
|
-> void {
|
||||||
m_lastImpRead = {address, imp};
|
m_lastImpRead = {address, imp};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,16 +294,16 @@ class Sandbox {
|
|||||||
L"PROMPT=$P$G",
|
L"PROMPT=$P$G",
|
||||||
L"SystemDrive=C:",
|
L"SystemDrive=C:",
|
||||||
L"SystemRoot=C:\\Windows",
|
L"SystemRoot=C:\\Windows",
|
||||||
L"TEMP=C:\\Users\\User\\AppData\\Local\\Temp",
|
L"TEMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
|
||||||
L"TMP=C:\\Users\\User\\AppData\\Local\\Temp",
|
L"TMP=C:\\Users\\huoji\\AppData\\Local\\Temp",
|
||||||
L"USERDOMAIN=DESKTOP",
|
L"USERDOMAIN=DESKTOP",
|
||||||
L"USERNAME=User",
|
L"USERNAME=User",
|
||||||
L"USERPROFILE=C:\\Users\\User",
|
L"USERPROFILE=C:\\Users\\huoji",
|
||||||
L"windir=C:\\Windows"};
|
L"windir=C:\\Windows"};
|
||||||
auto ResoveImport() -> void;
|
auto ResoveImport() -> void;
|
||||||
auto ResolveImportExports() -> void;
|
auto ResolveImportExports() -> void;
|
||||||
auto CreateModuleInfo(const char* dllName, uint64_t moduleBase, uint64_t realModuleBase,
|
auto CreateModuleInfo(const char* dllName, uint64_t moduleBase,
|
||||||
uint64_t bufferAddress)
|
uint64_t realModuleBase, uint64_t bufferAddress)
|
||||||
-> std::shared_ptr<struct_moudle>;
|
-> std::shared_ptr<struct_moudle>;
|
||||||
auto ResolveExport(uint64_t moduleBase)
|
auto ResolveExport(uint64_t moduleBase)
|
||||||
-> std::vector<std::shared_ptr<moudle_export>>;
|
-> std::vector<std::shared_ptr<moudle_export>>;
|
||||||
@@ -440,3 +442,5 @@ auto Api_FwpmEngineClose0(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
auto Api_TlsFree(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
auto Api_TlsFree(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||||
auto Api_FlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
auto Api_FlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||||
auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||||
|
auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||||
|
auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void;
|
||||||
@@ -1359,6 +1359,9 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
_fakeApi{.func = Api_GetStringTypeW, .paramCount = 4};
|
_fakeApi{.func = Api_GetStringTypeW, .paramCount = 4};
|
||||||
auto FakeApi_LCMapStringW =
|
auto FakeApi_LCMapStringW =
|
||||||
_fakeApi{.func = Api_LCMapStringW, .paramCount = 6};
|
_fakeApi{.func = Api_LCMapStringW, .paramCount = 6};
|
||||||
|
auto FakeApi__initterm_e =
|
||||||
|
_fakeApi{.func = Api__initterm_e, .paramCount = 2};
|
||||||
|
auto FakeApi_getenv = _fakeApi{.func = Api_getenv, .paramCount = 1};
|
||||||
|
|
||||||
api_map = {
|
api_map = {
|
||||||
{"GetSystemTimeAsFileTime",
|
{"GetSystemTimeAsFileTime",
|
||||||
@@ -1492,8 +1495,10 @@ auto Sandbox::InitApiHooks() -> void {
|
|||||||
{"TlsFree", std::make_shared<_fakeApi>(FakeApi_TlsFree)},
|
{"TlsFree", std::make_shared<_fakeApi>(FakeApi_TlsFree)},
|
||||||
{"FlsAlloc", std::make_shared<_fakeApi>(FakeApi_FlsAlloc)},
|
{"FlsAlloc", std::make_shared<_fakeApi>(FakeApi_FlsAlloc)},
|
||||||
{"FlsGetValue", std::make_shared<_fakeApi>(FakeApi_FlsGetValue)},
|
{"FlsGetValue", std::make_shared<_fakeApi>(FakeApi_FlsGetValue)},
|
||||||
|
{"_initterm_e", std::make_shared<_fakeApi>(FakeApi__initterm_e)},
|
||||||
{"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)},
|
{"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)},
|
||||||
{"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)},
|
{"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)},
|
||||||
|
{"getenv", std::make_shared<_fakeApi>(FakeApi_getenv)},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
||||||
@@ -1548,6 +1553,6 @@ auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
printf("ApiName: %s not found\n", ApiName.c_str());
|
printf("ApiName: %s not found\n", ApiName.c_str());
|
||||||
//uc_emu_stop(uc);
|
uc_emu_stop(uc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,7 @@ auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 使用指定长度
|
// 使用指定长度
|
||||||
if (cchWideChar > 0 && cchWideChar <= MAX_PATH) {
|
if (cchWideChar > 0 && cchWideChar <= 4 * 1024) {
|
||||||
srcBuffer.resize(cchWideChar);
|
srcBuffer.resize(cchWideChar);
|
||||||
if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(),
|
if (uc_mem_read(uc, lpWideCharStr, srcBuffer.data(),
|
||||||
cchWideChar * 2) != UC_ERR_OK) {
|
cchWideChar * 2) != UC_ERR_OK) {
|
||||||
@@ -699,7 +699,7 @@ auto Api_WideCharToMultiByte(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
"WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n",
|
"WideLen=%d, MultiStr=%p, MultiLen=%d, Result=%d\n",
|
||||||
CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar,
|
CodePage, dwFlags, (void*)lpWideCharStr, cchWideChar,
|
||||||
(void*)lpMultiByteStr, cbMultiByte, result);
|
(void*)lpMultiByteStr, cbMultiByte, result);
|
||||||
|
printf("[*] WideCharToMultiByte: pre=%s\n", multiByteBuffer.data());
|
||||||
uc_reg_write(uc,
|
uc_reg_write(uc,
|
||||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
&result);
|
&result);
|
||||||
@@ -1338,8 +1338,7 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
if (context->GetPeInfo()->isX64) {
|
if (context->GetPeInfo()->isX64) {
|
||||||
currentThreadHandle =
|
currentThreadHandle =
|
||||||
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
|
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
currentThreadHandle =
|
currentThreadHandle =
|
||||||
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
|
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
|
||||||
}
|
}
|
||||||
@@ -1347,21 +1346,19 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
if (lpCriticalSection != 0) {
|
if (lpCriticalSection != 0) {
|
||||||
if (context->GetPeInfo()->isX64) {
|
if (context->GetPeInfo()->isX64) {
|
||||||
RTL_CRITICAL_SECTION cs;
|
RTL_CRITICAL_SECTION cs;
|
||||||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
uc_mem_read(uc, lpCriticalSection, &cs,
|
||||||
|
sizeof(RTL_CRITICAL_SECTION));
|
||||||
|
|
||||||
// 如果当前线程已经拥有锁,增加递归计数
|
// 如果当前线程已经拥有锁,增加递归计数
|
||||||
if (cs.OwningThread == currentThreadHandle) {
|
if (cs.OwningThread == currentThreadHandle) {
|
||||||
cs.RecursionCount++;
|
cs.RecursionCount++;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 如果没有线程拥有锁,获取它
|
// 如果没有线程拥有锁,获取它
|
||||||
if (cs.LockCount == -1) {
|
if (cs.LockCount == -1) {
|
||||||
cs.OwningThread = currentThreadHandle;
|
cs.OwningThread = currentThreadHandle;
|
||||||
cs.RecursionCount = 1;
|
cs.RecursionCount = 1;
|
||||||
cs.LockCount = 0;
|
cs.LockCount = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
|
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
|
||||||
cs.OwningThread = currentThreadHandle;
|
cs.OwningThread = currentThreadHandle;
|
||||||
cs.RecursionCount = 1;
|
cs.RecursionCount = 1;
|
||||||
@@ -1370,25 +1367,23 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 写回更新后的关键段结构
|
// 写回更新后的关键段结构
|
||||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
|
uc_mem_write(uc, lpCriticalSection, &cs,
|
||||||
}
|
sizeof(RTL_CRITICAL_SECTION));
|
||||||
else {
|
} else {
|
||||||
RTL_CRITICAL_SECTION32 cs;
|
RTL_CRITICAL_SECTION32 cs;
|
||||||
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32));
|
uc_mem_read(uc, lpCriticalSection, &cs,
|
||||||
|
sizeof(RTL_CRITICAL_SECTION32));
|
||||||
|
|
||||||
// 如果当前线程已经拥有锁,增加递归计数
|
// 如果当前线程已经拥有锁,增加递归计数
|
||||||
if (cs.OwningThread == (DWORD)currentThreadHandle) {
|
if (cs.OwningThread == (DWORD)currentThreadHandle) {
|
||||||
cs.RecursionCount++;
|
cs.RecursionCount++;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 如果没有线程拥有锁,获取它
|
// 如果没有线程拥有锁,获取它
|
||||||
if (cs.LockCount == -1) {
|
if (cs.LockCount == -1) {
|
||||||
cs.OwningThread = (DWORD)currentThreadHandle;
|
cs.OwningThread = (DWORD)currentThreadHandle;
|
||||||
cs.RecursionCount = 1;
|
cs.RecursionCount = 1;
|
||||||
cs.LockCount = 0;
|
cs.LockCount = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
|
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
|
||||||
cs.OwningThread = (DWORD)currentThreadHandle;
|
cs.OwningThread = (DWORD)currentThreadHandle;
|
||||||
cs.RecursionCount = 1;
|
cs.RecursionCount = 1;
|
||||||
@@ -1397,7 +1392,8 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 写回更新后的关键段结构
|
// 写回更新后的关键段结构
|
||||||
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32));
|
uc_mem_write(uc, lpCriticalSection, &cs,
|
||||||
|
sizeof(RTL_CRITICAL_SECTION32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,7 +1471,6 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lpStartupInfo != 0) {
|
if (lpStartupInfo != 0) {
|
||||||
|
|
||||||
if (context->GetPeInfo()->isX64) {
|
if (context->GetPeInfo()->isX64) {
|
||||||
STARTUPINFOW si = {0};
|
STARTUPINFOW si = {0};
|
||||||
si.cb = sizeof(STARTUPINFOW);
|
si.cb = sizeof(STARTUPINFOW);
|
||||||
@@ -1496,8 +1491,7 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
|
|||||||
si.hStdOutput = nullptr;
|
si.hStdOutput = nullptr;
|
||||||
si.hStdError = nullptr;
|
si.hStdError = nullptr;
|
||||||
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW));
|
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
STARTUPINFOW32 si = {0};
|
STARTUPINFOW32 si = {0};
|
||||||
si.cb = sizeof(STARTUPINFOW32);
|
si.cb = sizeof(STARTUPINFOW32);
|
||||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||||
@@ -2111,21 +2105,24 @@ auto Api_RtlFormatCurrentUserKeyPath(void* sandbox, uc_engine* uc,
|
|||||||
if (context->GetPeInfo()->isX64) {
|
if (context->GetPeInfo()->isX64) {
|
||||||
// 创建UNICODE_STRING结构
|
// 创建UNICODE_STRING结构
|
||||||
UNICODE_STRING unicodeString;
|
UNICODE_STRING unicodeString;
|
||||||
unicodeString.Length = static_cast<USHORT>(pathLen * sizeof(wchar_t));
|
unicodeString.Length =
|
||||||
|
static_cast<USHORT>(pathLen * sizeof(wchar_t));
|
||||||
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
|
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
|
||||||
unicodeString.Buffer = reinterpret_cast<PWSTR>(stringBuffer);
|
unicodeString.Buffer = reinterpret_cast<PWSTR>(stringBuffer);
|
||||||
|
|
||||||
// 将UNICODE_STRING结构写入到提供的缓冲区
|
// 将UNICODE_STRING结构写入到提供的缓冲区
|
||||||
uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING));
|
uc_mem_write(uc, keyPathBuffer, &unicodeString,
|
||||||
}
|
sizeof(UNICODE_STRING));
|
||||||
else {
|
} else {
|
||||||
UNICODE_STRING32 unicodeString;
|
UNICODE_STRING32 unicodeString;
|
||||||
unicodeString.Length = static_cast<USHORT>(pathLen * sizeof(wchar_t));
|
unicodeString.Length =
|
||||||
|
static_cast<USHORT>(pathLen * sizeof(wchar_t));
|
||||||
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
|
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
|
||||||
unicodeString.Buffer = (DWORD)(stringBuffer);
|
unicodeString.Buffer = (DWORD)(stringBuffer);
|
||||||
|
|
||||||
// 将UNICODE_STRING结构写入到提供的缓冲区
|
// 将UNICODE_STRING结构写入到提供的缓冲区
|
||||||
uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING32));
|
uc_mem_write(uc, keyPathBuffer, &unicodeString,
|
||||||
|
sizeof(UNICODE_STRING32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2389,3 +2386,148 @@ auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
|||||||
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
&return_value);
|
&return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto Api__initterm_e(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint64_t table_start = 0;
|
||||||
|
uint64_t table_end = 0;
|
||||||
|
|
||||||
|
// 获取参数:函数表的起始地址和结束地址
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
// x64: 参数在RCX和RDX中
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &table_start);
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RDX, &table_end);
|
||||||
|
} else {
|
||||||
|
// x86: 从栈上读取参数
|
||||||
|
uint32_t esp = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_ESP, &esp);
|
||||||
|
esp += 0x4; // 跳过返回地址
|
||||||
|
|
||||||
|
uint32_t temp_start;
|
||||||
|
uc_mem_read(uc, esp, &temp_start, sizeof(uint32_t));
|
||||||
|
table_start = temp_start;
|
||||||
|
|
||||||
|
esp += 0x4;
|
||||||
|
uint32_t temp_end;
|
||||||
|
uc_mem_read(uc, esp, &temp_end, sizeof(uint32_t));
|
||||||
|
table_end = temp_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回值,默认为0(成功)
|
||||||
|
int32_t return_value = 0;
|
||||||
|
|
||||||
|
// 遍历函数表并调用每个初始化函数
|
||||||
|
// 在表的每一项都是函数指针
|
||||||
|
printf("[*] _initterm_e: Start=0x%llx, End=0x%llx\n", table_start,
|
||||||
|
table_end);
|
||||||
|
|
||||||
|
// 只有当表的起始地址和结束地址有效时才进行处理
|
||||||
|
if (table_start < table_end) {
|
||||||
|
uint64_t current = table_start;
|
||||||
|
uint64_t ptr_size = context->GetPeInfo()->isX64 ? 8 : 4;
|
||||||
|
|
||||||
|
// 遍历函数表
|
||||||
|
while (current < table_end) {
|
||||||
|
uint64_t function_ptr = 0;
|
||||||
|
|
||||||
|
// 读取当前表项中的函数指针
|
||||||
|
uc_mem_read(uc, current, &function_ptr, ptr_size);
|
||||||
|
|
||||||
|
// 非空函数指针才调用
|
||||||
|
if (function_ptr != 0) {
|
||||||
|
printf("[*] _initterm_e: Calling function at 0x%llx\n",
|
||||||
|
function_ptr);
|
||||||
|
|
||||||
|
// 在实际环境中,这里会调用该函数并检查返回值
|
||||||
|
// 但在沙箱中,我们模拟这个调用并返回成功
|
||||||
|
// 如果需要执行真实函数,可以使用uc_emu_start
|
||||||
|
|
||||||
|
// 如果有错误发生,设置返回值并退出
|
||||||
|
// 这里简化处理,始终假设初始化成功
|
||||||
|
// 实际实现可能需要更复杂的逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动到下一个表项
|
||||||
|
current += ptr_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置返回值
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现getenv API
|
||||||
|
auto Api_getenv(void* sandbox, uc_engine* uc, uint64_t address) -> void {
|
||||||
|
auto context = static_cast<Sandbox*>(sandbox);
|
||||||
|
uint64_t name_ptr = 0;
|
||||||
|
char name[256] = {0};
|
||||||
|
uint64_t return_value = 0; // 默认返回NULL
|
||||||
|
|
||||||
|
// 获取参数 - 环境变量名称
|
||||||
|
if (context->GetPeInfo()->isX64) {
|
||||||
|
// x64: rcx = name
|
||||||
|
uc_reg_read(uc, UC_X86_REG_RCX, &name_ptr);
|
||||||
|
} else {
|
||||||
|
// x86: 从栈上读取参数
|
||||||
|
uint32_t esp_address = 0;
|
||||||
|
uint32_t temp_name_ptr = 0;
|
||||||
|
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
|
||||||
|
esp_address += 0x4; // 跳过返回地址
|
||||||
|
uc_mem_read(uc, esp_address, &temp_name_ptr, sizeof(uint32_t));
|
||||||
|
name_ptr = temp_name_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取环境变量名
|
||||||
|
if (name_ptr != 0) {
|
||||||
|
size_t i = 0;
|
||||||
|
uint8_t byte = 1;
|
||||||
|
while (byte != 0 && i < sizeof(name) - 1) {
|
||||||
|
uc_mem_read(uc, name_ptr + i, &byte, 1);
|
||||||
|
name[i++] = static_cast<char>(byte);
|
||||||
|
}
|
||||||
|
name[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[*] getenv: Looking for env var '%s'\n", name);
|
||||||
|
|
||||||
|
// 获取环境变量值
|
||||||
|
bool found = false;
|
||||||
|
std::string value;
|
||||||
|
std::vector<std::wstring> envStrings = context->GetEnvStrings();
|
||||||
|
|
||||||
|
for (const auto& var : envStrings) {
|
||||||
|
std::string varA(var.begin(), var.end());
|
||||||
|
size_t pos = varA.find('=');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
std::string varName = varA.substr(0, pos);
|
||||||
|
if (_stricmp(varName.c_str(), name) == 0) {
|
||||||
|
value = varA.substr(pos + 1);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
// 分配内存存储环境变量值
|
||||||
|
uint64_t valueSize = value.size() + 1; // 包括结束符
|
||||||
|
uint64_t valuePtr = context->AllocateMemory(valueSize);
|
||||||
|
|
||||||
|
if (valuePtr) {
|
||||||
|
// 复制字符串到内存
|
||||||
|
uc_mem_write(uc, valuePtr, value.c_str(), valueSize);
|
||||||
|
return_value = valuePtr;
|
||||||
|
printf("[*] getenv: Found '%s'='%s' at 0x%llx\n", name,
|
||||||
|
value.c_str(), valuePtr);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("[*] getenv: Env var '%s' not found\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置返回值
|
||||||
|
uc_reg_write(uc,
|
||||||
|
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
|
||||||
|
&return_value);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user