12   1  /  2  页   跳转

[讲义] 基础脱壳教程-第二课

基础脱壳教程-第二课

这一课,来讲一下在程序运行时,加壳和未加壳程序的区别,另外根据原理,来单步跟踪,直到找到加了UPX壳的记事本的程序真实入口点

keywords:区段(session),程序真实入口点(Original Entry Point,OEP)




先来看一张图:


 附件: 您所在的用户组无法下载或查看附件

这里分别是原来的和加了UPX壳的XP系统的记事本程序。

从图中我们可以知道一些关键信息:
1,左边的是VC debug模式编译的;右边的被加了UPX的壳。
2,左边的,区段分别为:.text(代码段),.data(数据段),.rsrc(资源段);右边的,区段分别为:.UPX0,.UPX1,.rsrc(资源段)。
3,左边的,入口点为:0000739D,位于代码段;右边的,入口点为:00014240,位于UPX1区段。

对于UPX,它会把代码和数据压缩后,放到UPX0区段里,运行时,先在UPX1区段把UPX0里的代码和数据解压,然后跳到OEP继续执行



接下来,我来图解一下两种不同的结构对应的运行方式。

 附件: 您所在的用户组无法下载或查看附件


 附件: 您所在的用户组无法下载或查看附件

从上面的图中,我们已经了解了UPX的解压执行原理,那么我们可以按照该原理来脱壳。


按原理总结出的方法为:
1,一直往下执行,直到代码和数据解压完毕;
2,解压完毕后,会有一个向上的跳转,这是跳到解压后的代码继续执行的,我们跟过去(call和ret指令,可以当作另类的jmp);
3,在OEP处,DUMP程序并修复IAT(这里可以直接使用OD的OLLYDUMP插件)。




具体操作,就请参照xiaomajia52的视频,然后自己尝试一下,有什么问题请提出来。

这一课就讲到这里了,下一课,将讲解ESP定律的概念和操作方法。谢谢!

用户系统信息:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; MAXTHON 2.0)
最后编辑zapline 最后编辑于 2009-08-15 16:36:23
毕竟回忆是远了暗了的暮霭,希望才是近了亮了的晨光!
分享到:
gototop
 

回复: 基础脱壳教程-第二课

这是例子:含XP原版记事本和加了UPX的记事本

 附件: 您所在的用户组无法下载或查看附件
毕竟回忆是远了暗了的暮霭,希望才是近了亮了的晨光!
gototop
 

回复:基础脱壳教程-第二课

很好很强大

上面那个代码查看器那里。 看到的代码段的表头那有两组偏移、大小。有什么区别呀。。。V偏移和R便宜V大小和R大小 分别代表什么 还有标志是做什么用的。。?
gototop
 

回复: 基础脱壳教程-第二课



引用:
原帖由 Lighting_Cui 于 2009-8-15 16:38:00 发表
很好很强大

上面那个代码查看器那里。 看到的代码段的表头那有两组偏移、大小。有什么区别呀。。。V偏移和R便宜V大小和R大小 分别代表什么 还有标志是做什么用的。。?


V----Virtual  虚拟
R----Raw 原始(文件)
分别是虚拟偏移量,虚拟偏移大小,文件偏移量,文件偏移大小

因为应用程序,加载到内存中,各区段并不是连续的,所以存在这些。

相关的换算关系为:
1,先得到偏移量的差值
例如.text段,为:1000 - 400 = C00 ....该值记为K
2,记加载到内存中,镜像的基址为ImageBase
3,存在公式:
    File Offset = VA - ImageBase - K  (其中VA为VirtualAddress,即内存中的某个虚拟地址)
   
例如:
一虚拟地址(VA)为 00404111,它在.text区段中
那么,它在文件中的偏移为:FO = VA - IB -K = 404111 - 400000 - C00 = ***(懒得算)
所以说,该地址,在文件中的位置就是***了

至于标志, 就是个标志嘛,有时候程序运行出错,会提示********段加载错误
最后编辑zapline 最后编辑于 2009-08-15 17:52:48
毕竟回忆是远了暗了的暮霭,希望才是近了亮了的晨光!
gototop
 

