有关脱壳以及脱壳实例讲解

当前流行的查壳工具主要以peid和fileinfo这两个软件为代表。

PEiD的原理是利用查特征串搜索来完成识别工作的。各种开发语言都有固定的启动代码部分,利用这点就可识别出何种语言编译的。同样,不同的壳也有其特征码,利用这点就可以识别是被何种壳所加密。PEiD提供了一个扩展接口文件userdb.txt ,用户可以自定义一些特征码,这样就可识别出新的文件类型。
 

一般的压缩壳,如Aspack等都有专用的脱壳机。而加密壳(如ASProtect,Armadillo) 一般很少有脱壳机,必须手工脱壳。手工脱壳一般情况是分三步:一是查找程序的真正入口点(OEP);二是抓取内存映像文件;三是输入表重建。(当然现在的加密壳复杂些,要考虑更多的东西)OEP是Original Entry Point缩写,即程序加壳前的真正的入口点。

如何寻找oep

外壳初始化的现场环境(各寄存器值)与原程序的现场环境是相同的。加壳程序初始化时保存各寄存器的值,外壳执行完毕,会恢复各寄存器内容。其代码形式一般如下:

PUSHFD         ; 将标志寄存器入栈保存
PUSHAD         ; push eax, ecx, edx, ebx, esp, ebp, esi, edi
……           ; 外壳代码部分
POPAD          ; pop edi, esi, ebp, esp, ebx, edx, ecx, eax
POPFD          ; 恢复标志寄存器
JMP OEP        ;
OEP: ……          ; 解压后的程序原代码

方法一:利用UPX 通用脱壳机自动脱壳

 

脱壳后的程序,利用PEid进行分析,PEid给出如下的信息:
Borland Delphi 6.0-7.0

方法二:跨段指令寻找OEP

用Ollydbg来调试脱壳 ,运行Ollydbg,点击菜单“Options/Debugging options”,选择Events项,将第一次暂停设在WinMain函数上。 Ollydbg打开实例Bandook v1.35.exe.

相关代码:
006E0440 $ 60       pushad     //一开始Ollydbg就会中断这行,这个就是外壳的入口点,注意这个pushad指令 .

如下图所示

 

绝大多数加壳程序在被加密的程序中加上一个或多个段,所以依据跨段的转移指令(JMP)就可找到真正的入口点,此时就会有POPAD/POPFD 指令出现。UPX 用了一次跨段的转移指令(JMP),在跳到OEP处会看到虚拟地址的值有一个突变,此时就能确定OEP了。

UPX壳比较简单,中断WinMain后,只需要在Ollydbg里往下翻屏,就会发现这个跨段转移指令:

 

上图相关代码如下:
006E05A2  >  61    popad            //注意这里的popad指令,和开始的pushad对应            
006E05A3  - E9 444EE7FF     jmp     005553EC  //这里跳到OEP,将光标移到这,按F4执行到这行

这句006E05A3    jmp   005553EC就是跳到OEP的指令,执行到这,UPX外壳己将程序解压完毕,并模拟Windows加载器将原始程序加载到内存, 005553EC 就是映射到内存目标程序的入口点,此时就可抓取内存映像文件了。

相关代码:
005553EC 55  push ebp
005553ED 8BEC mov ebp,esp
选择Plugins->OllyDump->Dump debugged process项,Dump保存成新的文件。

 

方法三:编译语言特点找OEP

各类语言编译的文件入口点都有一些规律,可以这利用这点来寻找入口点。

1)Delphi程序
执行程序,用LordPE(或Prodump)选dump(full)脱壳,存为dump.exe。接着用Hex Workshop打开 dump.exe,搜索文本“runtime”,搜到后,向前查找离“runtime”最近的十六进制数字“55 8B EC”,数字所在的地址就是程序的OEP。

2)Visual C程序
可以利用Visual C启动部分几个函数GetCommandLineA(W)、GetVersion、GetModuleHandleA(W)、GetStartupInfoA(W) 等来定位程序的OEP。

常见的各类编译语言的入口汇编代码都要熟悉,因为一些加密强壳会偷OEP处的代码到壳里,一般情况各编译语言入口代码都相同,到时只需要直接引用相关程序的入口代码,这给我们恢复代码带来方便。

其它技术:

通过堆栈平衡寻找OEP,通过内存断点寻找OEP

补充讲解一下windowsapi函数,这可是脱壳的时候离不开的,如果熟悉了它可以更快的找到程序的入口及程序领空

Win32 API是基于C语言的接口,但是Win32 API中的函数可以由用不同语言编写的程序调用。

Windows的主要部分有三个主要子系统,分别是Kernel/User/GDI。
Kernel:操作系统核心功能服务,包括进行与线程控制、内存管理、文件访问等;
User:负责处理用户接口,包括键盘和鼠标输入、窗口和菜单管理等;
GDI:图形设备接口,允许程序在屏幕和打印机上显示文本和图形。

 

常用Win32 API函数
GetWindowText函数,作用是取得一个窗体的标题文字,或文本控件的内容。
GetDlgItemText函数,作用是获取对话框文本。
GetModuleFileName函数
InternetOpen函数
InternetOpenURL函数
SetWindowsHookEx函数
AdjustTokenPrivileges函数
LookupPrivilegeValue函数
OpenProcessToken函数
GetCurrentProcessId函数
GetCurrentProcess函数
GetWindowThreadProcessId函数
GetComputerName函数


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值