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是否存在,存在则尝试删除该文件,删除失败则退出,本来就不存在或者删除成功就把自己复制到系统目录并改名字。 |
|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏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.