回复:基础脱壳教程-第二课

很深刻~  谢谢ZAP大    还有个问题。。为什么脱壳以后程序变大了。。相比加壳前也变大了。。。80->40->120?
gototop
 

回复: 基础脱壳教程-第二课



引用:
原帖由 Lighting_Cui 于 2009-8-15 17:59:00 发表
很深刻~  谢谢ZAP小  还有个问题。。为什么脱壳以后程序变大了。。相比加壳前也变大了。。。80->40->120?


因为脱壳后,程序里还含有解密部分的代码,所以比加壳前的要大

对于某些脱壳高手(例如我的偶像fly大侠)来说,脱壳后还会对脱好的程序进行优化,让其尽量接近加壳前的程序。这称之为“完美脱壳”
毕竟回忆是远了暗了的暮霭,希望才是近了亮了的晨光!
gototop
 

回复:基础脱壳教程-第二课

果然高深  期待后续教程~~~
gototop
 

回复:基础脱壳教程-第二课

怎么判别自己是否到了OEP
gototop
 

回复: 基础脱壳教程-第二课



引用:
原帖由 smallyou93 于 2009-8-15 18:29:00 发表
怎么判别自己是否到了OEP


一般来说,根据两方面来判断

1,正如所画的运行图,可知跳到OEP是跳很远的(跨区段的),所以,遇到这样的跳转,很可能就是去OEP了

2,常见的编程工具编译的程序,同种工具编译,OEP是类似,我们需要记住的。例如常见的有:



引用:

Borland Delphi 6.0 - 7.0
004664A0 > 55 PUSH EBP
004664A1 8BEC MOV EBP,ESP
004664A3 83C4 F0 ADD ESP,-10
004664A6 53 PUSH EBX
004664A7 B8 90624600 MOV EAX,PerfectC.00466290
004664AC E8 7705FAFF CALL PerfectC.00406A28
004664B1 8B1D C4814600 MOV EBX,DWORD PTR DS:[4681C4] ; PerfectC.00469BB0
004664B7 8B03 MOV EAX,DWORD PTR DS:[EBX]
004664B9 E8 EE5AFFFF CALL PerfectC.0045BFAC
004664BE 8B03 MOV EAX,DWORD PTR DS:[EBX]
004664C0 BA 40654600 MOV EDX,PerfectC.00466540
004664C5 E8 E256FFFF CALL PerfectC.0045BBAC
004664CA 8B0D B8824600 MOV ECX,DWORD PTR DS:[4682B8] ; PerfectC.00469BF8
004664D0 8B03 MOV EAX,DWORD PTR DS:[EBX]
004664D2 8B15 E81A4600 MOV EDX,DWORD PTR DS:[461AE8] ; PerfectC.00461B34
004664D8 E8 E75AFFFF CALL PerfectC.0045BFC4
004664DD 8B0D F0824600 MOV ECX,DWORD PTR DS:[4682F0] ; PerfectC.00469BD8




引用:

Microsoft Visual C++ 6.0 [Overlay] E语言
00403831 >/$ 55 PUSH EBP
00403832 |. 8BEC MOV EBP,ESP
00403834 |. 6A FF PUSH -1
00403836 |. 68 F0624000 PUSH Nisy521.004062F0
0040383B |. 68 A44C4000 PUSH Nisy521.00404CA4 ; SE 处理程序安装
00403840 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
00403846 |. 50 PUSH EAX
00403847 |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP



引用:

vc8.0
00475E9A > E8 B9CE0000          call Unpack_e.00482D58
00475E9F ^ E9 16FEFFFF          jmp Unpack_e.00475CBA
00475EA4    55                  push ebp
00475EA5    8BEC                mov ebp,esp
00475EA7    51                  push ecx
00475EA8    53                  push ebx
00475EA9    8B45 0C              mov eax,dword ptr ss:[ebp+C]
00475EAC    83C0 0C              add eax,0C
00475EAF    8945 FC              mov dword ptr ss:[ebp-4],eax
00475EB2    64:8B1D 00000000    mov ebx,dword ptr fs:[0]
00475EB9    8B03                mov eax,dword ptr ds:[ebx]
00475EBB    64:A3 00000000      mov dword ptr fs:[0],eax



