壳的概念、LordPE的使用、C#读取PE文件初步

参阅 加密与解密 第三版;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头信息一致;

发布了475 篇原创文章 · 获赞 545 · 访问量 304万+

猜你喜欢

转载自blog.csdn.net/bcbobo21cn/article/details/104666042