初步增加32位支持(没加全)

This commit is contained in:
huoji
2025-03-19 20:47:26 +08:00
parent 9b970ce8a2
commit 232a7abcba
9 changed files with 819 additions and 137 deletions

View File

@@ -313,26 +313,24 @@ auto doMalwareScan(int argc, char* argv[]) -> void {
}
int doSandbox(int argc, char* argv[]) {
if (argc < 3) {
std::cout << "用法: " << argv[0] << " <文件路径> <地址>" << std::endl;
return;
}
std::string filePath = argv[1];
std::string filePath = "C:\\opengl32.dll";
auto peInfo = getPeInfo(filePath);
if (peInfo == nullptr) {
return 0;
std::cout << "无法加载PE文件: " << filePath << std::endl;
return 1;
}
Sandbox se;
se.InitEnv(peInfo);
// se.Run(0x180003980);
se.Run(0x10002F20);
return 0;
}
int main(int argc, char* argv[]) {
// doMl(argc, argv);
// doPredict(argc, argv);
doMalwareScan(argc, argv);
// doSandbox(argc, argv);
// doMalwareScan(argc, argv);
doSandbox(argc, argv);
return 0;
}

View File

@@ -82,6 +82,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)ai_anti_malware\libpeconv\libpeconv\;$(SolutionDir)ai_anti_malware\libpeconv\libpeconv\include;$(SolutionDir)ai_anti_malware\libpeconv\;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -131,8 +132,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@@ -120,6 +120,12 @@ typedef struct _UNICODE_STRING {
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef struct _UNICODE_STRING32 {
USHORT Length;
USHORT MaximumLength;
DWORD Buffer;
} UNICODE_STRING32;
typedef UNICODE_STRING* PUNICODE_STRING;
typedef const UNICODE_STRING* PCUNICODE_STRING;
typedef PVOID(NTAPI* RtlImageDirectoryEntryToDataFn)(PVOID, BOOLEAN, USHORT,
@@ -905,6 +911,54 @@ union SegmentSelector {
};
static_assert(sizeof(SegmentSelector) == 2, "Size check");
#include <poppack.h>
typedef struct _STARTUPINFOW32 {
DWORD cb;
DWORD lpReserved;
DWORD lpDesktop;
DWORD lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
DWORD lpReserved2;
DWORD hStdInput;
DWORD hStdOutput;
DWORD hStdError;
} STARTUPINFOW32, * LPSTARTUPINFOW32;
static_assert(sizeof(STARTUPINFOW32) == 68, "Size check");
typedef struct tagPROCESSENTRY32W_32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
DWORD th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
WCHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32W_32;
static_assert(sizeof(PROCESSENTRY32W_32) == 556, "Size check");
#pragma pack(push, 8)
typedef struct _RTL_CRITICAL_SECTION32 {
DWORD DebugInfo;
LONG LockCount;
LONG RecursionCount;
DWORD OwningThread; // from the thread's ClientId->UniqueThread
DWORD LockSemaphore;
DWORD SpinCount; // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION32, * PRTL_CRITICAL_SECTION32;
#pragma pack(pop)
static_assert(sizeof(RTL_CRITICAL_SECTION32) == 24, "Size check");
union FlagRegister {
ULONG_PTR all;

View File

@@ -651,7 +651,7 @@ auto Sandbox::InitEnv(std::shared_ptr<BasicPeInfo> peInfo) -> void {
if (!peconv::load_imports(m_peInfo->peBuffer, &importFixer)) {
throw std::runtime_error("Failed to fix imports");
}
//给所有导入表加c3
// 给所有导入表加c3
for (const auto& module : this->GetModuleList()) {
// 遍历导出函数查找对应名称
for (const auto& exp : module->export_function) {
@@ -751,8 +751,8 @@ auto Sandbox::Run(uint64_t address) -> void {
}
// 系统调用钩子
err = uc_hook_add(m_ucEngine, &hook_syscall, UC_HOOK_INTR | UC_HOOK_INSN,
reinterpret_cast<void*>(sandboxCallbacks::handleSyscall),
this, 1, 0, UC_X86_INS_SYSCALL);
reinterpret_cast<void*>(sandboxCallbacks::handleSyscall),
this, 1, 0, UC_X86_INS_SYSCALL);
if (err != UC_ERR_OK) {
throw std::runtime_error("Failed to add syscall hook");
}
@@ -773,9 +773,38 @@ auto Sandbox::Run(uint64_t address) -> void {
// 1.入口点是必须跑的
if (m_peInfo->isDll) {
// 给rcx和rdx设置dll应该设置的
auto dll_fdwReason = 1;
uc_reg_write(m_ucEngine, UC_X86_REG_RCX, &m_peInfo->RecImageBase);
uc_reg_write(m_ucEngine, UC_X86_REG_RDX, &dll_fdwReason);
auto dll_fdwReason = 1; // DLL_PROCESS_ATTACH
if (m_peInfo->isX64) {
uc_reg_write(m_ucEngine, UC_X86_REG_RCX, &m_peInfo->RecImageBase);
uc_reg_write(m_ucEngine, UC_X86_REG_RDX, &dll_fdwReason);
} else {
// 32位使用栈传参而不是寄存器传参
uint32_t rsp;
uc_reg_read(m_ucEngine, UC_X86_REG_ESP, &rsp);
// 为参数腾出空间
rsp -= 3 * 4; // 三个参数hinstDLL, fdwReason, lpvReserved
uc_reg_write(m_ucEngine, UC_X86_REG_ESP, &rsp);
// 按照从右到左的顺序压栈
uint32_t lpvReserved = 0; // 第三个参数为NULL
uint32_t reason = dll_fdwReason; // DLL_PROCESS_ATTACH
uint32_t imageBase = static_cast<uint32_t>(m_peInfo->RecImageBase);
// 按照从右到左的调用约定写入参数到栈上
uc_mem_write(m_ucEngine, rsp, &lpvReserved,
sizeof(uint32_t)); // lpvReserved (最右侧参数最先入栈)
uc_mem_write(m_ucEngine, rsp + 4, &reason,
sizeof(uint32_t)); // fdwReason (中间参数次之入栈)
uc_mem_write(m_ucEngine, rsp + 8, &imageBase,
sizeof(uint32_t)); // hinstDLL (最左侧参数最后入栈)
// 在Windows下DLL的返回地址也需要压栈
uint32_t returnAddress = 0xABABABAB; // 虚拟的返回地址
rsp -= 4; // 为返回地址腾出空间
uc_reg_write(m_ucEngine, UC_X86_REG_ESP, &rsp);
uc_mem_write(m_ucEngine, rsp, &returnAddress, sizeof(uint32_t));
}
}
err = uc_emu_start(m_ucEngine, entryPoint, m_peInfo->imageEnd, timeout, 0);
// 2. 有自定义地址 再跑自定义地址

View File

@@ -425,4 +425,7 @@ auto Api_FwpmProviderAdd0(void* sandbox, uc_engine* uc, uint64_t address)
-> void;
auto Api_FwpmFilterAdd0(void* sandbox, uc_engine* uc, uint64_t address) -> void;
auto Api_FwpmEngineClose0(void* sandbox, uc_engine* uc, uint64_t address)
-> void;
-> 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_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void;

View File

@@ -2,6 +2,7 @@
#include "sandbox_callbacks.h"
#include "sandbox_api_winhttp.h"
#include <tlhelp32.h>
auto Api_QueryPerformanceCounter(void* sandbox, uc_engine* uc, uint64_t address)
-> void {
auto context = static_cast<Sandbox*>(sandbox);
@@ -602,7 +603,16 @@ auto Api_VirtualProtect(void* sandbox, uc_engine* uc, uint64_t address)
// 检查地址范围是否已映射
uint32_t unicornProtect = WindowsToUnicornProtect(flNewProtect);
uc_err err = uc_mem_protect(uc, lpAddress, dwSize, unicornProtect);
// 对齐地址和大小到页面边界
uint64_t aligned_address =
lpAddress & ~(PAGE_SIZE - 1); // 向下对齐到页面边界
uint64_t end_address = (lpAddress + dwSize + PAGE_SIZE - 1) &
~(PAGE_SIZE - 1); // 向上对齐到页面边界
uint64_t aligned_size = end_address - aligned_address;
uc_err err =
uc_mem_protect(uc, aligned_address, aligned_size, unicornProtect);
if (err != UC_ERR_OK) {
uint64_t result = 0; // FALSE
uc_reg_write(
@@ -909,6 +919,285 @@ auto Api_CreateDirectoryW(void* sandbox, uc_engine* uc, uint64_t address)
}
}
}
auto Api_GetStringTypeW(void* sandbox, uc_engine* uc, uint64_t address)
-> void {
auto context = static_cast<Sandbox*>(sandbox);
uint32_t dwInfoType = 0;
uint64_t lpSrcStr = 0;
int32_t cchSrc = 0;
uint64_t lpCharType = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = dwInfoType, rdx = lpSrcStr, r8 = cchSrc, r9 = lpCharType
uc_reg_read(uc, UC_X86_REG_RCX, &dwInfoType);
uc_reg_read(uc, UC_X86_REG_RDX, &lpSrcStr);
uint64_t temp_size;
uc_reg_read(uc, UC_X86_REG_R8, &temp_size);
cchSrc = static_cast<int32_t>(temp_size);
uc_reg_read(uc, UC_X86_REG_R9, &lpCharType);
} else {
// x86: 从栈上读取参数
uint32_t esp_address = 0;
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
esp_address += 0x4; // 跳过返回地址
uc_mem_read(uc, esp_address, &dwInfoType, sizeof(uint32_t));
esp_address += 0x4;
uint32_t temp_src_str;
uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t));
lpSrcStr = temp_src_str;
esp_address += 0x4;
uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t));
esp_address += 0x4;
uint32_t temp_char_type;
uc_mem_read(uc, esp_address, &temp_char_type, sizeof(uint32_t));
lpCharType = temp_char_type;
}
// 验证参数
if (lpSrcStr == 0 || lpCharType == 0) {
uint64_t result = 0; // FALSE
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
DWORD error = ERROR_INVALID_PARAMETER;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
return;
}
// 如果cchSrc为负数计算字符串长度
if (cchSrc < 0) {
cchSrc = 0;
wchar_t temp_char;
do {
uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char,
sizeof(wchar_t));
cchSrc++;
} while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限
cchSrc--; // 不包括null终止符
}
// 读取源字符串
std::vector<wchar_t> srcStr(cchSrc);
uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t));
// 处理每个字符
std::vector<WORD> charTypes(cchSrc);
for (int i = 0; i < cchSrc; i++) {
WORD type = 0;
wchar_t ch = srcStr[i];
switch (dwInfoType) {
case CT_CTYPE1: {
// 基本字符类型检查
if (iswupper(ch)) type |= C1_UPPER;
if (iswlower(ch)) type |= C1_LOWER;
if (iswdigit(ch)) type |= C1_DIGIT;
if (iswspace(ch)) type |= C1_SPACE;
if (iswpunct(ch)) type |= C1_PUNCT;
if (iswcntrl(ch)) type |= C1_CNTRL;
if (ch == L' ' || ch == L'\t') type |= C1_BLANK;
if ((ch >= L'0' && ch <= L'9') || (ch >= L'A' && ch <= L'F') ||
(ch >= L'a' && ch <= L'f'))
type |= C1_XDIGIT;
if (iswalpha(ch)) type |= C1_ALPHA;
if (type == 0) type |= C1_DEFINED;
break;
}
case CT_CTYPE2: {
// 简单的双向文本支持
if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z') ||
(ch >= L'0' && ch <= L'9')) {
type = C2_LEFTTORIGHT;
} else if (iswspace(ch)) {
type = C2_WHITESPACE;
} else {
type = C2_NOTAPPLICABLE;
}
break;
}
case CT_CTYPE3: {
// 基本文本处理信息
if (iswalpha(ch)) type |= C3_ALPHA;
// 这里可以添加更多的C3类型检查
break;
}
}
charTypes[i] = type;
}
// 写入结果
uc_mem_write(uc, lpCharType, charTypes.data(), cchSrc * sizeof(WORD));
printf("[*] GetStringTypeW: InfoType=0x%x, StrLen=%d\n", dwInfoType,
cchSrc);
// 返回成功
uint64_t result = 1; // TRUE
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
}
auto Api_LCMapStringW(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint32_t Locale = 0;
uint32_t dwMapFlags = 0;
uint64_t lpSrcStr = 0;
int32_t cchSrc = 0;
uint64_t lpDestStr = 0;
int32_t cchDest = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = Locale, rdx = dwMapFlags, r8 = lpSrcStr, r9 = cchSrc
uc_reg_read(uc, UC_X86_REG_RCX, &Locale);
uc_reg_read(uc, UC_X86_REG_RDX, &dwMapFlags);
uc_reg_read(uc, UC_X86_REG_R8, &lpSrcStr);
uint64_t temp_src_size;
uc_reg_read(uc, UC_X86_REG_R9, &temp_src_size);
cchSrc = static_cast<int32_t>(temp_src_size);
// 从栈上读取剩余参数
uint64_t rsp;
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
uc_mem_read(uc, rsp + 0x28, &lpDestStr, sizeof(uint64_t));
uc_mem_read(uc, rsp + 0x30, &cchDest, sizeof(int32_t));
} else {
// x86: 从栈上读取参数
uint32_t esp_address = 0;
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
esp_address += 0x4; // 跳过返回地址
uc_mem_read(uc, esp_address, &Locale, sizeof(uint32_t));
esp_address += 0x4;
uc_mem_read(uc, esp_address, &dwMapFlags, sizeof(uint32_t));
esp_address += 0x4;
uint32_t temp_src_str;
uc_mem_read(uc, esp_address, &temp_src_str, sizeof(uint32_t));
lpSrcStr = temp_src_str;
esp_address += 0x4;
uc_mem_read(uc, esp_address, &cchSrc, sizeof(int32_t));
esp_address += 0x4;
uint32_t temp_dest_str;
uc_mem_read(uc, esp_address, &temp_dest_str, sizeof(uint32_t));
lpDestStr = temp_dest_str;
esp_address += 0x4;
uc_mem_read(uc, esp_address, &cchDest, sizeof(int32_t));
}
// 验证参数
if (lpSrcStr == 0) {
uint32_t result = 0;
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
DWORD error = ERROR_INVALID_PARAMETER;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
return;
}
// 如果cchSrc为负数计算源字符串长度
if (cchSrc < 0) {
cchSrc = 0;
wchar_t temp_char;
do {
uc_mem_read(uc, lpSrcStr + (cchSrc * 2), &temp_char,
sizeof(wchar_t));
cchSrc++;
} while (temp_char != 0 && cchSrc < 1024); // 设置一个合理的上限
cchSrc--; // 不包括null终止符
}
// 读取源字符串
std::vector<wchar_t> srcStr(cchSrc);
uc_mem_read(uc, lpSrcStr, srcStr.data(), cchSrc * sizeof(wchar_t));
// 如果cchDest为0返回所需缓冲区大小
if (cchDest == 0) {
uint32_t required_size = cchSrc;
if (dwMapFlags & LCMAP_SORTKEY) {
required_size = cchSrc * 2 + 1; // 排序键通常需要更多空间
}
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&required_size);
return;
}
// 检查目标缓冲区大小是否足够
if (cchDest < cchSrc) {
uint32_t result = 0;
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
DWORD error = ERROR_INSUFFICIENT_BUFFER;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
return;
}
// 处理字符串映射
std::vector<wchar_t> destStr(cchSrc);
for (int i = 0; i < cchSrc; i++) {
wchar_t ch = srcStr[i];
if (dwMapFlags & LCMAP_UPPERCASE) {
destStr[i] = towupper(ch);
} else if (dwMapFlags & LCMAP_LOWERCASE) {
destStr[i] = towlower(ch);
} else {
destStr[i] = ch; // 默认保持不变
}
}
// 写入结果
if (dwMapFlags & LCMAP_SORTKEY) {
// 生成简单的排序键(这里只是一个基本实现)
std::vector<BYTE> sortKey(cchSrc * 2 + 1);
for (int i = 0; i < cchSrc; i++) {
sortKey[i * 2] = static_cast<BYTE>(destStr[i] & 0xFF);
sortKey[i * 2 + 1] = static_cast<BYTE>((destStr[i] >> 8) & 0xFF);
}
sortKey[cchSrc * 2] = 0; // 终止符
uc_mem_write(uc, lpDestStr, sortKey.data(), sortKey.size());
uint32_t result = static_cast<uint32_t>(sortKey.size());
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
} else {
// 写入映射后的字符串
uc_mem_write(uc, lpDestStr, destStr.data(), cchSrc * sizeof(wchar_t));
uint32_t result = cchSrc;
uc_reg_write(
uc, context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&result);
}
printf(
"[*] LCMapStringW: Locale=0x%x, MapFlags=0x%x, SrcLen=%d, DestLen=%d\n",
Locale, dwMapFlags, cchSrc, cchDest);
}
auto Sandbox::InitApiHooks() -> void {
auto FakeApi_GetSystemTimeAsFileTime =
_fakeApi{.func = Api_GetSystemTimeAsFileTime, .paramCount = 1};
@@ -1062,6 +1351,15 @@ auto Sandbox::InitApiHooks() -> void {
_fakeApi{.func = Api_CreateDirectoryW, .paramCount = 2};
auto FakeApi_URLDownloadToFileW =
_fakeApi{.func = Api_URLDownloadToFileW, .paramCount = 5};
auto FakeApi_TlsFree = _fakeApi{.func = Api_TlsFree, .paramCount = 1};
auto FakeApi_FlsAlloc = _fakeApi{.func = Api_FlsAlloc, .paramCount = 1};
auto FakeApi_FlsGetValue =
_fakeApi{.func = Api_FlsGetValue, .paramCount = 1};
auto FakeApi_GetStringTypeW =
_fakeApi{.func = Api_GetStringTypeW, .paramCount = 4};
auto FakeApi_LCMapStringW =
_fakeApi{.func = Api_LCMapStringW, .paramCount = 6};
api_map = {
{"GetSystemTimeAsFileTime",
std::make_shared<_fakeApi>(FakeApi_GetSystemTimeAsFileTime)},
@@ -1187,14 +1485,15 @@ auto Sandbox::InitApiHooks() -> void {
std::make_shared<_fakeApi>(FakeApi_LookupPrivilegeValueA)},
{"AdjustTokenPrivileges",
std::make_shared<_fakeApi>(FakeApi_AdjustTokenPrivileges)},
{"LookupPrivilegeValueA",
std::make_shared<_fakeApi>(FakeApi_LookupPrivilegeValueA)},
{"AdjustTokenPrivileges",
std::make_shared<_fakeApi>(FakeApi_AdjustTokenPrivileges)},
{"CreateDirectoryW",
std::make_shared<_fakeApi>(FakeApi_CreateDirectoryW)},
{"URLDownloadToFileW",
std::make_shared<_fakeApi>(FakeApi_URLDownloadToFileW)},
{"TlsFree", std::make_shared<_fakeApi>(FakeApi_TlsFree)},
{"FlsAlloc", std::make_shared<_fakeApi>(FakeApi_FlsAlloc)},
{"FlsGetValue", std::make_shared<_fakeApi>(FakeApi_FlsGetValue)},
{"GetStringTypeW", std::make_shared<_fakeApi>(FakeApi_GetStringTypeW)},
{"LCMapStringW", std::make_shared<_fakeApi>(FakeApi_LCMapStringW)},
};
}
auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
@@ -1202,8 +1501,8 @@ auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
auto it = api_map.find(ApiName);
if (it != api_map.end()) {
it->second->func(this, uc, address);
this->ApiCallList.push_back(ApiName);
this->ApiCallList.push_back(ApiName);
// 获取参数数量
int paramCount = it->second->paramCount;
uint32_t esp;
@@ -1236,7 +1535,8 @@ auto Sandbox::EmulateApi(uc_engine* uc, uint64_t address, uint64_t rip,
// x86下所有参数都通过栈传递
// 调整栈指针每个参数4字节 + 返回地址4字节
esp += (paramCount * 4) + 4;
// 设置EIP为返回地址
// esp += 4;
// 设置EIP为返回地址
uc_reg_write(uc, UC_X86_REG_EIP, &return_address_32);
}
if (this->GetPeInfo()->isX64) {

View File

@@ -270,23 +270,46 @@ auto Api_Process32FirstW(void* sandbox, uc_engine* uc, uint64_t address)
// 读取结构体大小
DWORD structSize = 0;
if (uc_mem_read(uc, lppe, &structSize, sizeof(DWORD)) == UC_ERR_OK) {
if (structSize == sizeof(PROCESSENTRY32W)) {
// 获取第一个进程信息在我们的实现中是DingTalk.exe
PROCESSENTRY32W pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32W);
pe32.th32ProcessID = 1001; // DingTalk的PID
pe32.cntThreads = 1;
pe32.th32ParentProcessID = 4; // 父进程是System
pe32.pcPriClassBase = 8; // 正常优先级
if (context->GetPeInfo()->isX64) {
if (structSize == sizeof(PROCESSENTRY32W)) {
// 获取第一个进程信息在我们的实现中是DingTalk.exe
PROCESSENTRY32W pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32W);
pe32.th32ProcessID = 1001; // DingTalk的PID
pe32.cntThreads = 1;
pe32.th32ParentProcessID = 4; // 父进程是System
pe32.pcPriClassBase = 8; // 正常优先级
// 设置进程名
std::wstring procName = L"DingTalk.exe";
wcscpy_s(pe32.szExeFile, procName.c_str());
// 设置进程名
std::wstring procName = L"DingTalk.exe";
wcscpy_s(pe32.szExeFile, procName.c_str());
// 写入进程信息到用户提供的缓冲区
if (uc_mem_write(uc, lppe, &pe32, sizeof(PROCESSENTRY32W)) ==
UC_ERR_OK) {
success = true;
// 写入进程信息到用户提供的缓冲区
if (uc_mem_write(uc, lppe, &pe32, sizeof(PROCESSENTRY32W)) ==
UC_ERR_OK) {
success = true;
}
}
}
else {
if (structSize == sizeof(PROCESSENTRY32W_32)) {
// 获取第一个进程信息在我们的实现中是DingTalk.exe
PROCESSENTRY32W_32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32W_32);
pe32.th32ProcessID = 1001; // DingTalk的PID
pe32.cntThreads = 1;
pe32.th32ParentProcessID = 4; // 父进程是System
pe32.pcPriClassBase = 8; // 正常优先级
// 设置进程名
std::wstring procName = L"DingTalk.exe";
wcscpy_s(pe32.szExeFile, procName.c_str());
// 写入进程信息到用户提供的缓冲区
if (uc_mem_write(uc, lppe, &pe32, sizeof(PROCESSENTRY32W_32)) ==
UC_ERR_OK) {
success = true;
}
}
}
}
@@ -388,6 +411,36 @@ auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address)
hSnapshot = temp_handle;
lppe = temp_lppe;
}
// 获取当前进程索引
size_t currentIndex = 0;
auto it = context->process_enum_state.find(hSnapshot);
if (it != context->process_enum_state.end()) {
currentIndex = it->second;
currentIndex++; // 移动到下一个进程
}
// 定义进程列表
struct ProcessInfo {
const wchar_t* name;
uint32_t pid;
uint32_t parentPid;
};
ProcessInfo processes[] = {
{L"DingTalk.exe", 1001, 4}, // 钉钉
{L"Lanxin.exe", 1002, 4}, // 蓝信
{L"QQ.exe", 1003, 4}, // QQ
{L"Feishu.exe", 1004, 4}, // 飞书
{L"explorer.exe", 1005, 4}, // Windows 资源管理器
{L"svchost.exe", 1006, 4}, // 系统服务宿主进程
{L"System", 4, 0}, // 系统进程
{L"smss.exe", 376, 4}, // 会话管理器
{L"csrss.exe", 648, 376}, // 客户端服务器运行时子系统
{L"winlogon.exe", 672, 376}, // Windows 登录进程
};
const size_t processCount =
sizeof(processes) / sizeof(processes[0]);
// 验证句柄
bool success = false;
@@ -395,43 +448,37 @@ auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address)
// 读取结构体大小
DWORD structSize = 0;
if (uc_mem_read(uc, lppe, &structSize, sizeof(DWORD)) == UC_ERR_OK) {
if (structSize == sizeof(PROCESSENTRY32W)) {
// 获取当前进程索引
size_t currentIndex = 0;
auto it = context->process_enum_state.find(hSnapshot);
if (it != context->process_enum_state.end()) {
currentIndex = it->second;
currentIndex++; // 移动到下一个进程
if (context->GetPeInfo()->isX64) {
if (structSize == sizeof(PROCESSENTRY32W)) {
// 检查是否还有更多进程
if (currentIndex < processCount) {
// 填充进程信息
PROCESSENTRY32W pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32W);
pe32.th32ProcessID = processes[currentIndex].pid;
pe32.th32ParentProcessID =
processes[currentIndex].parentPid;
pe32.cntThreads = 1;
pe32.pcPriClassBase = 8; // 正常优先级
// 设置进程名
wcscpy_s(pe32.szExeFile, processes[currentIndex].name);
// 写入进程信息到用户提供的缓冲区
if (uc_mem_write(uc, lppe, &pe32,
sizeof(PROCESSENTRY32W)) == UC_ERR_OK) {
success = true;
// 更新进程索引
context->process_enum_state[hSnapshot] = currentIndex;
}
}
}
// 定义进程列表
struct ProcessInfo {
const wchar_t* name;
uint32_t pid;
uint32_t parentPid;
};
ProcessInfo processes[] = {
{L"DingTalk.exe", 1001, 4}, // 钉钉
{L"Lanxin.exe", 1002, 4}, // 蓝信
{L"QQ.exe", 1003, 4}, // QQ
{L"Feishu.exe", 1004, 4}, // 飞书
{L"explorer.exe", 1005, 4}, // Windows 资源管理器
{L"svchost.exe", 1006, 4}, // 系统服务宿主进程
{L"System", 4, 0}, // 系统进程
{L"smss.exe", 376, 4}, // 会话管理器
{L"csrss.exe", 648, 376}, // 客户端服务器运行时子系统
{L"winlogon.exe", 672, 376}, // Windows 登录进程
};
const size_t processCount =
sizeof(processes) / sizeof(processes[0]);
// 检查是否还有更多进程
}
else {
if (currentIndex < processCount) {
// 填充进程信息
PROCESSENTRY32W pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32W);
PROCESSENTRY32W_32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32W_32);
pe32.th32ProcessID = processes[currentIndex].pid;
pe32.th32ParentProcessID =
processes[currentIndex].parentPid;
@@ -443,7 +490,7 @@ auto Api_Process32NextW(void* sandbox, uc_engine* uc, uint64_t address)
// 写入进程信息到用户提供的缓冲区
if (uc_mem_write(uc, lppe, &pe32,
sizeof(PROCESSENTRY32W)) == UC_ERR_OK) {
sizeof(PROCESSENTRY32W_32)) == UC_ERR_OK) {
success = true;
// 更新进程索引
context->process_enum_state[hSnapshot] = currentIndex;

View File

@@ -1333,39 +1333,72 @@ auto Api_EnterCriticalSection(void* sandbox, uc_engine* uc, uint64_t address)
lpCriticalSection = temp_cs;
}
// 获取当前线程ID
HANDLE currentThreadHandle = nullptr;
if (context->GetPeInfo()->isX64) {
currentThreadHandle =
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
}
else {
currentThreadHandle =
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
}
if (lpCriticalSection != 0) {
RTL_CRITICAL_SECTION cs;
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
// 获取当前线程ID
HANDLE currentThreadHandle = nullptr;
if (context->GetPeInfo()->isX64) {
currentThreadHandle =
(HANDLE)(ULONG_PTR)context->GetTeb64()->ClientId.UniqueThread;
} else {
currentThreadHandle =
(HANDLE)(ULONG_PTR)context->GetTeb32()->ClientId.UniqueThread;
}
RTL_CRITICAL_SECTION cs;
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
// 如果当前线程已经拥有锁,增加递归计数
if (cs.OwningThread == currentThreadHandle) {
cs.RecursionCount++;
} else {
// 如果没有线程拥有锁,获取它
if (cs.LockCount == -1) {
cs.OwningThread = currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount = 0;
} else {
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
cs.OwningThread = currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount++;
// 如果当前线程已经拥有锁,增加递归计数
if (cs.OwningThread == currentThreadHandle) {
cs.RecursionCount++;
}
else {
// 如果没有线程拥有锁,获取它
if (cs.LockCount == -1) {
cs.OwningThread = currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount = 0;
}
else {
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
cs.OwningThread = currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount++;
}
}
}
// 写回更新后的关键段结构
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
// 写回更新后的关键段结构
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION));
}
else {
RTL_CRITICAL_SECTION32 cs;
uc_mem_read(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32));
// 如果当前线程已经拥有锁,增加递归计数
if (cs.OwningThread == (DWORD)currentThreadHandle) {
cs.RecursionCount++;
}
else {
// 如果没有线程拥有锁,获取它
if (cs.LockCount == -1) {
cs.OwningThread = (DWORD)currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount = 0;
}
else {
// 在实际情况下这里应该自旋等待,但在模拟环境中我们直接获取锁
cs.OwningThread = (DWORD)currentThreadHandle;
cs.RecursionCount = 1;
cs.LockCount++;
}
}
// 写回更新后的关键段结构
uc_mem_write(uc, lpCriticalSection, &cs, sizeof(RTL_CRITICAL_SECTION32));
}
}
printf("[*] EnterCriticalSection: CS=0x%llx\n", lpCriticalSection);
@@ -1426,7 +1459,7 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
-> void {
auto context = static_cast<Sandbox*>(sandbox);
uint64_t lpStartupInfo = 0;
printf("[*] GetStartupInfoW start dump vmenv\n");
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = lpStartupInfo
@@ -1442,28 +1475,49 @@ auto Api_GetStartupInfoW(void* sandbox, uc_engine* uc, uint64_t address)
}
if (lpStartupInfo != 0) {
// 创建一个默认的 STARTUPINFOW 结构
STARTUPINFOW si = {0};
si.cb = sizeof(STARTUPINFOW);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
si.lpDesktop = nullptr;
si.lpTitle = nullptr;
si.dwX = 0;
si.dwY = 0;
si.dwXSize = 0;
si.dwYSize = 0;
si.dwXCountChars = 0;
si.dwYCountChars = 0;
si.dwFillAttribute = 0;
si.cbReserved2 = 0;
si.lpReserved2 = nullptr;
si.hStdInput = nullptr;
si.hStdOutput = nullptr;
si.hStdError = nullptr;
// 写入结构到目标内存
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW));
if (context->GetPeInfo()->isX64) {
STARTUPINFOW si = { 0 };
si.cb = sizeof(STARTUPINFOW);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
si.lpDesktop = nullptr;
si.lpTitle = nullptr;
si.dwX = 0;
si.dwY = 0;
si.dwXSize = 0;
si.dwYSize = 0;
si.dwXCountChars = 0;
si.dwYCountChars = 0;
si.dwFillAttribute = 0;
si.cbReserved2 = 0;
si.lpReserved2 = nullptr;
si.hStdInput = nullptr;
si.hStdOutput = nullptr;
si.hStdError = nullptr;
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW));
}
else {
STARTUPINFOW32 si = { 0 };
si.cb = sizeof(STARTUPINFOW32);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
si.lpDesktop = 0;
si.lpTitle = 0;
si.dwX = 0;
si.dwY = 0;
si.dwXSize = 0;
si.dwYSize = 0;
si.dwXCountChars = 0;
si.dwYCountChars = 0;
si.dwFillAttribute = 0;
si.cbReserved2 = 0;
si.lpReserved2 = 0;
si.hStdInput = 0;
si.hStdOutput = 0;
si.hStdError = 0;
uc_mem_write(uc, lpStartupInfo, &si, sizeof(STARTUPINFOW32));
}
}
printf("[*] GetStartupInfoW: lpStartupInfo=0x%llx\n", lpStartupInfo);
@@ -2058,15 +2112,25 @@ auto Api_RtlFormatCurrentUserKeyPath(void* sandbox, uc_engine* uc,
if (stringBuffer != 0 && keyPathBuffer != 0) {
// 将路径字符串写入到分配的缓冲区
uc_mem_write(uc, stringBuffer, userKeyPath, bufferSize);
if (context->GetPeInfo()->isX64) {
// 创建UNICODE_STRING结构
UNICODE_STRING unicodeString;
unicodeString.Length = static_cast<USHORT>(pathLen * sizeof(wchar_t));
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
unicodeString.Buffer = reinterpret_cast<PWSTR>(stringBuffer);
// 创建UNICODE_STRING结构
UNICODE_STRING unicodeString;
unicodeString.Length = static_cast<USHORT>(pathLen * sizeof(wchar_t));
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
unicodeString.Buffer = reinterpret_cast<PWSTR>(stringBuffer);
// UNICODE_STRING结构写入到提供的缓冲区
uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING));
}
else {
UNICODE_STRING32 unicodeString;
unicodeString.Length = static_cast<USHORT>(pathLen * sizeof(wchar_t));
unicodeString.MaximumLength = static_cast<USHORT>(bufferSize);
unicodeString.Buffer = (DWORD)(stringBuffer);
// 将UNICODE_STRING结构写入到提供的缓冲区
uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING));
// 将UNICODE_STRING结构写入到提供的缓冲区
uc_mem_write(uc, keyPathBuffer, &unicodeString, sizeof(UNICODE_STRING32));
}
}
// 返回NTSTATUS成功代码 (0x00000000 = STATUS_SUCCESS)
@@ -2143,3 +2207,189 @@ auto Api_FlsSetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
}
}
}
// 实现TlsFree API
auto Api_TlsFree(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint32_t dwTlsIndex = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = dwTlsIndex
uint64_t temp_index;
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
dwTlsIndex = static_cast<uint32_t>(temp_index);
} else {
// x86: 从栈上读取参数
uint32_t esp_address = 0;
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
esp_address += 0x4; // 跳过返回地址
uc_mem_read(uc, esp_address, &dwTlsIndex, sizeof(uint32_t));
}
// 检查索引是否有效小于64并释放对应的TLS槽
BOOL success = FALSE;
if (dwTlsIndex < 64) {
if (context->GetPeInfo()->isX64) {
auto teb = context->GetTeb64();
// 检查槽是否已分配不为0x1337ffffff
if (teb->TlsSlots[dwTlsIndex] != (void*)0x1337ffffff) {
// 将槽位标记为可用
teb->TlsSlots[dwTlsIndex] = (void*)0x1337ffffff;
success = TRUE;
}
} else {
auto teb = context->GetTeb32();
// 检查槽是否已分配不为0x1337
if (teb->TlsSlots[dwTlsIndex] != 0x1337) {
// 将槽位标记为可用
teb->TlsSlots[dwTlsIndex] = 0x1337;
success = TRUE;
}
}
}
if (!success) {
// 设置错误码
DWORD error = ERROR_INVALID_PARAMETER;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
}
printf("[*] TlsFree: Index=0x%x, Success=%d\n", dwTlsIndex, success);
// 返回操作是否成功
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&success);
}
// 实现FlsAlloc API
auto Api_FlsAlloc(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint64_t lpCallback = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = lpCallback
uc_reg_read(uc, UC_X86_REG_RCX, &lpCallback);
} else {
// x86: 从栈上读取参数
uint32_t esp_address = 0;
uint32_t temp_callback = 0;
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
esp_address += 0x4; // 跳过返回地址
uc_mem_read(uc, esp_address, &temp_callback, sizeof(uint32_t));
lpCallback = temp_callback;
}
// 初始化返回值为失败状态
DWORD fls_index = FLS_OUT_OF_INDEXES;
// 获取TEB结构
if (context->GetPeInfo()->isX64) {
auto teb = context->GetTeb64();
// 在TLS槽中查找第一个可用的位置
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
if (teb->TlsSlots[i] == (void*)0x1337ffffff) {
teb->TlsSlots[i] = (void*)0; // 标记为已使用
fls_index = i;
break;
}
}
} else {
auto teb = context->GetTeb32();
// 在TLS槽中查找第一个可用的位置
for (DWORD i = 0; i < 64; i++) { // TEB中TlsSlots数组大小为64
if (teb->TlsSlots[i] == 0x1337) {
teb->TlsSlots[i] = 0; // 标记为已使用
fls_index = i;
break;
}
}
}
if (fls_index == FLS_OUT_OF_INDEXES) {
// 设置LastError为没有可用的FLS索引
DWORD error = ERROR_NO_MORE_ITEMS;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
}
printf("[*] FlsAlloc: Callback=0x%llx, Allocated FLS Index=0x%x\n",
lpCallback, fls_index);
// 返回分配的FLS索引
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&fls_index);
}
// 实现FlsGetValue API
auto Api_FlsGetValue(void* sandbox, uc_engine* uc, uint64_t address) -> void {
auto context = static_cast<Sandbox*>(sandbox);
uint32_t dwFlsIndex = 0;
uint64_t return_value = 0;
// 获取参数
if (context->GetPeInfo()->isX64) {
// x64: rcx = dwFlsIndex
uint64_t temp_index;
uc_reg_read(uc, UC_X86_REG_RCX, &temp_index);
dwFlsIndex = static_cast<uint32_t>(temp_index);
} else {
// x86: 从栈上读取参数
uint32_t esp_address = 0;
uc_reg_read(uc, UC_X86_REG_ESP, &esp_address);
esp_address += 0x4; // 跳过返回地址
uc_mem_read(uc, esp_address, &dwFlsIndex, sizeof(uint32_t));
}
// 检查索引是否有效小于64
if (dwFlsIndex < 64) {
if (context->GetPeInfo()->isX64) {
auto teb = context->GetTeb64();
// 检查槽是否已分配不为nullptr
if (teb->TlsSlots[dwFlsIndex] != (void*)0x1337ffffff) {
return_value =
reinterpret_cast<uint64_t>(teb->TlsSlots[dwFlsIndex]);
} else {
// 槽未分配设置LastError
DWORD error = ERROR_INVALID_PARAMETER;
teb->LastErrorValue = error;
}
} else {
auto teb = context->GetTeb32();
// 检查槽是否已分配不为0
if (teb->TlsSlots[dwFlsIndex] != 0x1337) {
return_value = teb->TlsSlots[dwFlsIndex];
} else {
// 槽未分配设置LastError
DWORD error = ERROR_INVALID_PARAMETER;
teb->LastErrorValue = error;
}
}
} else {
// 索引无效设置LastError
DWORD error = ERROR_INVALID_PARAMETER;
if (context->GetPeInfo()->isX64) {
context->GetTeb64()->LastErrorValue = error;
} else {
context->GetTeb32()->LastErrorValue = error;
}
}
printf("[*] FlsGetValue: Index=0x%x, Value=0x%llx\n", dwFlsIndex,
return_value);
// 返回FLS槽中的值
uc_reg_write(uc,
context->GetPeInfo()->isX64 ? UC_X86_REG_RAX : UC_X86_REG_EAX,
&return_value);
}