引用:


Microsoft Visual Basic 5.0 / 6.0
00401166 - FF25 6C104000 JMP DWORD PTR DS:[<&MSVBVM60.#100>] ; MSVBVM60.ThunRTMain
0040116C > 68 147C4000 PUSH PACKME.00407C14
00401171 E8 F0FFFFFF CALL <JMP.&MSVBVM60.#100>
00401176 0000 ADD BYTE PTR DS:[EAX],AL
00401178 0000 ADD BYTE PTR DS:[EAX],AL
0040117A 0000 ADD BYTE PTR DS:[EAX],AL
0040117C 3000 XOR BYTE PTR DS:[EAX],AL
或省略第一行的JMP
00401FBC > 68 D0D44000 push dumped_.0040D4D0
00401FC1 E8 EEFFFFFF call <jmp.&msvbvm60.ThunRTMain>
00401FC6 0000 add byte ptr ds:[eax],al
00401FC8 0000 add byte ptr ds:[eax],al
00401FCA 0000 add byte ptr ds:[eax],al
00401FCC 3000 xor byte ptr ds:[eax],al
00401FCE 0000 add byte ptr ds:[eax],al



引用:


BC++
0040163C > $ /EB 10 JMP SHORT BCLOCK.0040164E
0040163E |66 DB 66 ; CHAR 'f'
0040163F |62 DB 62 ; CHAR 'b'
00401640 |3A DB 3A ; CHAR ':'
00401641 |43 DB 43 ; CHAR 'C'
00401642 |2B DB 2B ; CHAR '+'
00401643 |2B DB 2B ; CHAR '+'
00401644 |48 DB 48 ; CHAR 'H'
00401645 |4F DB 4F ; CHAR 'O'
00401646 |4F DB 4F ; CHAR 'O'
00401647 |4B DB 4B ; CHAR 'K'
00401648 |90 NOP
00401649 |E9 DB E9
0040164A . |98E04E00 DD OFFSET BCLOCK.___CPPdebugHook
0040164E > \A1 8BE04E00 MOV EAX,DWORD PTR DS:[4EE08B]
00401653 . C1E0 02 SHL EAX,2
00401656 . A3 8FE04E00 MOV DWORD PTR DS:[4EE08F],EAX
0040165B . 52 PUSH EDX
0040165C . 6A 00 PUSH 0 ; /pModule = NULL
0040165E . E8 DFBC0E00 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401663 . 8BD0 MOV EDX,EAX



引用:

Dasm:
00401000 >/$ 6A 00 PUSH 0 ; /pModule = NULL
00401002 |. E8 C50A0000 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA
00401007 |. A3 0C354000 MOV DWORD PTR DS:[40350C],EAX
0040100C |. E8 B50A0000 CALL <JMP.&KERNEL32.GetCommandLineA> ; [GetCommandLineA
00401011 |. A3 10354000 MOV DWORD PTR DS:[403510],EAX
00401016 |. 6A 0A PUSH 0A ; /Arg4 = 0000000A
00401018 |. FF35 10354000 PUSH DWORD PTR DS:[403510] ; |Arg3 = 00000000
0040101E |. 6A 00 PUSH 0 ; |Arg2 = 00000000
00401020 |. FF35 0C354000 PUSH DWORD PTR DS:[40350C] ; |Arg1 = 00000000
毕竟回忆是远了暗了的暮霭,希望才是近了亮了的晨光!
gototop
 

回复: 基础脱壳教程-第二课



引用:
原帖由 smallyou93 于 2009-8-15 18:29:00 发表
怎么判别自己是否到了OEP


两个理由。
1 教程里写了 UPX壳是个压缩壳子 完成解压后会有一个向上的跳转


2在POPAD之后的循环,仔细观察栈区,它在做的事对栈使用过后的清理工作。通过这个也可以认为 在清理完成后的下一个动作应该是跳转到OEP






(个人观点 欢迎拍砖)
gototop
 
12   1  /  2  页   跳转
页面顶部
Powered by Discuz!NT