好友
阅读权限20
听众
最后登录1970-1-1
|
sjg8
发表于 2010-9-15 10:45
本帖最后由 sjg8 于 2010-9-15 11:07 编辑
标 题: 【原创】不同思路脱UPX加密壳及修复IAT表
作 者: rxzcums
时 间: 2008-11-03,20:39
链 接: http://bbs.pediy.com/showthread.php?t=75937
目标软件:见附件
使用工具:OllyDbg, ImportREC
首先声明:本人是壳盲,还懒,本来由于水平太差不敢班门弄斧的,可是看了szdbg大侠的文章:【原创】手脱UPX加密壳及修复IAT表,原文链接:http://bbs.pediy.com/showthread.php?t=62098,感觉这个UPX有点意思,遂下来玩玩,粗粗解决下后竟发觉手痒痒,遂产生此文!还请各位不要见笑。
我是一只小菜鸟。。。愿与大家分享。。。(哎!套话我都讲不利索:eek:)
一、查壳
PeID显示:UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo
脱壳机以失败告终,上OD吧。
二、Dump
dump的过程和正常的UPX没有任何区别,就是ESP定律,简述:
引用007DB68A > 60 pushad
007DB68B BE 00908B00 mov esi, 8B9000
007DB690 8DBE 0080B4FF lea edi, dword ptr ds:[esi+FFB48000]
007DB696 57 push edi
007DB697 83CD FF or ebp, FFFFFFFF
007DB69A EB 3A jmp short 007DB6D6 ; WishGJ.007DB6D6
007DB69C 90 nop
007DB69D 90 nop
007DB69E 90 nop
007DB69F 90 nop
007DB6A0 90 nop
007DB6A1 90 nop
007DB6A2 8A06 mov al, byte ptr ds:[esi]
007DB6A4 46 inc esi
007DB6A5 8807 mov byte ptr ds:[edi], al
F9一次断在007DB6D8:
引用007DB6D8 90 nop ; 停在这里
007DB6D9 60 pushad
007DB6DA E8 00000000 call 007DB6DF ; 第二次F9停在这里,继续!
007DB6DF 8B2C24 mov ebp, dword ptr ss:[esp]
007DB6E2 83C4 04 add esp, 4
007DB6E5 E8 500D0000 call 007DC43A ; WishGJ.007DC43A
007DB6EA E8 740D0000 call 007DC463 ; WishGJ.007DC463
007DB6EF E8 960C0000 call 007DC38A ; WishGJ.007DC38A
007DB6F4 8DB5 73260000 lea esi, dword ptr ss:[ebp+2673]
007DB6FA 8D9D 58030000 lea ebx, dword ptr ss:[ebp+358]
007DB700 33FF xor edi, edi
第三次F9,断下,代码如下:
引用007DB91C 61 popad
007DB91D - E9 F6E4DFFF jmp 005D9E18 ; 停在这里,传说中飞向光明之巅的跳板~
007DB922 83BD 231B0000 0>cmp dword ptr ss:[ebp+1B23], 0
007DB929 74 16 je short 007DB941 ; WishGJ.007DB941
007DB92B 2B85 1B1B0000 sub eax, dword ptr ss:[ebp+1B1B]
007DB931 034424 4C add eax, dword ptr ss:[esp+4C]
007DB935 50 push eax
007DB936 8B4424 50 mov eax, dword ptr ss:[esp+50]
007DB93A 8985 1F1B0000 mov dword ptr ss:[ebp+1B1F], eax
007DB940 58 pop eax
007DB941 C3 retn
再次F8一次来到OEP:
引用005D9E18 55 push ebp ; OEP!还等什么?
005D9E19 8BEC mov ebp, esp
005D9E1B 83C4 F0 add esp, -10
005D9E1E 53 push ebx
005D9E1F B8 18955D00 mov eax, 5D9518
005D9E24 E8 FFD4E2FF call 00407328 ; WishGJ.00407328
005D9E29 8B1D 40EC5D00 mov ebx, dword ptr ds:[5DEC40] ; WishGJ.005DFC38
005D9E2F E8 9899E9FF call 004737CC ; WishGJ.004737CC
005D9E34 E8 8793E9FF call 004731C0 ; WishGJ.004731C0
005D9E39 8B0B mov ecx, dword ptr ds:[ebx]
005D9E3B B2 01 mov dl, 1
005D9E3D A1 D4445A00 mov eax, dword ptr ds:[5A44D4]
005D9E42 E8 5D91FAFF call 00582FA4 ; WishGJ.00582FA4
005D9E47 8B15 80ED5D00 mov edx, dword ptr ds:[5DED80] ; WishGJ.005E23B0
005D9E4D 8902 mov dword ptr ds:[edx], eax
删除硬件断点,打开LordPE把程序dump下来,可是发生了“无法抓取进程内存”的错误!
不过没关系,右键“修正镜像大小”一下,重新dump,成功了!哈哈~
打开ImportREC,填上OEP的RVA:1D9E18,发觉指针163个无效!修不了哦。。。
三、避开IAT加密,让IAT完整现身吧!
本文重点在这里,各位看官提个神:cool:
从ImportREC的IAT开始RVA:001E31B4 去OD的数据区看看到底那里是怎么回事。
先把查看方式改成 长形->地址 以便于观察,RVA+基址400000=005E31B4,来到之后005E31B4处是dword的00,IAT应该是从005E31B8开始的,都是些什么啊!
引用005E31B4 00000000
005E31B8 00CF0000
005E31BC 00CF0017
005E31C0 00CF002E
005E31C4 00CF0045
005E31C8 00CF005C
005E31CC 00CF0073
。。。
看来IAT被毁的很厉害啊!
没关系,我们看看它们到底是怎么被毁的。
在005E31B8这行下硬件写入断点!Ctrl+F2重新载入,F9运行,第一次断下:
引用007DB86E FFB5 6B260000 push dword ptr ss:[ebp+266B]
007DB874 FFB5 67260000 push dword ptr ss:[ebp+2667]
007DB87A FF95 FF0A0000 call dword ptr ss:[ebp+AFF]
007DB880 85C0 test eax, eax
007DB882 0F84 F7090000 je 007DC27F ; WishGJ.007DC27F
007DB888 E8 F9150000 call 007DCE86 ; WishGJ.007DCE86
007DB88D C785 2F1B0000 0>mov dword ptr ss:[ebp+1B2F], 0
007DB897 8907 mov dword ptr ds:[edi], eax
007DB899 83C7 04 add edi, 4 ; 断在这里
007DB89C 8B85 6B260000 mov eax, dword ptr ss:[ebp+266B]
007DB8A2 EB 01 jmp short 007DB8A5 ; WishGJ.007DB8A5
007DB8A4 40 inc eax
007DB8A5 8038 00 cmp byte ptr ds:[eax], 0
007DB8A8 ^ 75 FA jnz short 007DB8A4 ; WishGJ.007DB8A4
观察数据窗口005E31B8处变成了这样:
引用005E31B4 00000000
005E31B8 00CF0000 ;变了
005E31BC 00000000
005E31C0 00000000
005E31C4 00000000
005E31C8 00000000
再次F9程序直接跑飞,看来005E31B8处的IAT在这之前就生成了!
所以我在007DB86E处下硬件执行断点,Ctrl+F2重新载入。
F9运行断在007DB86E处:
引用007DB86E FFB5 6B260000 push dword ptr ss:[ebp+266B] ; 断在这里
007DB874 FFB5 67260000 push dword ptr ss:[ebp+2667]
007DB87A FF95 FF0A0000 call dword ptr ss:[ebp+AFF]
007DB880 85C0 test eax, eax ; F8至此EAX显示:ntdll.RtlEnterCriticalSection
007DB882 0F84 F7090000 je 007DC27F ; WishGJ.007DC27F
007DB888 E8 F9150000 call 007DCE86 ; 看来这个call是个坏东西!
007DB88D C785 2F1B0000 0>mov dword ptr ss:[ebp+1B2F], 0 ; F8至此EAX里面的值消失了!变成00CF0000
007DB897 8907 mov dword ptr ds:[edi], eax
007DB899 83C7 04 add edi, 4
007DB89C 8B85 6B260000 mov eax, dword ptr ss:[ebp+266B]
007DB8A2 EB 01 jmp short 007DB8A5 ; WishGJ.007DB8A5
007DB86E处断下时数据窗口005E31B8处并无变化,依然是一堆00:
引用005E31B4 00000000
005E31B8 00000000
005E31BC 00000000
005E31C0 00000000
005E31C4 00000000
F8单步走,注意观察!!
当走到007DB880处,寄存器EAX显示:ntdll.RtlEnterCriticalSection
这个就是IAT开始处005E31B8所应该有的函数!继续F8看看EAX的值为什么没有写入到005E31B8。。。
当单步到007DB88D的时候发现EAX的值消失了,变成00CF0000,也就是我们第一次看见的被毁时候的值。看起来call 007DCE86是个坏东西!
Ctrl+F2重来,F9再次断在硬件执行断点007DB86E处,nop掉007DB888处的坏蛋call:
引用007DB86E FFB5 6B260000 push dword ptr ss:[ebp+266B] ; 断在这里
007DB874 FFB5 67260000 push dword ptr ss:[ebp+2667]
007DB87A FF95 FF0A0000 call dword ptr ss:[ebp+AFF]
007DB880 85C0 test eax, eax
007DB882 0F84 F7090000 je 007DC27F ; WishGJ.007DC27F
007DB888 90 nop ; nop掉的坏蛋call
007DB889 90 nop ; nop掉的坏蛋call
007DB88A 90 nop ; nop掉的坏蛋call
007DB88B 90 nop ; nop掉的坏蛋call
007DB88C 90 nop ; nop掉的坏蛋call
007DB88D C785 2F1B0000 0>mov dword ptr ss:[ebp+1B2F], 0
007DB897 8907 mov dword ptr ds:[edi], eax ; EAX中的api地址成功写入到005E31B8了!
看看,写入了第一个api地址:
引用005E31B4 00000000
005E31B8 7C93188A ntdll.RtlDeleteCriticalSection
005E31BC 00000000
005E31C0 00000000
005E31C4 00000000
005E31C8 00000000
满以为就这样程序在这里循环后就写入全部的IAT了,可是又发生了点插曲:
F9一下在硬件写入断点断下:
引用007DCE58 60 pushad
007DCE59 8B85 80200000 mov eax, dword ptr ss:[ebp+2080]
007DCE5F 8B9D 67260000 mov ebx, dword ptr ss:[ebp+2667]
007DCE65 0BC0 or eax, eax
007DCE67 75 07 jnz short 007DCE70 ; WishGJ.007DCE70
007DCE69 C747 FC 0000000>mov dword ptr ds:[edi-4], 0 ; 这里又搞鬼了!
007DCE70 3B9D 3B1B0000 cmp ebx, dword ptr ss:[ebp+1B3B] ; 断在这里
007DCE76 75 0C jnz short 007DCE84 ; WishGJ.007DCE84
007DCE78 3947 FC cmp dword ptr ds:[edi-4], eax
007DCE7B 76 07 jbe short 007DCE84 ; WishGJ.007DCE84
007DCE7D C747 FC 0000000>mov dword ptr ds:[edi-4], 0
007DCE84 61 popad
007DCE85 C3 retn
刚才写入的api又被弄成了00,是007DCE69搞的鬼!
看看这个小循环也没什么实质性的操作,只是将刚写入的IAT擦掉,别让他擦就好了。
删除原来的硬件写入断点,在段首007DCE58也下个硬件执行断点,Ctrl+F2来,F9一次,在007DB86E处断下,如下修改:
引用007DB888 E8 F9150000 call 007DCE86 ; nop掉
删除007DB86处这个硬件执行断点,再次F9,在007DCE58处断下,如下修改:
引用007DCE58 60 pushad ; 回去吧,别捣乱了!改为retn
(这样改了2处之后IAT老老实实全部写出来了,绕过IAT加密,爽:D: )
然后在前面找到的OEP:005D9E18处下个硬件执行断点,F9一下就到OEP了,拿出ImportREC抓取IAT,OK,全部有效!
修复刚才dump的文件,成功运行~~
四、感慨
深感写篇文章的艰辛!感谢写了那么多教程指引过我的大牛们! |
|