View File

@@ -38,7 +38,6 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
break;
}
}
// 如果找到区段,并且与上次执行的区段不同,记录跨区段行为
if (currentSectionIndex >= 0 &&
sandbox->GetLastExecuteSectionIndex() != currentSectionIndex &&
@@ -84,7 +83,7 @@ void handleCodeRun(uc_engine* uc, uint64_t address, uint32_t size,
}
cs_free(instruction, instructionCount);
// dumpVmenv(uc, userData);
//dumpVmenv(uc, userData);
}
}
@@ -177,9 +176,9 @@ void dumpVmenv(uc_engine* uc, void* userData) {
"%08x Ecx: %08x\n",
Rip, Rax, Rsp, Rbp, Rcx, Rdx, Eax, Ecx);
// 打印16层栈内存
printf("\n[Stack Memory Dump (16 levels)]\n");
const int STACK_LEVELS = 16;
// 打印32层栈内存
printf("\n[Stack Memory Dump (32 levels)]\n");
const int STACK_LEVELS = 32;
const int POINTER_SIZE = sandbox->GetPeInfo()->isX64 ? 8 : 4;
for (int i = 0; i < STACK_LEVELS; i++) {
@@ -219,7 +218,7 @@ void dumpVmenv(uc_engine* uc, void* userData) {
}
}
printf("\n[Frame Pointer Stack (16 levels)]\n");
printf("\n[Frame Pointer Stack (32 levels)]\n");
uint64_t currentBp = Rbp;
for (int i = 0; i < STACK_LEVELS && currentBp != 0; i++) {
uint64_t nextBp = 0;