参阅 加密与解密 第三版;13.1;13.2;
有加壳,必有脱壳。
壳的加载过程
1 保存入口参数
加壳程序初始化时保存各寄存器的值,外壳执行完毕,再恢复各寄存器内容,最后再跳到原程序执行;
2 获取壳自己所需要使用的API地址
通过LoadLibrary或LoadLibraryEx将DLL文件映像映射到调用进程的地址空间中;然后调用GetModuleHandle()获取DLL模块句柄;DLL模块被加载,然后调用GetProcAddress函数获取输入函数的地址;外壳中用到其它函数主要用这三个函数来调用;
3 解密原程序的各个区块的数据
壳出于保护原程序代码和数据的目的,会加密原程序文件的各个区块。在程序执行时外壳将会对这些区块数据解密,以让程序能正常运行。
4 IAT的初始化
IAT的填写,本来应该由PE装载器实现。但加壳时,自己构造了一个输入表。
5 重定位项的处理
文件执行时将被映像到指定内存地址,这个初始内存地址称为基址。这是程序文件中声明的。对于exe,Win系统会尽量满足,按程序文件声明加载。对于DLL,Win系统没有办法保证每一次DLL运行时提供相同的基地址。
6 HOOK-API
程序文件中输入表的作用是让Windows系统在程序运行时提供API的实际地址给程序使用。壳一般都修改了原程序文件的输入表;然后自己来填充输入表中相关的数据。
7 跳转到程序原入口点(OEP)
这时壳把控制权交还给原程序。
手动脱壳第一步是查找程序的真正入口点。
先认识一下LordPE的使用;然后才能找OEP;此工具据说是一个很好的PE工具;这里的PE指Windows可执行文件;
下了几个LordPE;有的不能用;启动以后如下;
点 PE编辑器 按钮;加载原书13章用于练习的示例RebPE.exe;此时程序未加壳;
程序入口点是1130h;有4个区段;
使用原书第16章编写的一个加壳程序;来对上面程序加壳;
另外LordPE,点击L按钮,可查看PE文件详情;
加壳完毕;加壳后的程序被杀软认为木马;
信任;
然后用LordPE打开加壳后的exe文件;
程序入口点已经变为1300H;
并多出一个.pediy区段;按原文,此多出的区段就是外壳,相当于一个文件加载器;是否所有的壳,都会在PE里多出一个区段,就不了解;
启动ollydbg;选项;设置程序暂停点为主模块的入口点;
加载上面加壳之后的程序;按原文,因为加了壳,加载程序可能提示 所加载程序入口点超出代码范围;并没有提示;直接加载了加壳的程序;下面可以尝试查找OEP;先到这里;
因为都是对PE文件进行操作;下面先来用C#写一个程序;读取前面未加壳程序的PE信息,其中的DOS头信息;
DOS头结构是:14个word、4个word长的数组、word、word、10个word的数组、1个long;共64字节;
C#代码:
FileStream fs;
fs = new FileStream("RebPE_back.exe", FileMode.OpenOrCreate, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] dosheader = new byte[64];
dosheader = br.ReadBytes(64);
textBox1.Text = "e_magic: " + BitConverter.ToString(dosheader, 0, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_cblp: " + BitConverter.ToString(dosheader, 2, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_cp: " + BitConverter.ToString(dosheader, 4, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_crlc: " + BitConverter.ToString(dosheader, 6, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_cparhdr: " + BitConverter.ToString(dosheader, 8, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_minalloc: " + BitConverter.ToString(dosheader, 10, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_maxalloc: " + BitConverter.ToString(dosheader, 12, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_ss: " + BitConverter.ToString(dosheader, 14, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_sp: " + BitConverter.ToString(dosheader, 16, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_csum: " + BitConverter.ToString(dosheader, 18, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += " e_ip: " + BitConverter.ToString(dosheader, 20, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += " e_cs: " + BitConverter.ToString(dosheader, 22, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_lfarlc: " + BitConverter.ToString(dosheader, 24, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_ovno: " + BitConverter.ToString(dosheader, 26, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_res: " + BitConverter.ToString(dosheader, 28, 8);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_oemid: " + BitConverter.ToString(dosheader, 36, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_oeminfo: " + BitConverter.ToString(dosheader, 38, 2);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_res2: " + BitConverter.ToString(dosheader, 40, 20);
textBox1.Text += Environment.NewLine;
textBox1.Text += "e_lfanew: " + BitConverter.ToString(dosheader, 60, 4);
fs.Close();
br.Close();
添加using System.IO;
字节转换到16进制字符串使用BitConverter类;
运行情况如下;和LordPE获取的DOS头信息一致;