您的位置:首页 > 其它

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

2012-07-11 16:31 183 查看
当前流行的查壳工具主要以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函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: