└文章标题┐:Obsidium 1.0.0.69标准方式加壳 ->脱壳修复
└破文作者┐:大菜一号
└破解对象┐:hello world
└下载地址┐:附件
└对象大小┐:不知
└加壳方式┐:Obsidium 1.0.0
└保护方式┐:Obsidium 1.0.0
└编写语言┐:vc
└使用工具┐:od,REC
└破解平台┐:xp
└破解声明┐:`
----------------------------------------------------------------------------------
└破解过程┐:
闲来无事,脱个壳!
突然发现,脱壳也挺好玩的,呵~去看雪主页上看了看,选择了Obsidium这个壳,因为介绍上写着“强度中等” - -
还是一个自己写的hello world,本来不打算拿它来加壳的,不过这款壳的兼容好像有点问题,拿一些其他工具进行加壳,都无法运行!
好了,加壳之后,正常运行,不过比hello world多了一个对话框,因为这款壳我没有注册!- -
用od载入,还是老方法,用最后一次异常找oep!忽略掉除了“非法访问内存异常”之外的所有异常,f9运行!
.....
程序13次异常之后运行,ctrl+f2重新载入,到达第12次异常时,堆栈说:
shift+f9运行,断这上面那句了,f2取消断点(壳有自校验)代码:0012FE54 009053D9 SE处理程序 <-脱壳者,请去9053d9这个地址上下断
要进行最后一次让程序运行的异常,则我们alt+m在第一块的code节上下断,f9运行,来到这种地方
ctrl+a让od重新分析一下程序,往上翻看,可以看到:代码:00401046 FF db FF
00401047 15 db 15
00401048 14 db 14
00401049 50 db 50 ; CHAR 'P'
0040104A 40 db 40 ; CHAR '@'
0040104B 00 db 00
0040104C 33 db 33 ; CHAR '3'
0040104D D2 db D2
代码:00401007 . 68 30 60 40 0>ascii "h0`@",0
0040100C . 6A 00 push 0
0040100E . FF15 9C504000 call dword ptr [40509C]
00401014 . 33C0 xor eax, eax
00401016 . EB FF jmp short 00401017
00401018 . 15 B0A04000 adc eax, 0040A0B0
0040101D . C2 1000 retn 10
00401020 E1 db E1 <-这里开始的Stolen Code
00401021 8B db 8B
00401022 69 db 69 ; CHAR 'i'
00401023 C7 db C7
00401024 FD db FD
00401025 56 db 56 ; CHAR 'V'
00401026 03 db 03
00401027 89 db 89
00401028 CF db CF
00401029 DB db DB
0040102A 83 db 83
0040102B E2 db E2
0040102C AD db AD
0040102D 60 db 60 ; CHAR '`'
0040102E D6 db D6
0040102F 32 db 32 ; CHAR '2'
00401030 17 db 17
00401031 0B db 0B
00401032 B8 db B8
00401033 69 db 69 ; CHAR 'i'
00401034 D8 db D8
00401035 09 db 09
00401036 97 db 97
00401037 EC db EC
00401038 4C db 4C ; CHAR 'L'
00401039 9F db 9F
0040103A DE db DE
0040103B A0 db A0
0040103C A0 db A0
0040103D 6D db 6D ; CHAR 'm'
0040103E 3E db 3E ; CHAR '>'
0040103F 8C db 8C
00401040 . 394B 8A cmp dword ptr [ebx-76], ecx
00401043 . B5 9B mov ch, 9B
00401045 . 8BFF mov edi, edi
00401047 . 15 14504000 adc eax, 00405014
0040104C . 33D2 xor edx, edx
0040104E . 8AD4 mov dl, ah
00401050 . 8915 F4844000 mov dword ptr [4084F4], edx
00401056 . 8BC8 mov ecx, eax
Stolen Code,把oep抽掉了!可以确定的是,oep在00401020处,为了修补oep,往下翻看
代码:00401058 . 81E1 FF000000 and ecx, 0FF
0040105E . 890D F0844000 mov dword ptr [4084F0], ecx
00401064 . C1E1 08 shl ecx, 8
00401067 . 03CA add ecx, edx
00401069 . 890D EC844000 mov dword ptr [4084EC], ecx
0040106F . C1E8 10 shr eax, 10
00401072 . A3 E8844000 mov dword ptr [4084E8], eax
00401077 . 33F6 xor esi, esi
00401079 . 56 push esi
0040107A . E8 160B0000 call 00401B95
0040107F . 59 pop ecx
00401080 . 85C0 test eax, eax
00401082 . 75 08 jnz short 0040108C
00401084 . 6A 1C push 1C
00401086 . E8 B0000000 call 0040113B
0040108B . 59 pop ecx
0040108C > 8975 FC mov dword ptr [ebp-4], esi
0040108F . E8 E1070000 call 00401875
00401094 . FF15 10504000 call dword ptr [405010]
<-这边,vc程序的GetVersion一般都在这里,机器码为FF 15,从这里以上的到oep处的字节全被抽掉了!
随便找一个标准的vc程序,od载入,下面代码
命令行下d 004013fb,把从字节55 8B开始到 FF 15之间的38个字节二进制粘贴到被抽掉的oep处,看到以下正常的代码:代码:004013FB >/$ 55 push ebp
004013FC |. 8BEC mov ebp, esp
004013FE |. 6A FF push -1
00401400 |. 68 B8404000 push 004040B8
00401405 |. 68 301F4000 push 00401F30 ; SE 处理程序安装
0040140A |. 64:A1 0000000>mov eax, dword ptr fs:[0]
00401410 |. 50 push eax
00401411 |. 64:8925 00000>mov dword ptr fs:[0], esp
00401418 |. 83EC 58 sub esp, 58
0040141B |. 53 push ebx
0040141C |. 56 push esi
0040141D |. 57 push edi
0040141E |. 8965 E8 mov dword ptr [ebp-18], esp
00401421 |. FF15 2C404000 call dword ptr [<&KERNEL32.GetVersion>;<-这句以上的,
现在可dump了,od插件,修改modify为1020,dump出来一个"1.exe"代码:00401020 55 push ebp
00401021 8BEC mov ebp, esp
00401023 6A FF push -1
00401025 68 B8404000 push 004040B8
0040102A 68 301F4000 push 00401F30
0040102F 64:A1 0000000>mov eax, dword ptr fs:[0]
00401035 50 push eax
00401036 64:8925 00000>mov dword ptr fs:[0], esp
0040103D 83EC 58 sub esp, 58
00401040 53 push ebx
00401041 56 push esi
00401042 57 push edi
00401043 8965 E8 mov dword ptr [ebp-18], esp
00401046 ? FF15 14504000 call dword ptr [405014] <-这句以上的都是修复后的oep
当然无法运行了!打开rec,选择这个带壳进程,oep为1020,发现无法修复无效指针n个!IAT被加密了!
看一下这句
命令行上下d 00405014,向上翻一下下!都是0x0090xxxx的dword,说起来正确的应该是0x7xxxxxx才对的!代码:00401046 ? FF15 14504000 call dword ptr [405014]<-GetVersion函数调用,证明程序调用系统里的一个函数,可以确定一个iat的地址
iat地始地址为405000,结束地址为4050a4,则大小为0xa4!引用:
00404FF4 F4 4A 90 00 ?
00405004 00 4B 90 00 0C 4B 90 00 18 4B 90 00 07 4D 90 00 .K?.K?K?M?
00405014 11 4D 90 00 3C 4B 90 00 48 4B 90 00 1B 4D 90 00 M?<K?HK?M?
00405024 60 4B 90 00 6C 4B 90 00 78 4B 90 00 84 4B 90 00 `K?lK?xK??
00405034 90 4B 90 00 9C 4B 90 00 A8 4B 90 00 B4 4B 90 00 ????
00405044 C0 4B 90 00 CC 4B 90 00 D8 4B 90 00 E4 4B 90 00 ????
00405054 F0 4B 90 00 FC 4B 90 00 08 4C 90 00 14 4C 90 00 ??L?L?
00405064 20 4C 90 00 2C 4C 90 00 38 4C 90 00 44 4C 90 00 L?,L?8L?DL?
00405074 50 4C 90 00 5C 4C 90 00 68 4C 90 00 74 4C 90 00 PL?\L?hL?tL?
00405084 80 4C 90 00 8C 4C 90 00 98 4C 90 00 A4 4C 90 00 L????
00405094 B0 4C 90 00 BC 4C 90 00 DC 4A 90 00 E8 4A 90 00 ????
Ctrl+f2重新载入带壳程序,看程序加密iat
命令行上下,d 00405000,可以看到地址里都是空的,证明壳还没填充IAT
shift+f9运行到第11次异常之后,看到IAT里的数据都填充了!则我们在第10次异常时
在00405000处下内存写入断点,让壳往IAT里填充的数据时断下来
shift+f9运行
这里esi指向00405000,而edi则为0x009xxxx之类的,翻看下面代码,小狗阿花还真不少的说!代码:00904700 893E mov dword ptr [esi], edi <-断在这里
00904702 EB 01 jmp short 00904705
用插件去掉花指令,突然发现,人生原来可以这么爽。代码:00904700 893E mov dword ptr [esi], edi
00904702 EB 01 jmp short 00904705
00904704 0A83 C70CEB02 or al, byte ptr [ebx+2EB0CC7]
0090470A A3 0B83C604 mov dword ptr [4C6830B], eax
0090470F EB 01 jmp short 00904712
00904711 6B41 EB 01 imul eax, dword ptr [ecx-15], 1
00904715 8E3B mov seg?, word ptr [ebx] ; 未定义的段寄存器
00904717 4D dec ebp
00904718 0C EB or al, 0EB
0090471A 0311 add edx, dword ptr [ecx]
0090471C 9D popfd
0090471D 0E push cs
0090471E ^ 72 8B jb short 009046AB
返回后又看到小花,再次去掉, 下面是去掉小花后的指令代码:00904700 893E mov dword ptr [esi], edi <-填充iat
00904702 90 nop
00904703 90 nop
00904704 90 nop
00904705 83C7 0C add edi, 0C
00904708 90 nop
00904709 90 nop
0090470A 90 nop
0090470B 90 nop
0090470C 83C6 04 add esi, 4
0090470F 90 nop
00904710 90 nop
00904711 90 nop
00904712 41 inc ecx <-循环计数器
00904713 90 nop
00904714 90 nop
00904715 90 nop
00904716 3B4D 0C cmp ecx, dword ptr [ebp+C]
00904719 90 nop
0090471A 90 nop
0090471B 90 nop
0090471C 90 nop
0090471D 90 nop
0090471E ^ 72 8B jb short 009046AB <-没循环填充完加密数据IAT则跳上去
00904720 90 nop <-f4到这里,让壳填充完iat
00904721 90 nop
00904722 90 nop
00904723 90 nop
00904724 90 nop
00904725 90 nop
00904726 90 nop
00904727 90 nop
00904728 833E 00 cmp dword ptr [esi], 0 <-esi指向00405098,这里还没填充
0090472B 90 nop
0090472C 90 nop
0090472D 90 nop
0090472E 90 nop
0090472F 75 64 jnz short 00904795 <-如果填充了,就跳
00904731 90 nop
00904732 90 nop
00904733 90 nop
00904734 893E mov dword ptr [esi], edi <-否则这里进行填充
00904736 90 nop
00904737 90 nop
00904738 90 nop
00904739 90 nop
0090473A 90 nop
0090473B C607 60 mov byte ptr [edi], 60
0090473E 90 nop
0090473F 90 nop
00904740 90 nop
00904741 90 nop
00904742 90 nop
00904743 90 nop
00904744 66:C747 01 66B8 mov word ptr [edi+1], 0B866
0090474A 90 nop
0090474B 90 nop
0090474C 90 nop
0090474D 90 nop
0090474E 90 nop
0090474F 90 nop
00904750 66:894F 03 mov word ptr [edi+3], cx
00904754 90 nop
00904755 90 nop
00904756 90 nop
00904757 90 nop
00904758 90 nop
00904759 90 nop
0090475A C647 05 B2 mov byte ptr [edi+5], 0B2
0090475E 90 nop
0090475F 90 nop
00904760 90 nop
00904761 90 nop
00904762 90 nop
00904763 90 nop
00904764 8857 06 mov byte ptr [edi+6], dl
00904767 90 nop
00904768 90 nop
00904769 90 nop
0090476A 90 nop
0090476B 90 nop
0090476C C647 07 E9 mov byte ptr [edi+7], 0E9
00904770 90 nop
00904771 90 nop
00904772 90 nop
00904773 90 nop
00904774 8B45 14 mov eax, dword ptr [ebp+14]
00904777 2BC7 sub eax, edi
00904779 90 nop
0090477A 90 nop
0090477B 90 nop
0090477C 90 nop
0090477D 90 nop
0090477E 83E8 0C sub eax, 0C
00904781 90 nop
00904782 90 nop
00904783 90 nop
00904784 90 nop
00904785 90 nop
00904786 90 nop
00904787 8947 08 mov dword ptr [edi+8], eax
0090478A 90 nop
0090478B 90 nop
0090478C 90 nop
0090478D 90 nop
0090478E 90 nop
0090478F 83C7 0C add edi, 0C
00904792 90 nop
00904793 90 nop
00904794 90 nop
00904795 90 nop
00904796 90 nop
00904797 90 nop
00904798 90 nop
00904799 90 nop
0090479A 8BC7 mov eax, edi
0090479C 90 nop
0090479D 90 nop
0090479E 90 nop
0090479F 2B45 18 sub eax, dword ptr [ebp+18]
009047A2 90 nop
009047A3 90 nop
009047A4 90 nop
009047A5 90 nop
009047A6 90 nop
009047A7 5F pop edi
009047A8 5E pop esi
009047A9 5B pop ebx
009047AA C9 leave
009047AB C2 1400 retn 14 <-返回吧
解释一下为什么这么改:代码:00904382 90 nop
00904383 90 nop
00904384 90 nop
00904385 90 nop
00904386 90 nop
00904387 0143 04 add dword ptr [ebx+4], eax
0090438A 90 nop
0090438B 90 nop
0090438C 90 nop
0090438D 90 nop
0090438E 90 nop
0090438F 90 nop
00904390 90 nop
00904391 90 nop
00904392 90 nop
00904393 90 nop
00904394 90 nop
00904395 90 nop
00904396 8B46 14 mov eax, dword ptr [esi+14] <-IAT偏移传到eax
00904399 90 nop
0090439A 90 nop
0090439B 90 nop
0090439C 90 nop
0090439D 90 nop
0090439E 8B56 10 mov edx, dword ptr [esi+10]
009043A1 90 nop
009043A2 90 nop
009043A3 90 nop
009043A4 90 nop
009043A5 90 nop
009043A6 0303 add eax, dword ptr [ebx] <-偏移加基址,形成IAT实际地址,为405000
009043A8 90 nop
009043A9 90 nop
009043AA 90 nop
009043AB 0353 28 add edx, dword ptr [ebx+28]
009043AE 90 nop
009043AF 90 nop
009043B0 90 nop
009043B1 90 nop
009043B2 90 nop
009043B3 FF76 04 push dword ptr [esi+4] <-dll基址进栈
009043B6 53 push ebx
009043B7 52 push edx
009043B8 50 push eax <-IAT实际地址进栈
009043B9 FF76 0C push dword ptr [esi+C]
009043BC E8 6D010000 call 0090452E <-这个call,很可疑!跟进
代码:
[ 解密函数call ]
将修改下面代码,(修改方法是辉仔yock的文章里提到了,也是看后有感才脱这个壳,大家可以去搜一搜)
0090452E C8 000000 enter 0, 0
00904532 53 push ebx
00904533 56 push esi
00904534 57 push edi
00904535 8B5D 14 mov ebx, dword ptr [ebp+14]
00904538 8B75 10 mov esi, dword ptr [ebp+10]
0090453B 8B7D 0C mov edi, dword ptr [ebp+C]
0090453E 8B5B 04 mov ebx, dword ptr [ebx+4]
00904541 66:F706 2000 test word ptr [esi], 20 <-改为test word ptr[esi],8
00904546 74 46 je short 0090458E <-改为jne 0090458e,记住0090458e这个地址
00904548 66:F706 0200 test word ptr [esi], 2
0090454D 75 1F jnz short 0090456E
0090454F 66:C706 0400 mov word ptr [esi], 4
00904554 8B45 14 mov eax, dword ptr [ebp+14]
00904557 6A 01 push 1
00904559 6A 00 push 0
0090455B FF76 04 push dword ptr [esi+4]
0090455E 6A 00 push 0
00904560 FF75 18 push dword ptr [ebp+18]
00904563 FF50 40 call dword ptr [eax+40]
00904566 85C0 test eax, eax
00904568 74 39 je short 009045A3 <-改为je 0090458e
0090456A 8907 mov dword ptr [edi], eax
0090456C EB 20 jmp short 0090458E
0090456E 66:C706 0400 mov word ptr [esi], 4
00904573 8B45 14 mov eax, dword ptr [ebp+14]
00904576 0FB756 02 movzx edx, word ptr [esi+2]
0090457A 6A 01 push 1
0090457C 52 push edx
0090457D 6A 00 push 0
0090457F FF76 04 push dword ptr [esi+4]
00904582 FF75 18 push dword ptr [ebp+18]
00904585 FF50 40 call dword ptr [eax+40]
00904588 85C0 test eax, eax
0090458A 74 17 je short 009045A3 <-改为je 0090458e
0090458C 8907 mov dword ptr [edi], eax
0090458E 83C6 08 add esi, 8
00904591 83C7 04 add edi, 4
00904594 FF4D 08 dec dword ptr [ebp+8]
00904597 ^ 75 A8 jnz short 00904541
00904599 33C0 xor eax, eax
0090459B 40 inc eax
0090459C 5F pop edi
0090459D 5E pop esi
0090459E 5B pop ebx
0090459F C9 leave
009045A0 C2 1400 retn 14
就像那篇文章所说,此壳标志一个函数为普通函数还是特殊函数!用08表示特殊函数,02表示普通函数,则,没改代码之前
test word ptr [esi], 20<-这句比较是否为普通函数
je short 0090458E <-是普通函数,则不进行处理
改为
test word ptr[esi], 08<-则,比较是否为特殊函数
jnz short 0090458e <-不是特殊函数,则不进行处理
好了`改了之后,程序就会把正确的普通函数的正确地址填充进IAT里!当然还有特殊函数!
所谓特殊函数,仔细看了一下几个未填充的IAT地址,可以确认为几个重要的启动函数,比如像GetCommandLine之类的,不解密,则程序无法运行了!处理完普通函数,返回到这里:
<-解密后,到这里,此时edi指0x405010,hex窗口中看到一下0x405010,可以看到数据是0x009xxxx代码:009043C1 90 nop < -返回到这里
009043C2 90 nop
009043C3 90 nop
009043C4 85C0 test eax, eax
009043C6 90 nop
009043C7 90 nop
009043C8 90 nop
009043C9 0F84 BB000000 je 0090448A
009043CF 90 nop
009043D0 90 nop
009043D1 90 nop
009043D2 90 nop
009043D3 90 nop
009043D4 90 nop
009043D5 90 nop
009043D6 90 nop
009043D7 837D F0 00 cmp dword ptr [ebp-10], 0
009043DB 90 nop
009043DC 90 nop
009043DD 90 nop
009043DE 90 nop
009043DF 90 nop
009043E0 90 nop
009043E1 74 37 je short 0090441A
009043E3 90 nop
009043E4 90 nop
009043E5 90 nop
009043E6 90 nop
009043E7 90 nop
009043E8 90 nop
009043E9 90 nop
009043EA 8B46 14 mov eax, dword ptr [esi+14]
009043ED 90 nop
009043EE 90 nop
009043EF 90 nop
009043F0 90 nop
009043F1 90 nop
009043F2 90 nop
009043F3 8B56 10 mov edx, dword ptr [esi+10]
009043F6 90 nop
009043F7 90 nop
009043F8 90 nop
009043F9 90 nop
009043FA 90 nop
009043FB 90 nop
009043FC 0303 add eax, dword ptr [ebx]
009043FE 90 nop
009043FF 90 nop
00904400 90 nop
00904401 90 nop
00904402 90 nop
00904403 90 nop
00904404 0353 28 add edx, dword ptr [ebx+28]
00904407 90 nop
00904408 90 nop
00904409 90 nop
0090440A 90 nop
0090440B 90 nop
0090440C FF75 F4 push dword ptr [ebp-C]
0090440F 53 push ebx
00904410 52 push edx
00904411 50 push eax
00904412 FF76 0C push dword ptr [esi+C]
00904415 E8 92010000 call 009045AC <-这个call,跟进
来到这里
代码:
009045AC C8 000000 enter 0, 0
009045B0 53 push ebx
009045B1 56 push esi
009045B2 57 push edi
009045B3 8B5D 14 mov ebx, dword ptr [ebp+14]
009045B6 8B75 10 mov esi, dword ptr [ebp+10]
009045B9 8B7D 0C mov edi, dword ptr [ebp+C]
009045BC 8B5B 04 mov ebx, dword ptr [ebx+4]
009045BF 66:833E 08 cmp word ptr [esi], 8 <-比较是否为特殊函数
009045C3 0F85 97000000 jnz 00904660 <-不是则不处理
009045C9 8B46 04 mov eax, dword ptr [esi+4]
009045CC 83F8 00 cmp eax, 0
009045CF 74 44 je short 00904615
009045D1 83F8 01 cmp eax, 1
009045D4 74 4E je short 00904624
009045D6 83F8 02 cmp eax, 2
009045D9 74 58 je short 00904633
009045DB 83F8 03 cmp eax, 3
009045DE 74 11 je short 009045F1
009045E0 83F8 04 cmp eax, 4
009045E3 75 7B jnz short 00904660
009045E5 8B45 18 mov eax, dword ptr [ebp+18]
009045E8 05 EE1DB300 add eax, 0B31DEE
009045ED 8907 mov dword ptr [edi], eax
009045EF EB 6F jmp short 00904660
009045F1 8B45 14 mov eax, dword ptr [ebp+14]
009045F4 68 C5B1662D push 2D66B1C5
009045F9 6A 00 push 0
009045FB FF50 20 call dword ptr [eax+20] <-这里进行处理.跟进
跟进后来到这里,下面是去掉小花后的指令
代码:
004144DE 90 nop
004144DF 90 nop
004144E0 90 nop
004144E1 90 nop
004144E2 90 nop
004144E3 60 pushad
004144E4 90 nop
004144E5 90 nop
004144E6 90 nop
004144E7 90 nop
004144E8 E8 00000000 call 004144ED
004144ED 90 nop
004144EE 90 nop
004144EF 90 nop
004144F0 90 nop
004144F1 5B pop ebx
004144F2 90 nop
004144F3 90 nop
004144F4 90 nop
004144F5 90 nop
004144F6 90 nop
004144F7 90 nop
004144F8 81EB C85AB300 sub ebx, 0B35AC8
004144FE 90 nop
004144FF 90 nop
00414500 90 nop
00414501 90 nop
00414502 8B9B B45AB300 mov ebx, dword ptr [ebx+B35AB4]
00414508 90 nop
00414509 90 nop
0041450A 90 nop
0041450B 90 nop
0041450C 90 nop
0041450D 90 nop
0041450E 90 nop
0041450F 90 nop
00414510 8B4424 24 mov eax, dword ptr [esp+24]
00414514 90 nop
00414515 90 nop
00414516 90 nop
00414517 90 nop
00414518 90 nop
00414519 90 nop
0041451A 90 nop
0041451B 90 nop
0041451C 90 nop
0041451D 90 nop
0041451E 33C9 xor ecx, ecx
00414520 90 nop
00414521 90 nop
00414522 90 nop
00414523 90 nop
00414524 90 nop
00414525 90 nop
00414526 8B4483 48 mov eax, dword ptr [ebx+eax*4+48]
0041452A 90 nop
0041452B 90 nop
0041452C 90 nop
0041452D 90 nop
0041452E 90 nop
0041452F 8B5424 28 mov edx, dword ptr [esp+28]
00414533 90 nop
00414534 90 nop
00414535 90 nop
00414536 90 nop
00414537 90 nop
00414538 51 push ecx
00414539 51 push ecx
0041453A 51 push ecx
0041453B 52 push edx
0041453C 50 push eax
0041453D FF53 40 call dword ptr [ebx+40] <-解密的call
00414540 90 nop
00414541 90 nop
00414542 90 nop
00414543 90 nop
00414544 90 nop
00414545 85C0 test eax, eax
00414547 90 nop
00414548 90 nop
00414549 90 nop
0041454A 90 nop
0041454B 0F84 DE010000 je 0041472F
00414551 90 nop
,说明是到这里未解密的函数,到这里还没解密的,就是特殊函数,看一下eax,第一次是GetCommandLineA的正确地址。我们得把这个地址填充到IAT里去,也就是此时的edi,
00414551 90 nop <-所以,应该把这句,改为mov [edi],eax
//到达上面那句的时候,ebx又还原成加密数据了,而edi此时还是指向刚刚的401050,则壳想把加密数据填充到IAT!所以,这里我们得nop代码:009045FE 50 push eax <-返回之后,到达这里
009045FF 53 push ebx
00904600 E8 D7030000 call 009049DC
00904605 53 push ebx
00904606 E8 46030000 call 00904951
0090460B 8BCB mov ecx, ebx
0090460D 8D5C03 01 lea ebx, dword ptr [ebx+eax+1]
00904611 8BC1 mov eax, ecx
00904613 EB 2B jmp short 00904640
00904615 8B45 14 mov eax, dword ptr [ebp+14]
00904618 68 0F1ACF4C push 4CCF1A0F
0090461D 6A 00 push 0
0090461F FF50 20 call dword ptr [eax+20]
00904622 EB 1C jmp short 00904640
00904624 8B45 14 mov eax, dword ptr [ebp+14]
00904627 68 A41A86D0 push D0861AA4
0090462C 6A 00 push 0
0090462E FF50 20 call dword ptr [eax+20]
00904631 EB 0D jmp short 00904640
00904633 8B45 14 mov eax, dword ptr [ebp+14]
00904636 68 E313B41D push 1DB413E3
0090463B 6A 00 push 0
0090463D FF50 20 call dword ptr [eax+20]
00904640 C603 B8 mov byte ptr [ebx], 0B8
00904643 8943 01 mov dword ptr [ebx+1], eax
00904646 8B55 18 mov edx, dword ptr [ebp+18]
00904649 81C2 511CB300 add edx, 0B31C51
0090464F 8D43 0A lea eax, dword ptr [ebx+A]
00904652 2BD0 sub edx, eax
00904654 C643 05 E9 mov byte ptr [ebx+5], 0E9
00904658 8953 06 mov dword ptr [ebx+6], edx
0090465B 891F mov dword ptr [edi], ebx <-nop
代码:0090465D 83C3 0A add ebx, 0A
00904660 83C6 08 add esi, 8
00904663 83C7 04 add edi, 4
00904666 8B45 14 mov eax, dword ptr [ebp+14]
00904669 8958 04 mov dword ptr [eax+4], ebx
0090466C FF4D 08 dec dword ptr [ebp+8]
0090466F ^ 0F85 4AFFFFFF jnz 009045BF
00904675 5F pop edi
00904676 5E pop esi
00904677 5B pop ebx
00904678 C9 leave
00904679 C2 1400 retn 14 <-返回
可以用rec修复iat了,虽然翻看一下iat表,末尾还是有未解密的指针,可以看到,大部份指针都解密完了代码:0090465D 83C3 0A add ebx, 0A
00904660 83C6 08 add esi, 8
00904663 83C7 04 add edi, 4
00904666 8B45 14 mov eax, dword ptr [ebp+14]
00904669 8958 04 mov dword ptr [eax+4], ebx
0090466C FF4D 08 dec dword ptr [ebp+8]
0090466F ^ 0F85 4AFFFFFF jnz 009045BF
00904675 5F pop edi
00904676 5E pop esi
00904677 5B pop ebx
00904678 C9 leave
00904679 C2 1400 retn 14 <-返回
0090441A 90 nop <-返回之后到达这里
0090441B 90 nop
0090441C 90 nop
0090441D 90 nop
0090441E 90 nop
0090441F 90 nop
00904420 83C6 18 add esi, 18
00904423 90 nop
00904424 90 nop
00904425 90 nop
00904426 90 nop
00904427 90 nop
00904428 90 nop
00904429 FF45 F8 inc dword ptr [ebp-8]
0090442C 90 nop
0090442D 90 nop
0090442E 90 nop
0090442F 90 nop
00904430 FF4D FC dec dword ptr [ebp-4]
00904433 90 nop
00904434 90 nop
00904435 90 nop
00904436 90 nop
00904437 90 nop
00904438 90 nop
00904439 ^ 0F85 1CFDFFFF jnz 0090415B <-[ebp-4]是计数器,没处理完iat就跳上去
0090443F 90 nop
00904440 90 nop
00904441 90 nop
00904442 33C0 xor eax, eax <-要改的都改完了,这里f2下断,f9运行,断下后壳已经处理完iat了!记住f2取消断点
00904444 90 nop
00904445 90 nop
00904446 90 nop
00904447 90 nop
00904448 90 nop
00904449 90 nop
0090444A 5F pop edi
0090444B 5E pop esi
0090444C 5B pop ebx
0090444D C9 leave
0090444E C3 retn <-从这里返回
0040BEE2 /EB 02 jmp short 0040BEE6 <-到达这里
0040BEE4 |6BF6 F7 imul esi, esi, -9
引用:
FThunk: 00005000 NbFunc: 00000029
1 00005000 kernel32.dll 0207 HeapDestroy
1 00005004 kernel32.dll 01B3 GetStringTypeW
1 00005008 kernel32.dll 0176 GetModuleHandleA
1 0000500C kernel32.dll 01AD GetStartupInfoA
1 00005010 kernel32.dll 010A GetCommandLineA
1 00005014 kernel32.dll 01DB GetVersion
1 00005018 kernel32.dll 00B7 ExitProcess
1 0000501C kernel32.dll 0347 TerminateProcess
1 00005020 kernel32.dll 013C GetCurrentProcess
1 00005024 kernel32.dll 0358 UnhandledExceptionFilter
1 00005028 kernel32.dll 0174 GetModuleFileNameA
1 0000502C kernel32.dll 00EF FreeEnvironmentStringsA
1 00005030 kernel32.dll 00F0 FreeEnvironmentStringsW
1 00005034 kernel32.dll 037F WideCharToMultiByte
1 00005038 kernel32.dll 014E GetEnvironmentStrings
1 0000503C kernel32.dll 0150 GetEnvironmentStringsW
1 00005040 kernel32.dll 0255 LockResource
1 00005044 kernel32.dll 01AF GetStdHandle
1 00005048 kernel32.dll 015F GetFileType
1 0000504C kernel32.dll 0151 GetEnvironmentVariableA
1 00005050 kernel32.dll 01DC GetVersionExA
1 00005054 kernel32.dll 0205 HeapCreate
1 00005058 kernel32.dll 036E VirtualFree
1 0000505C kernel32.dll 0209 HeapFree
1 00005060 kernel32.dll 02C5 RtlUnwind
1 00005064 kernel32.dll 038C WriteFile
1 00005068 kernel32.dll 00FE GetCPInfo
1 0000506C kernel32.dll 00F7 GetACP
1 00005070 kernel32.dll 018B GetOEMCP
1 00005074 kernel32.dll 0203 HeapAlloc
1 00005078 kernel32.dll 036B VirtualAlloc
1 0000507C kernel32.dll 020D HeapReAlloc
1 00005080 kernel32.dll 0198 GetProcAddress
1 00005084 kernel32.dll 0242 LoadLibraryA
1 00005088 kernel32.dll 0265 MultiByteToWideChar
1 0000508C kernel32.dll 0234 LCMapStringA
1 00005090 kernel32.dll 0235 LCMapStringW
1 00005094 kernel32.dll 01B0 GetStringTypeA
0 00005098 ? 0000 00904CBC <-这个还没有
0 0000509C ? 0000 00904ADC <-这个还没有
0 000050A0 ? 0000 00904AE8 <-这个还没有
按照脱壳高手们的职业病,先全部改为MessageBox函数,发现这三个都改为MessageBox之后,5098这个会总是无效,并把其上面一个指针拖下水!则MessageBox为user32.dll,5098作为其kernel32.dll与user32.dll的分界,这个就剪掉!
全部指针有效之后,修复抓取文件,抓出一个"1_.exe"
还是无法运行的!od载入这个"1_.exe",忽略掉所有的异常,f9运行时,出现一个错误对话框“不知如何继续,因为内存地址0090162b......”之类的,
重新载入,hex窗口看查找0090162b
0040A0B4 2B 16 90 00 00 00 00 00 00 00 00 00 00 00 00 00 <-在这个地方
我们在0040a0b4这个地方下内存访问断点,f9运行,断在这里
00402581 . /EB FF jmp short 00402582 <-垃圾东西,nop
00402583 . 15 B4A04000 adc eax, 0040A0B4 <-垃圾东西,也nop
00402588 . C3 retn
保存后运行程序,程序是可以运行了,不过结束时还有一个错误
od再载入,不忽略内存访问异常!f9运行,程序要退出的时候,堆栈说:
0012FF34 0040101D 返回到 1_.0040101D 来自 0090162A<-要修复程序者,就去40101d那里吧
我们听堆栈的话,来到40101d,发现了和上面一模一样的垃圾代码:
00401016 . /EB FF jmp short 00401017
00401018 . 15 B0A04000 adc eax, 0040A0B0
都nop掉!程序可以运行了!
----------------------------------------------------------------------------------
└经验总结┐:
壳盲的经验还是不分享的好~
----------------------------------------------------------------------------------
└版权声明┐ 本文原创于看雪软件安全论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年9月20日 11:37:51