EP(Entry Point),意即程序的入口点。而OEP是程序的原始入口点,一个正常的程序只有一个EP,只有入口点被修改的程序(加壳等),才会拥有OEP。
OEP(Original Entry Point),程序的原始入口点,软件加壳就是隐藏了EP,只要我们找到程序的OEP,就可以立刻脱壳。
PUSHAD(压栈)代表程序的入口点
POPAD(出栈)代表程序的出口点,与PUSHAD相对应,一般找到这个OEP就在附近。
寻找OEP脱壳的方法
方法一:
1.用OD载入,不分析代码!
2.单步向下跟踪F8,是向下跳的让它实现
3.遇到程序往回跳的(包括循环),我们在下一句代码处按F4(或者右健单击代码,选择断点——运行到所选)
4.绿色线条表示跳转没实现,不用理会,红色线条表示跳转已经实现!
5.如果刚载入程序,在附近就有一个CALL的,我们就F7跟进去,这样很快就能到程序的OEP
6.在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7进入
7.一般有很大的跳转,比如 jmp XXXXXX 或者 JE XXXXXX 或者有RETE的一般很快就会到程序的OEP。
方法二:
ESP定理脱壳(ESP在OD的寄存器中,我们只要在命令行下ESP的硬件访问断点,就会一下来到程序的OEP了!)
1.开始就点F8,注意观察OD右上角的寄存器中ESP有没出现。
2.在命令行下:dd 0012FFA4(指在当前代码中的ESP地址),按回车!
3.选种下断的地址,下硬件访问WORD断点。
4.按一下F9运行程序,直接来到了跳转处,按下F8,到达程序OEP,脱壳
方法三:
内存跟踪:
1:用OD打开软件!
2:点击选项——调试选项——异常,把里面的忽略全部√上!CTRL+F2重载下程序!
3:按ALT+M,DA 打开内存镜象,找到第一个。rsrc.按F2下断点,
然后按SHIFT+F9运行到断点,接着再按ALT+M,DA 打开内存镜象,找到。RSRC上面的CODE,按
F2下断点!然后按SHIFT+F9,直接到达程序OEP,脱壳!
方法四:
一步到达OEP(前辈们总结的经验)
1.开始按Ctrl+F,输入:popad(只适合少数壳,包括ASPACK壳),然后按下F2,F9运行到此处
2.来到大跳转处,点下F8,脱壳之!
方法五:
1:用OD打开软件!
2:点击选项——调试选项——异常,把里面的√全部去掉!CTRL+F2重载下程序!
3:一开是程序就是一个跳转,在这里我们按SHIFT+F9,直到程序运行,记下从开始按F9到程序
运行的次数!
4:CTRL+F2重载程序,按SHIFT+F9(次数为程序运行的次数-1次
5:在OD的右下角我们看见有一个SE 句柄,这时我们按CTRL+G,输入SE句柄前的地址!
6:按F2下断点!然后按SHIFT+F9来到断点处!
7:去掉断点,按F8慢慢向下走!
8:到达程序的OEP,脱壳!
1、前置知识
ESP
esp:堆栈指针寄存器,主要用于存放堆栈内存储单元的偏移量,用它可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
栈
栈(stack)是内存中分配的一段空间。向一个栈插入新元素又称作入(push)放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈(pop),它把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
call
相当于高级语言中的函数调用。当执行call指令时,进行两步操作:将下一条的指令的地址压入栈中,再跳转到该地址处。相当于:
push ip
jmp near ptr 地址
ref && retf
与call指令相对应,将当前的ESP中指向的地址出栈,然后跳转到这个地址。相当于:
pop ip
#ret
pop IP
pop CS
#retf
2、ESP定理
为什么要保证堆栈平衡(保证数据环境)
程序在读写数据的时候是通过地址查找的,如果函数调用之前的堆栈与函数调用之后的堆栈不一致,就可能导致找不到数据或找到的数据错误,那么久有可能导致程序崩溃.
为什么要使用EBP寻址
EBP在程序的运行过程中有着特定的作用,保存数据的基址,根据这个特性,EBP一般不会被更改
但是在汇编中,函数需要用到的数据都会在运行前入栈,函数可以通过栈顶找到这些数据,所以在函数运行时,EBP就暂时失去了意义,所以我们就用它来临时保存开辟的栈底
也就是说,如果有一个数据(全局变量等)能够存储要索引的位置并且在函数运行时不会被改变,那么在函数运行时就可以用它来替代ESP去索引
如下图所示,EBP前后的值相同
找到OEP之后,右键,选择【用OllyDump脱壳调试进程】
将新PE程序保存为aaa.exe
然后运行aaa.exe
Borland Delphi 6.0 - 7.0
00509CB0 > $ 55 PUSH EBP
00509CB1 . 8BEC MOV EBP,ESP
00509CB3 . 83C4 EC ADD ESP,-14
00509CB6 . 53 PUSH EBX
00509CB7 . 56 PUSH ESI
00509CB8 . 57 PUSH EDI
00509CB9 . 33C0 XOR EAX,EAX
00509CBB . 8945 EC MOV DWORD PTR SS:[EBP-14],EAX
00509CBE . B8 20975000 MOV EAX,unpack.00509720
00509CC3 . E8 84CCEFFF CALL unpack.0040694C
Microsoft Visual C++ 6.0
00496EB8 >/$ 55 PUSH EBP ; (初始 cpu 选择)
00496EB9 |. 8BEC MOV EBP,ESP
00496EBB |. 6A FF PUSH -1
00496EBD |. 68 40375600 PUSH Screensh.00563740
00496EC2 |. 68 8CC74900 PUSH Screensh.0049C78C ; SE 处理程序安装
A1 0000000>MOV EAX,DWORD PTR FS:[0] :
00496ECD |. 50 PUSH EAX
8925 00000>MOV DWORD PTR FS:[0],ESP :
00496ED5 |. 83EC 58 SUB ESP,58
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 处理程序安装
A1 0000000>MOV EAX,DWORD PTR FS:[0] :
00403846 |. 50 PUSH EAX
8925 00000>MOV DWORD PTR FS:[0],ESP :
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>
[EAX],AL :
[EAX],AL :
[EAX],AL :
[EAX],AL :
或省略第一行的JMP
00401FBC > 68 D0D44000 push dumped_.0040D4D0
00401FC1 E8 EEFFFFFF call<jmp.&msvbvm60.ThunRTMain>
ds:[eax],al
ds:[eax],al
ds:[eax],al
ds:[eax],al
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
BCLOCK.___CPPdebugHook
PTR DS:[4EE08B]
00401653 . C1E0 02 SHL EAX,2
00401656 . A3 8FE04E00 MOV DWORD PTR DS:[4EE08F],EAX
0040165B . 52 PUSH EDX
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
0000000A =
DS:[403510] ; |Arg3 =
00000000
0040101E |. 6A 00 PUSH 0 ; |Arg2 = 00000000
[40350C] ; |Arg1 =00000000 :
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,戟星安全实验室及文章作者不为此承担任何责任。
戟星安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经戟星安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
原文始发于微信公众号(戟星安全实验室):OEP找壳和UPX脱壳的方法,赶紧收藏吧
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论