Hezhi病毒是去年分析一个病毒,下面是分析报告,由于xxx原因杀毒程序不能公布(其实分析报告应该写得比较清楚了,哈)
写杀变形病毒的程序, 首先是要解决怎么查这个病毒(把病毒的变形引擎分析透彻一点,它怎么变你就怎么查),然后才是杀(好像是废话:))
hezhi病毒分析报告
haiwei/CVC.GB
关键字:
变形\病毒\感染\AntiDebug
分析工具:
OD(动态)\IDA(静态)
分析目标:
1.样本MD5值:a7be1177766cec09d7e914ea7985c723
2.病毒名称:Win32.Hezhi
难度:中
病毒简介:
1.这是一个基于poly技术的病毒,病毒代码经过五层加密,且key为动态的.
2.感染在宿主程序的节空隙,如果没有足够的空隙,则增加最后一节的节大小.
3.加密原宿主代码.
4.病毒代码中有多处SEH陷井来反动态调试
病毒执行流程:
1.第一次解密
004087D3 0F 84 87 EF FF FF jz near ptr loc_40775F+1
.text:004087D9 50 push eax
.text:004087DA E8 00 00 00 00 call $+5
.text:004087DF 58 pop eax
.text:004087E0 58 pop eax
.text:004087E1 BE 00 00 09 02 mov esi, 2090000h \\关键
.text:004087E6 50 push eax
.text:004087E7 13 C3 adc eax, ebx
.text:004087E9 1B C3 sbb eax, ebx
.text:004087EB 58 pop eax
.text:004087EC B8 0C 03 00 00 mov eax, 30Ch
.text:004087F1 57 push edi
.text:004087F2 F7 D7 not edi
.text:004087F4 0F 03 F8 lsl edi, eax
.text:004087F7 5F pop edi
.text:004087F8 81 C0 3A 2E 00 00 add eax, 2E3Ah
.text:004087FE 57 push edi
.text:004087FF F7 D7 not edi
.text:00408801 0F 03 F8 lsl edi, eax
.text:00408804 5F pop edi
.text:00408805 C1 C6 1D rol esi, 1Dh \\经过这条指令Esi为待解密代码的
\\起始地址
.text:00408808 51 push ecx
.text:00408809 81 C1 19 39 D0 DB add ecx, 0DBD03919h
.text:0040880F 59 pop ecx
.text:00408810
.text:00408810 loc_408810: ; CODE XREF: start+D0j
.text:00408810 81 34 30 DA 0C 03 D2 xor dword ptr [eax+esi], 0D2030CDAh \\Key
.text:00408817 F5 cmc
.text:00408818 F5 cmc
.text:00408819 90 nop
.text:0040881A 90 nop
.text:0040881B 48 dec eax
.text:0040881C 50 push eax
.text:0040881D E8 00 00 00 00 call $+5
.text:00408822 58 pop eax
.text:00408823 58 pop eax
.text:00408824 7D EA jge short loc_408810 \\循环
.text:00408826 57 push edi
.text:00408827 F7 D7 not edi
.text:00408829 0F 03 F8 lsl edi, eax
.text:0040882C 5F pop edi
.text:0040882D FF E6 jmp esi \\跳到已解密代码执行
下面为小弟写的IDC解密脚本:
auto RegEsi;
auto Key;
auto RegEax;
RegEsi=0x412000;
Key=0xd2030cda;
RegEax=0x3146;
for (;RegEax>=0;RegEax--)
{
Data=Dword(RegEax+RegEsi)^Key;
PatchDword(RegEax+RegEsi,Data);
}
在OD里可以把代码直接拉到JMP XX处 F4(XX可变),在这个例子样本中为JMP Esi
2.第二次解密
JMP Esi来到412000,该处代码如下
00412002 50 PUSH EAX
00412003 E8 00000000 CALL CLSPACK1.00412008
00412008 58 POP EAX
00412009 83C0 1A ADD EAX,1A
0041200C 50 PUSH EAX ; CLSPACK1.00412022
0041200D 64:67:FF36 0000 PUSH DWORD PTR FS:[0] \\这里很明显是一个SEH陷井
00412013 64:67:8926 0000 MOV DWORD PTR FS:[0],ESP
00412019 B8 FFFFFFFF MOV EAX,-1
0041201E FFE0 JMP EAX \\故意产生异常
00412020 FFE0 JMP EAX
00412022 64:67:A1 0000 MOV EAX,DWORD PTR FS:[0] \\在这个位置F2下断点,F9,出现异常
\\出现异常后按shift+F9到412022断点处停下
00412027 8B20 MOV ESP,DWORD PTR DS:[EAX]
00412029 64:67:8F06 0000 POP DWORD PTR FS:[0]
0041202F 58 POP EAX \\这几条指令在恢复SEH
00412030 58 POP EAX
00412031 60 PUSHAD
00412032 E8 00000000 CALL CLSPACK1.00412037
00412037 58 POP EAX
00412038 BE 82104000 MOV ESI,CLSPACK1.00401082
0041203D BB 37104000 MOV EBX,CLSPACK1.00401037
00412042 2BF3 SUB ESI,EBX
00412044 03F0 ADD ESI,EAX \\Esi为解密起始地址
00412046 BB C4300000 MOV EBX,30C4 \\解密长度
0041204B 81341E 30C87B80 XOR DWORD PTR DS:[ESI+EBX],807BC830 \\Key
00412052 9C PUSHFD
省略若干垃圾指令
0041207D 9D POPFD
0041207E 4B DEC EBX
0041207F ^7D CA JGE SHORT CLSPACK1.0041204B \\循环
00412081 61 POPAD \\在OD中把光标停在这F4
下面是第二次解密IDC脚本:
auto RegEsi;
auto Key;
auto RegEax;
auto Data;
RegEsi=0x412082;
Key=0x807bc830;
RegEax=0x30c4;
for (;RegEax>=0;RegEax--)
{
Data=Dword(RegEax+RegEsi)^Key;
PatchDword(RegEax+RegEsi,Data);
}
3.第三次解密
00412089 BE CC104000 MOV ESI,<&KERNEL32.RtlUnwind>
0041208E BB 88104000 MOV EBX,<&KERNEL32.ExitProcess>
00412093 2BF3 SUB ESI,EBX
00412095 03F0 ADD ESI,EAX \\解密起始地址
00412097 B9 1F0C0000 MOV ECX,0C1F \\长度
0041209C 8B06 MOV EAX,DWORD PTR DS:[ESI]
0041209E F7D0 NOT EAX \\解密
004120A0 8906 MOV DWORD PTR DS:[ESI],EAX
004120A2 83C6 04 ADD ESI,4
省略若干垃圾代码
004120C9 ^E2 D1 LOOPD SHORT CLSPACK1.0041209C
004120CB 61 POPAD \\光标停在这,F4
下面是第三次解密的IDC脚本:
auto RegEsi;
auto RegEax;
auto i;
auto Data;
RegEsi=0x4120cc;
RegEax=0xc1f;
for (i=0;i<RegEax;i=i+4)
{
Data=~Dword(i+RegEsi);
PatchDword(i+RegEsi,Data);
}
4.第四解密
004120D8 64:67:FF36 0000 PUSH DWORD PTR FS:[0]
004120DE 64:67:8926 0000 MOV DWORD PTR FS:[0],ESP \\又是一个SEH陷井
004120E4 B0 88 MOV AL,88
004120E6 02C0 ADD AL,AL
004120E8 CE INTO \\产生异常
004120E9 FFE0 JMP EAX
004120EB 64:67:A1 0000 MOV EAX,DWORD PTR FS:[0]
004120F0 8B20 MOV ESP,DWORD PTR DS:[EAX]
004120F2 64:67:8F06 0000 POP DWORD PTR FS:[0]
004120F8 58 POP EAX
004120F9 58 POP EAX
004120FA E8 00000000 CALL CLSPACK1.004120FF
004120FF 58 POP EAX
00412100 BE 1F114000 MOV ESI,CLSPACK1.0040111F
00412105 BB FF104000 MOV EBX,CLSPACK1.004010FF
0041210A 2BF3 SUB ESI,EBX
0041210C 03F0 ADD ESI,EAX \\解密起始地址
0041210E B9 0A0C0000 MOV ECX,0C0A \\长度
00412113 8106 B2C430E1 ADD DWORD PTR DS:[ESI],E130C4B2 \\Key
00412119 83C6 04 ADD ESI,4
0041211C ^E2 F5 LOOPD SHORT CLSPACK1.00412113
0041211E 61 POPAD \\这里F2下断点,F9,Shift+F9 停在这
下面是第四次解密的IDC脚本:
auto RegEsi;
auto Key;
auto RegEax;
auto i;
auto Data;
RegEsi=0x41211f;
Key=0xe130c4b2;
RegEax=0xc0a;
for (i=0;i<RegEax;i=i+4)
{
Data=Dword(i+RegEsi)+Key;
PatchDword(i+RegEsi,Data);
}
5.第五次解密
00412126 58 POP EAX
00412127 83C0 1B ADD EAX,1B
0041212A 50 PUSH EAX
0041212B 64:67:FF36 0000 PUSH DWORD PTR FS:[0] \\SEH陷井
00412131 64:67:8926 0000 MOV DWORD PTR FS:[0],ESP
00412137 B8 FFFFFFFF MOV EAX,-1
0041213C C600 CC MOV BYTE PTR DS:[EAX],0CC \\产生异常
0041213F FFE0 JMP EAX
00412141 64:67:A1 0000 MOV EAX,DWORD PTR FS:[0]
00412146 8B20 MOV ESP,DWORD PTR DS:[EAX]
00412148 64:67:8F06 0000 POP DWORD PTR FS:[0] \\恢复SEH
0041214E 58 POP EAX
0041214F 58 POP EAX
00412150 E8 00000000 CALL CLSPACK1.00412155
00412155 58 POP EAX
00412156 BE 76114000 MOV ESI,CLSPACK1.00401176
0041215B BB 55114000 MOV EBX,CLSPACK1.00401155
00412160 2BF3 SUB ESI,EBX
00412162 03F0 ADD ESI,EAX \\解密起始地址
00412164 B9 F50B0000 MOV ECX,0BF5 \\长度
00412169 8B06 MOV EAX,DWORD PTR DS:[ESI] \\
0041216B C1C0 10 ROL EAX,10 \\解密
0041216E 8906 MOV DWORD PTR DS:[ESI],EAX
00412170 83C6 04 ADD ESI,4
00412173 ^E2 F4 LOOPD SHORT CLSPACK1.00412169
00412175 61 POPAD \\这里F2下断点,F9,Shift+F9 停在这
下面是第五次解密的IDC脚本:
auto RegEsi;
auto RegEax;
auto i;
auto Data,Temp1,Temp2;
RegEsi=0x412176;
RegEax=0xbf5;
for (i=0;i<RegEax;i=i+4)
{
Temp1=Dword(i+RegEsi);
Temp1=Temp1<<0x10;
Temp1=Temp1&0xffff0000;
Temp2=Dword(i+RegEsi);
Temp2=Temp2>>0x10;
Temp2=Temp2&0xffff;
Data=Temp1|Temp2;
PatchDword(i+RegEsi,Data);
}
6.在当前进程堆中分配8000H字节空间,并把病毒代码复制过去,并跳到堆中执行
004122B4 50 PUSH EAX
004122B5 52 PUSH EDX
004122B6 68 00800000 PUSH 8000
004122BB 6A 09 PUSH 9
004122BD 53 PUSH EBX
004122BE FFD1 CALL ECX \\RtlAllocateHeap
\\在进程堆中分配8000H字节空间
004122C0 8BC8 MOV ECX,EAX
004122C2 0BC0 OR EAX,EAX
004122C4 5A POP EDX
004122C5 58 POP EAX
004122C6 0F84 EA2D0000 JE CLSPACK1.004150B6
004122CC 50 PUSH EAX
004122CD 51 PUSH ECX
004122CE 51 PUSH ECX
004122CF 6A 09 PUSH 9
004122D1 53 PUSH EBX
004122D2 FFD2 CALL EDX
004122D4 3D 00800000 CMP EAX,8000
004122D9 0F85 D72D0000 JNZ CLSPACK1.004150B6
004122DF 59 POP ECX
004122E0 58 POP EAX
004122E1 57 PUSH EDI
004122E2 50 PUSH EAX
004122E3 8BF9 MOV EDI,ECX
004122E5 57 PUSH EDI
004122E6 B8 FC124000 MOV EAX,CLSPACK1.004012FC ; ASCII "runtime error "
004122EB 2D 00104000 SUB EAX,<&ADVAPI32.RegSetValueExA>
004122F0 03C7 ADD EAX,EDI
004122F2 B9 4A310000 MOV ECX,314A \\需复制代码的长度
004122F7 FC CLD
004122F8 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] \\复制
004122FA FFE0 JMP EAX \\跳到堆中执行
7.判断当前系统中是否有一个名为"DELPHI"的事件,如果存在则转12 否则转8
则解密原宿主程序代码.
相关文章