PE解析器与加载器编写指南

  最近准备去实习,看公司要求应该开发PE相关的查杀引擎,因此再回头复习一下PE格式,重新写一个PE解析器和PE加载器,再此记录下有关坑。

PE解析器部分:

1)如何确定节区表

  正确计算方法: pSection =  pNtHeader + sizeof(IMAGE_NT_HEADER) 。

  错误计算方法:pSection = pFile + sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADER)。

  原因:DOS_HEADER后面还留有一段数据,并不紧跟着NT_HEADER,因此你这样计算是错误的!

    

2)RVA与FOA的转换

  我们现在是PE解析,其都基于FOA,因此我们现在只讲解RVA->FOA进行转换,在后面的PELoader这块,我们再来分析FOA->RVA。

  其分析是基于节表的,循环遍历节表,判断其落在相关区间,然后在差值计算,得到对应的FOA,如下图:

  

3)导入表的解析

  导入表是当DLL加载时,根据该PE文件的导入表对其进行修复操作,之后函数找到该函数就可以找到对应的函数地址。

  现在我们来回顾一下导入表结构,其导入表结构如下:

  

  如果我们要获取整张表的数据,我们需要建立一个二维数组,对应着两行数据,因此我们设计了如下数据结构:

  

  现在,随之而来的一个问题:如何确定导入表的个数?PE文件的数据结构似乎没有一个数据表明其个数。

  答案是其连续0为结束,因此我们申请一块中间内存进行比较即可。(这种方式在PE文件解析中经常用到)。

  下面就是初始化导入表的代码,很好理解:

   

4)导出表的解析

  导出表主要是三张子表,函数名称表,函数序号表,函数地址表,这三张表用一张图就很好解决。

  

  因此我们采用如下数据结构存储:

  

  解析代码:

  先遍历函数地址表,地址和序号初始化,名字先设置为NULL,之后我们再遍历名称和序号表,根据序号将其赋值。

  

5)重定位的解析

  重定位表构造相对简单,其sizeOfBlock是加上块头部8字节的大小,计算偏移是要注意不要再加多了。

  重定位元素也很简单,以WORD为单位,但要注意高4位为0x3才有效,修复重定位表时要检查该位是否有效。

  我们开始是如下的数据结构:

  

  下面为重定位表的解析,其依然采用中间变量的方法:

  

PE加载器

  PE加载器,就是将一个PE文件映射到自己的内存,然后启动其main函数运行程序。

  一个PELoader的实现,需要有几个注意点:修复IAT表;修复重定位表;将内存属性写为可执行。

1)修复IAT表

  这里有两个函数 LoadLibrary 和 GetProcAddress,这两个函数能帮助我们很好的找到目标函数,其代码如下:

  

2)修复重定位表

  

3)修改属性并执行Main函数

  我们开始将文件映射时,其是只读属性,在修复之后如果执行Main函数会触发0xc0000005页权限访问异常。

  因此我们需要通过如下代码将其置为可执行属性,当然这里存在瑕疵,但是我们只是写个简单Demo,也没太多要求。

  

