找回密码
 注册
搜索
热搜: 回贴

WINDBG IDA对某木马手脱nSPACK LOADER部分分析,IDA,键盘记录

2010-1-30 18:32| 发布者: admin| 查看: 168| 评论: 0|原作者: 仙之剑缘


WINDBG IDA对某木马手脱nSPACK LOADER部分分析,IDA,键盘记录
2008年06月24日 星期二 上午 00:02
【文章标题】: WINDBG IDA对某木马手脱nSPACK LOADER部分分析

【文章作者】: 笨笨雄

【软件名称】: 灰鸽子

【下载地址】: 这东西,还是不放出来了

【使用工具】: WINDBG IDA LORDPE IMPORTREC FILEMON REGMON PEID VMWARE

【工具介绍】: WINDBG是微软出的调试器,R0下的,并且能双机调试。缺点是反汇编功能简单。IDA静态分析功能强大,缺点是动态调试功能简单。

【作者声明】: 论坛限制大,混个精华好办事,水平低,只好来新手区碰碰运气。刚啃完debugging tools for windows帮助文件里的debugger reference,写篇文章简单介绍WINDBG的使用。



----------------------------------------------------------------------



打开FILEMON跟REGMON,排除无关进程后运行木马LOADER。得知此木马通过在系统目录SYSTEM32下释放名为SERVER的文件并注册为服务作恶。



在已被感染的情况下,再次运行木马LOADER,可在FILEMON看到,先是确认SERVER的存在,然后设置文件属性,之后程序就退出了。



我猜在系统目录下建立一个假的SERVER,就对木马免疫了。(VMWARE这款虚拟机很方便还原快照,又回到无毒的环境了)



试了一下,失败了。假的SERVER被删了,然后重新建立SERVER。究竟是怎么分辨真假的?特征码识别?还是文件大小识别?为了找出对这一木马(特指这个文件,显然文件名可以随便改)的免疫方法,下面进行汇编级的分析。



----------------------------------脱壳--------------------------------



PEID查得nSPack 2.1 - 2.5 -> North Star/Liu Xing Ping [Overlay]



用WINDBG打开木马的LOADER



g $exentry



来到入口点。g命令是运行。$exentry是伪寄存器,调试器载入程序之后$exentry=EP



ba w4 0012ffc0



设置内存断点,ba代表内存断点,W代表写入,4代表4个字节,这里用ESP定律找OEP



连续g几次之后,来到下面,Access violation(非法访问)



eax=00000087 ebx=7ffde030 ecx=00010102 edx=ffffffff esi=00000000 edi=00084d99

eip=13203208 esp=0012ffa4 ebp=0012fff0 iopl=0 nv up ei pl nz na po nc

cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000202

image13140000 0xc3208:

13203208 0000 add byte ptr [eax],al ds:0023:00000087=??



看来是ANTI-DEBUG。向上滚动命令行窗口,找到最后一次能正确中断的地方



eax=00000000 ebx=7ffdf000 ecx=00010101 edx=ffffffff esi=00000000 edi=00084d98

eip=13203107 esp=0012ffa4 ebp=0012fff0 iopl=0 nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00000206

image13140000 0xc3107:

13203107 e8fffeffff call image13140000 0xc300b (1320300b)



CRTL SHIFT F5重新开始,g $exentry来到入口点后ba e1 13203107



e代表运行,1代表字节,代表指令的长度(非操作数)。



g就可以直接断在13203107了,按F8跟进,ALT 7打开反汇编窗口



1320300b b818000000 mov eax,18h

13203010 648b18 mov ebx,dword ptr fs:[eax]

13203013 83c330 add ebx,30h

13203016 c3 ret



[fs:[18h] 2]是PEB.BeingDebugged 标志,即7ffdf002,1代表被调试,0代表没有被调试



f 7ffdf002 l1 0



f代表写内存,l1代表长度为1个字节,后面是需要写进内存的数据



ba w4 0012ffc0



g,断在1314cb1b。



1314cb1a 55 push ebp

1314cb1b 8bec mov ebp,esp



这就是入口点了。