PE解析器与加载器编写指南的更多相关文章

  1. C编译器、链接器、加载器详解

    摘自http://blog.csdn.net/zzxian/article/details/16820035 C编译器.链接器.加载器详解 一.概述 C语言的编译链接过程要把我们编写的一个c程序(源代 ...

  2. Day18 (一)类的加载器

    一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这个虚拟机实例也就随之消亡. 如果在同一台计算机上同时运行多个Java程序 ...

  3. KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器

    无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...

  4. jQuery Mobile 手动显示ajax加载器,提示加载中...

    在使用jQuery Mobile开发时,有时候我们需要在请求ajax期间,显示加载提示框(例如:一个旋转图片+一个提示:加载中...).这个时候,我们可以手动显示jQuery Mobile的加载器,大 ...

  5. JavaScript AMD 模块加载器原理与实现

    关于前端模块化,玉伯在其博文 前端模块化开发的价值 中有论述,有兴趣的同学可以去阅读一下. 1. 模块加载器 模块加载器目前比较流行的有 Requirejs 和 Seajs.前者遵循 AMD规范,后者 ...

  6. xLua自定义加载器

    xLua入门基础 环境配置 github下载xLua文件: xLua是腾讯开发,据说比较先进: 下载下来后将Plugins和XLua文件夹考进项目: Plugins多平台权限:XLua和C#交互: t ...

  7. 【译】CLR类型加载器设计

    前言 本文翻译自BotR中的一篇,原文链接 Type Loader Design ,可以帮助我们了解CLR的类型加载机制(注意是Type类型,而不是Class类),文中涉及到术语或者容易混淆的地方,我 ...

  8. How Tomcat Works 读书笔记 八 加载器 上

    Java的类加载器 具体资料见 http://blog.csdn.net/dlf123321/article/details/39957175 http://blog.csdn.net/dlf1233 ...

  9. PE可执行文件加载器

    PE文件加载器 模仿操作系统,加载pe文件到内存中 该项目主要是为了检测pe的学习程度,是否都完全理解了.当然没有完全理解 实现功能的如下: 模仿操作系统,加载pe文件到内存中,然后执行待执行的pe文 ...

随机推荐

  1. Vue好书推荐

    1.Vue.js实战 从基础知识到ui组件封装和剖析,层层推进,最后两个案例实战.适合零基础入门,学完可就业.(推荐看这本) 交流地址(pdf原件):链接(点击跳转):提取码:7IsG 2.vue.j ...

  2. 你都这么拼了,面试官TM怎么还是无动于衷?

    前言 面试,对于每个人而然并不陌生,可以说是必须经历的一个过程了,小到一场考试,大到企业面试,甚至大型选秀...... 有时自己明明很努力了,但偏偏会在面试环节出了插曲,比如,紧张就是最容易出现的了. ...

  3. php实现登录失败次数限制

    需求:同一个账号在同一个IP地址连续密码输错一定次数后,这个账号是会被锁定30分钟的. 实现思路: 需要一个表(user_login_info)负责记录用户登录的信息,不管登录成功还是失败都记录.并且 ...

  4. SpringBoot整合分布式ZooKeeper和Dubbo

    ZooKeeper ZooKeeper是一个分布式的,开放远吗的分布式应用程序协调服务.它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护.域名服务.分布式同步.组服务等. 服务提供者 ...

  5. @loj - 3043@「ZJOI2019」线段树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个喜欢数据结构的女孩子,在常见的数据结构中,可怜最喜 ...

  6. 一张图搞懂Ubuntu安装时姓名、计算机名、用户名

    安装Ubuntu时会要求填写如下图的信息: 感谢:苏守坤 注意:上面的博客讲述了各自的具体含义,本篇博客只是说明这些名称在系统安装后会出现的位置.

  7. CentOS Linux release 7.7.1908 (Core)--rabbitmq用户创建以及相关防火墙端口开启问题

    增加访问用户,默认用户guest只能本地访问. #添加用户 rabbitmqctl add_user 账号 密码 rabbitmqctl add_user admin admin #分配用户标签(ad ...

  8. MySQL5.7.X 的下载和安装

    1 MySQL的下载 这里是mysql5.7.30的版本下载地址 https://dev.mysql.com/downloads/mysql/5.7.html#downloads 根据自己电脑选择合适 ...

  9. 自由切换 网页上的 ico 图标

    自由切换 网页上的   ico   图标: 第一步:      进入这个网站 :https://www.uupoop.com/ico/?action=make 第二步:      进入网站后,然后选择 ...

  10. Redis:缓存淘汰策略

    将redis用做缓存是一种非常常见的手段,然而由于内存大小的限制,会导致redis在内存空间满了以后需要处理继续存入的数据.总计有以下几种策略: volatile-ttl:在设置了过期时间的数据集里, ...