用LORDPE完整DUMP下来。运行IMPORTREC,修改入OEP为CB1A,自动查找IAT,结果没多少是可用的。右键菜单->高级命令->获取API调用。最小地址13140000,最大地址13150000。确定,现在可以看到很多无效的,也看到很多有效的,IAT似乎没加密。删掉无效的有点麻烦,没有删除的快捷键:(



按住SHIFT键选中所有无效的,右键菜单->删除指针,现在修复转存文件就OK了。



本来想介绍WINDBG本身的.dump命令,原文件就700K左右,可是DUMP下来居然有7M,不知道DUMP多了多少对于脱壳没意义的数据。用LORDPE DUMP下来的只有1M左右,经测试,至少可以顺利运行到感染你的机器了。



--------------------------------脱壳完毕------------------------------



关于下断的问题,我是直接查输入表,把所有跟文件操作有关的API都下了断。为了方便阅读,我把一些没意义的过程省略了。



用WINDBG打开已经脱壳的程序。g $exentry来到入口点

bp findfirstfilea下断,不分大小写,太好了,这在OLLYDBG可是不行的!

输入G,断在系统区域,ALT 6查看CALL STACK(调用栈)



00 0012fdf8 131463ce 00b91a1c 0012fe0c 00b91a1c kernel32!FindFirstFileA



CALL指令执行的时候会把返回地址压栈,CALL里面的第一条指令一般是PUSH EBP。所以堆栈段地址0012FXXX(XXX为任意数字)后一个数值便是返回地址了。在这个例子中131463ce 返回地址 00b91a1c 函数左边第一个参数



db 00b91a1c查看内存



00b91a1c 43 3a 5c 57 49 4e 4e 54-5c 73 79 73 74 65 6d 33 C:\WINNT\system3

00b91a2c 32 5c 73 65 72 76 72 65-00 00 00 00 16 00 00 00 2\servre........



一开始就断在正确的位置了,运气不错。用IDA打开程序,按G,输入131463ce,跳到下面sub_131463AE中。sub表示一个CALL



--------------------------sub_131463AE分析,可不看,直接跳到下一个分割线------------------------------



.nsp0:131463AE sub_131463AE proc near ; CODE XREF: sub_13146416 5 p

.nsp0:131463AE

.nsp0:131463AE FileTime = FILETIME ptr -14Ch

.nsp0:131463AE LocalFileTime = _FILETIME ptr -0Ch

.nsp0:131463AE FatTime = word ptr -4



高级语言中的函数变量在堆栈中存在,EBP为基址加上偏移访问堆栈获得变量,为了方便阅读IDA分别为偏移命名



.nsp0:131463AE push ebp

.nsp0:131463AF mov ebp, esp

.nsp0:131463B1 add esp, 0FFFFFEB4h

.nsp0:131463B7 push ebx

.nsp0:131463B8 mov ebx, eax ;把EAX的值暂存EBX

.nsp0:131463BA lea eax, [ebp FileTime]

.nsp0:131463C0 push eax ; lpFindFileData

.nsp0:131463C1 mov eax, ebx ;取回原来的值

.nsp0:131463C3 call sub_1314414E



用EAX作为传入传出参数,估计此CALL作用为对EAX的值修正,可不跟进



.nsp0:131463C8 push eax ; lpFileName

.nsp0:131463C9 call FindFirstFileA_0 ;查找文件

.nsp0:131463C9

.nsp0:131463CE cmp eax, 0FFFFFFFFh ;比较是否为-1,此处返回-1表示操作失败

.nsp0:131463D1 jz short loc_13146407 ;跳到函数最后

.nsp0:131463D1

.nsp0:131463D3 push eax ; hFindFile

.nsp0:131463D4 call FindClose_0 ;结束查找

.nsp0:131463D4

.nsp0:131463D9 test byte ptr [ebp FileTime.dwLowDateTime], 10h

.nsp0:131463E0 jnz short loc_13146407

.nsp0:131463E2 lea eax, [ebp LocalFileTime]

.nsp0:131463E5 push eax ; lpLocalFileTime

.nsp0:131463E6 lea eax, [ebp-138h]

.nsp0:131463EC push eax ; lpFileTime

.nsp0:131463ED call FileTimeToLocalFileTime ;转换文件时间的API

.nsp0:131463ED

.nsp0:131463F2 lea eax, [ebp FatTime]

.nsp0:131463F5 push eax ; lpFatTime

.nsp0:131463F6 lea eax, [ebp-2]

.nsp0:131463F9 push eax ; lpFatDate

.nsp0:131463FA lea eax, [ebp LocalFileTime]

.nsp0:131463FD push eax ; lpFileTime

.nsp0:131463FE call FileTimeToDosDateTime ;问题如上所述

.nsp0:131463FE

.nsp0:13146403 test eax, eax

.nsp0:13146405 jnz short loc_1314640E

.nsp0:13146405

.nsp0:13146407

.nsp0:13146407 loc_13146407: ; CODE XREF: sub_131463AE 23 j

.nsp0:13146407 ; sub_131463AE 32 j

.nsp0:13146407 mov dword ptr [ebp FatTime], 0FFFFFFFFh ;返回-1

.nsp0:13146407

.nsp0:1314640E

.nsp0:1314640E loc_1314640E: ; CODE XREF: sub_131463AE 57 j

.nsp0:1314640E mov eax, dword ptr [ebp FatTime]

.nsp0:13146411 pop ebx

.nsp0:13146412 mov esp, ebp ;恢复堆栈

.nsp0:13146414 pop ebp

.nsp0:13146415 retn

.nsp0:13146415

.nsp0:13146415 sub_131463AE endp



-----------------------------sub_131463AE分析完毕----------------------------------



sub_131463AE功能:

1 寻找C:\WINNT\system32\servre文件,成功则对文件时间作修正

2 成功EAX=FatTime,失败EAX=-1



现在我们需要知道哪里调用此CALL



返回WINDBG,使用gu回到程序代码,再使用一次gu跳出此CALL



经过前面的分析之后,也可以用dd ebp显示堆栈信息(dd跟db都是内存显示的命令,只是显示格式不同,根据需要选择命令)



0012ff58 0012ffc0 13146420 7ffdf000 1314cbc4

0012ff68 0012ff74 1314cc62 0012ffc0 0012ffb4

0012ff78 1314ce18 0012ffc0 000862c8 00000000



13146420就是返回地址了



IDA按G,输入13146420,来到sub_13146416



------------------sub_13146416分析,可不看,直接跳到下一个分割线----------------------



.nsp0:13146416 sub_13146416 proc near ; CODE XREF: sub_1314B9BE 59 p

.nsp0:13146416 ; sub_1314C6DE C2 p

.nsp0:13146416 ; sub_1314C6DE FA p

.nsp0:13146416 ; .nsp0:1314CBBF p

.nsp0:13146416 ; .nsp0:1314CBE3 p

.nsp0:13146416 ; .nsp0:1314CD57 p ...

.nsp0:13146416 push ebx

.nsp0:13146417 mov ebx, eax ;由sub_131463AE分析可知

.nsp0:13146419 mov eax, ebx ;这两条指令相当于NOP

.nsp0:1314641B call sub_131463AE

.nsp0:1314641B

.nsp0:13146420 inc eax ;假如EAX返回-1,EAX为0

.nsp0:13146421 setnz al ;假如不为0,al被置为1

.nsp0:13146424 pop ebx

.nsp0:13146425 retn

.nsp0:13146425

.nsp0:13146425 sub_13146416 endp



-----------------------------sub_13146416分析完毕----------------------------------



sub_13146416功能: 修正为成功EAX=1,失败EAX=0



经分析可知1314cbc4是更上一层的返回地址



IDA按G,输入1314cbc4,来到入口函数,sub_13146416是loc_1314CBAC内调用的。



.nsp0:1314CBAC loc_1314CBAC: ; CODE XREF: .nsp0:1314CB9E j

.nsp0:1314CBAC xor eax, eax ;EAX为0

.nsp0:1314CBAE push ebp

.nsp0:1314CBAF push offset s_SoiSjkSJI ; "閛i\xFF\xFF鐹k\xFF\xFF桉哱xFF\xFF?

.nsp0:1314CBB4 push dword ptr fs:[eax] ;保存上一个SEH处理函数

.nsp0:1314CBB7 mov fs:[eax], esp ;指向SEH处理函数

.nsp0:1314CBBA mov eax, dword_1314E964

.nsp0:1314CBBF call sub_13146416 ;搜索SERVER

.nsp0:1314CBC4 test al, al

.nsp0:1314CBC6 jz short loc_1314CC00 ;搜索不到就跳

.nsp0:1314CBC8 xor edx, edx

.nsp0:1314CBCA mov eax, dword_1314E964

.nsp0:1314CBCF call sub_1314644A ;设置文件属性为普通

.nsp0:1314CBD4 mov eax, dword_1314E964

.nsp0:1314CBD9 call sub_13146472 ;删除文件

.nsp0:1314CBDE mov eax, dword_1314E964

.nsp0:1314CBE3 call sub_13146416 ;再搜索SERVER

.nsp0:1314CBE8 test al, al

.nsp0:1314CBEA jz short loc_1314CC00 ;搜索不到就跳

.nsp0:1314CBEC push 0

.nsp0:1314CBEE call ExitProcess_0



注:sub_1314644A和sub_13146472都是直接调用SetFileAttributesA和DeleteFileA。没有什么好分析的



mov eax, dword_1314E964然后是CALL,出现次数频繁,现在看看那是什么



回到windbg,使用dd 1314E964



1314e964 00b91a1c 01010100 00000000 00b918ec

1314e974 00b918d8 00b91900 00000001 00000000

1314e984 00000000 00000000 00000000 00000000



还记得00b91a1c吗?findfirstfilea的第一个参数“C:\WINNT\system32\servre”的首个地址。



现在来看看loc_1314CC00,看到COPYFILEA



.nsp0:1314CC00 loc_1314CC00: ; CODE XREF: .nsp0:1314CBC6 j

.nsp0:1314CC00 ; .nsp0:1314CBEA j

.nsp0:1314CC00 lea edx, [ebp-18h]

.nsp0:1314CC03 mov eax, dword_1314E964

.nsp0:1314CC08 call sub_131464DA

.nsp0:1314CC08

.nsp0:1314CC0D mov edx, [ebp-18h]

.nsp0:1314CC10 mov eax, offset dword_1314E9C4

.nsp0:1314CC15 call sub_13143D2E

.nsp0:1314CC15

.nsp0:1314CC1A mov eax, dword_1314E9C4

.nsp0:1314CC1F call sub_1314B4A2

.nsp0:1314CC1F

.nsp0:1314CC24 push 0

.nsp0:1314CC26 mov eax, dword_1314E964

.nsp0:1314CC2B call sub_1314414E

.nsp0:1314CC2B

.nsp0:1314CC30 push eax

.nsp0:1314CC31 lea edx, [ebp-1Ch]

.nsp0:1314CC34 xor eax, eax

.nsp0:1314CC36 call sub_13142856

.nsp0:1314CC36

.nsp0:1314CC3B mov eax, [ebp-1Ch]

.nsp0:1314CC3E call sub_1314414E

.nsp0:1314CC3E

.nsp0:1314CC43 push eax

.nsp0:1314CC44 call CopyFileA



返回WINDBG,输入g 1314CC44来到call CopyFileA,F8跟进



查看CALL STACK



00 0012ff54 1314cc49 00b91a78 00b91a1c 00000000 kernel32!CopyFileA



db 00b91a78



00b91a78 44 3a 5c b9 a4 d7 f7 5c-75 6e 70 61 63 6b 2e 65 D:\....\unpack.e

00b91a88 78 65 00 00 00 00 00 00-00 00 00 00 00 00 00 00 xe..............



db 00b91a1c



00b91a1c 43 3a 5c 57 49 4e 4e 54-5c 73 79 73 74 65 6d 33 C:\WINNT\system3

00b91a2c 32 5c 73 65 72 76 72 65-00 00 00 00 16 00 00 00 2\servre........



windbg中文显示不太好...中文目录名显示不出来



总结:由分析可知,程序先检查SERVER是否存在,存在则尝试删除该文件,删除失败则退出,本来就不存在或者删除成功就把自己复制到系统目录并改名字。


最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-29 11:38 , Processed in 0.241517 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部