目标:

改动PE导入表,手工给HelloWorld增加一个功能,就是启动的时候写入一条开机启动项,C:\cmd0000000000000000000000000000.exe

实现方法:

直接在注册相关自启动里面添加一个开启启动文件路径就行了。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

NewValue   C:\cmd0000000000000000000000000000.exe

代码逻辑相关:

RegCreateA()

RegSetValueExA()

RegClose()

对应汇编代码:

0001  68xxxxxxxx      Push addr @hKey

0002  68xxxxxxxx      Push addr szKey

0003  68xxxxxxxx      Push HKEY_LOCAL_MACHINE

0004  E8xxxxxxxx      Call RegCreateA

0005  6A27            Push 39

0006  68xxxxxxxx      Push addr lpszValue

0007  6A01            Push REG_SZ

0008  6A00            Push NULL

0009  68xxxxxxxx      Push addr lpszValueName

000A  FF35 xxxxxxxx   Push @hKey

000B  E8xxxxxxxx      Call RegSetValueExA

000C  FF35 xxxxxxxx   Push @hKey

000D  E8xxxxxxxx      Call RegClose

.

.

.

000E  FF25xxxxxxxx    JMP DWORD PTR [xxxxxxxx]

000F  FF25xxxxxxxx    JMP DWORD PTR [xxxxxxxx]

0010  FF25xxxxxxxx    JMP DWORD PTR [xxxxxxxx]

细化指令:

(1)64xxxxxxxx push addr @hKey

如果数据在.data段中,而传递的是地址,比如addr @hKey,则push的指令码为64h,后面紧跟着8位的地址,该地址只是了数据所在位置的VA.。即@hKey所在的VA。关于这个值得计算方法如下:

获得程序默认装载地址=0x00400000

获得数据段.data的起始RVA=0x03000

假设数据段的安排如下(注意路径不是***cmd000000.....exe,但是长度一样)

对应字节码为:

根据数据段各变量的位置,从上述所列字节码中找到@hKey所在的位置为0x00403069,所以第一条指令字节码是68 69 30 40 00。

(2)68xxxxxxxx push addr sz1

采用同样的方式 68 0B 30 40 00

(3)68xxxxxxxx push HKEY_LOCAL_MACHINE

因为HKEY_LOCAL_MACHINE是一个双字节常亮,所以压栈的字节码为68h,其后是该常量的值。

So   68 02 00 00 80

(4)E8xxxxxxxx call RgeCreateKeyA

由于这是一个段内调用,所以call的指令字节码为E8,其后跟随的则是距离真正跳转指令的偏移。偏移这么计算:

首先确定HelloWorld.exe的指令长度为24h。

其次,他要跳转过自身后面的所有指令,如下所示:

这些指令加起来长度为26h,两者相加即为call到jmp的偏移量4Ah;所以第四条指令的字节码是 E8 4A 00 00 00。

(5) 6A27  PUSH 27H

如果往栈里推入的双子可以控制在一个字节内,那么需要使用6A指令。后面直接跟一个字节的数值。

根据上面的分析方法,不难得出6-9条指令的字节码依次为:

68 42 30 40 00

6A 01

6A 00

68 39 30 40 00。

(6)FF35xxxxxxxx push @hKey

当要讲数据段制定位置的双字压入栈时,需要使用指令FF35,其跟着制定位置的VA。其实该指令可以解释为: push dword prt ds:[xxxxxxxx]。

所以第十条指令字节码是FF 35 69 30 40 00。

(7)E8xxxxxxxx call RegSetValueExA

同第四条指令,该跳转地址紧跟在第四条指令跳转的后面。现在计算操作数,长度由一下部分组成(call 的话 是直接call的距离,不是直接call VA):

1)该指令下的其他指令如下,总计0Bh个字节

2)原Helloworld.exe指令,总计24个字节。

3)第四条跳转指令FF25xxxxxxxx,总共6h个字节

以上长度加起来后结果是35h。所以第是一条指令字节码为E8 35 00 00 00。

(8) FF35 xxxxxxxx Push @hKey

第十二条指令字节码是 FF 35 69 30 40 00。

(9)E8xxxxxxxx Call RegClose

同第四条指令,该跳转地址紧跟在是一条指令后,其长度的计算包含以下几个部分:

其后再无添加代码(0h)

原Helloworld指令(24h)

第四条指令的跳转指令FF25xxxxxxxx(6h)

第是一条指令的跳转指令FF25xxxxxxxx(6h)

以上长度加起来后的结果是30h。则第十三条指令字节为E8 30 00 00 00。

(10)跳转指令

跳转指令为FF25,后面跟着要跳转到的VA地址。从前面对导入表的分析看,这三个函数地址是IAT的前三个,也就是最后一个非零IMAGE_IMAPORT_DESCRIPTOR结构中字段FirstThunk只想的位置。其地址依次为00402000 00402004 00402008,所以,最后三个跳转指令依次为:(这个地方看不懂的话就去看下之前总结的导入表那章)

FF 25 00 20 40 00

FF 25 04 20 40 00

FF 25 08 20 40 00

综上所述,新增加代码的字节码如下:

与原Helloworld的字节码相比,代码部分增加了4Ch大小。指令字节码构造完成后,接下来的任务是分析此次修改导致的PE头部的变化。

PE头部变化

1.IMAGE_SECTION_HEADER(.data).VirtualSize

新增加的常量都定义在源码的数据段主要包括以下内容:

(上面路径我改成c下的cmdaaaa...aa.exe了)

共98个字节,所以.data接的尺寸要增加64h。

2.IMAGE_DATA_DIRECORY[IAT].size

由于新增加了一个IMAGE_IMPORT_DESCRIPTOR,所以在IAT中要加入新增加的三个入口函数地址;同时,增加一个结尾的0,共四个双字,16个字节,所以IMAGE_DATA_DIRECTOY[IAT].isize要多加10h。

3.IMAGE_DATA_DIRECOTRY[IT].VirtualAddress

由于导入表的起始地址紧跟在IAT后,IAT多增加的字节数也是导入表起始位置偏移的数量,所以该字段要后移16个字节,即IMAGE_DATA_DIRECORY[IT].VirtualAddress需要多加10h。

4.IMAGE_SECTION_HEADER(.rdata).VirtualSize

1)增加一个动态链接库,就增加一个IMAGE_IMPORT_DESCRIPTOR结构,大小14h。

2)OriginalFiresThunk部分,3个新增注册表操作函数名指针和一个0结尾的指针共10h。

3)“编号/名称”部分包含以下定义:

xxRegCreateKeyA\0xxRegSetValueExA\0xxRegCkiseKey\0advapi32.dll\0\0共61个字节(3Dh)。

4)FirstThrunk部分,3个新增注册表函数名指针和一个0结尾的指针共10h。

综上所述,IMAGE_SECTION_HEADER(.rdata).VirtualSize的值需要多加71h。

5)IMAGE_DATA_DIRECTORY[IT].isize

多了一个动态库,就多出一个IMAGE_IMPORT_DESCRIPTOR结构,该结构大小为14h。即IMAGE_DATA_DIRECTORY[IT].isize多增加14h。

6.IMAGE_SECTION_HEADER(.text).VritualSize

代码段前面已经说过,增加4Ch大小。

由于插入代码而使得PE头部发生变化如下:

上面按顺序依次是:

导入表地址   [IT].VirtualAddress

导入表大小   [IT].isize

数据目录数   [IAT].isize

代码段大小   .text

增加的一些导入表相关,就是上面4说的那些,只读数据 .rdata

数据段大小 .data

手工重组

完成了指令字节码构造,明确了PE头部需要更改的字段,接下来就是手工重组部分。由于新的代码和数据与原来的代码和数据加在一起没有超出文件对其要求得粒度,所以DOS头、PE头的大部分字段不需要修改。以下是手动修改过程:

1.数据段

首先,添加程序中用到的数据。定位到HelloWorld.exe文件的800h处,从第一个字节为0的地方复制以下数据:

为什么从800h开始,因为800h是数据段:

然后修改数据段大小:

到200h的地方找到0B改成6Dh

此时的exe还是可以正常运行的。

2.代码段

找到代码段在400h处:

原来是只有这些:

然后在代码段的开始部分加入我们新增的代码,就是最上面分析的那些代码:

之后再修改

橙色是新增功能代码段,黑色是源代码段,黑色原代码段中红色部分是修改部分,因为新产生的IA被安排在IAR的头部,所以其他的调用地址必须往后调整。在程序中,一共增加了三个函数(来自同一个动态链接库),所以按照导入表的要求,在IAT表头需要增加三个函数入口地址(12个字节)和一个全0(4字节)的地址,这样,原来的入口函数地址都要往后调整10h个字节,所以FF25 JMP的IAT都向后偏移10h。

然后把.text代码段长度修改下:

找到代码段长度位置:

到1B0h处把24h改为70h:

改之后代码段长度显示也就变了:

此时的程序无法运行,因为.rdata处还没改,导入表部分还没有改。上面直接偏移了两个原来函数JMP地址。那个地址是什么还不知道呢!所以目前无法运行。

3. .rdata段

这个地方相对较难,要细心些:

首先看下原始导入表数据字节码:

去FOA=600h地方去找:

原来的样子:

修改后的内容如下(带下划线为待定部分,一会会重新计算)

新增的内容,三个函数加一个0位,是4*4

之前有两个函数,Message,和ExitProcess分别只有一个函数,每个又有一个0位,所以是

2*4+2*4最后一共20h

共涉及到3个Dll加上一个0位,20*3+20=50h

对应IAT,3个函数(3+1)*4  一个函数(1+1)*4 所有的一共4*4+2*4+2*4=20h

以上列出了导入表的四个组成部分,只要知道了代码中调用函数的个数以及链接库的个数,INT、导入表项、IAT三个大部分的大小就是固定的了。实际上,导入表的重组只需要先将第4部分也就是函数编号、函数名和动态库这一部分根据编码设置好,剩下的其他部分的数据就可以按照数据结构自行构造了。

第三个导入表项IMAGE_IMPORT_DESCRIPTOR的OriginalFirstChunk值为00002070h,他是一个RVA,转换为文件偏移地址为0x00000670、FirstChunk的值为00002000h,也是一个RVA,对应的FOA为0x00000600。

文件中IAT和INT维护了两份值相同的双字数组。

000020C6H 来源于表4-2中函数RegCreateKeyA的VA地址。由于是RVA所以要减去基地址0x00400000h。另外两个双字用同样的方法填充。构造好的第三部分代码如下:

4.修改与数据目录表项和节表想相关字段

上面说过了:

5.运行测试:

开机启动项的注册表是加上了,但是没有之前的Messagebox弹窗了。

结果往后看,书中是给了解释的(一开始第一遍做没注意,以为做错了)。

修改之后:

这个地方别改错了,书上没有告诉具体细节,我改了好几次最后找到了,JMP顺序

402018,402010,402000,402004,402008改成402010,402018,402000,402004,402008

OK就这些,所有的都搞定了。这个写了好几天,今天又是一点多了。终于整完了,明天还要上班。酱紫。

手动添加导入表修改EXE功能相关推荐

  1. 移动导入表/导入表注入(注入导入表后EXE无法运行的BUG解决方案)

    移动导入表其实不难,只需要while循环一下导入表并使用memcpy()拷贝到新加的节当中. 核心的代码如下,新增节和其他解析PE文件的最基础的东西发在最后的完整代码里. pImport_Temp = ...

  2. 瑞吉外卖-移动端菜品展示功能,购物车添加菜品及修改等功能,用户下单功能及历史订单派送功能

    整理记录下学习整个瑞吉外卖项目,详细代码可在我的Gitee仓库瑞吉外卖实战克隆下载学习使用! 12.菜品展示 12.1 需求分析 12.2 更改前台页面使其正常显示 由于购物车功能还未进行开发,所以修 ...

  3. (菜鸟要飞系列)五,基于Asp.Net MVC5的后台管理系统(添加数据表的分页功能)...

    献上代码 1 public ActionResult SelectAll(int id=1) 2 { 3 4 List<UserModel> arrayUserModel = new Li ...

  4. 注入(二):修改导入表(c++)

    导入表注入:修改游戏EXE依赖dll树上找个结点,程序运行前加载,加载修改回导入表.  优:游戏依赖库多,不易用完整性来查验,同时客户端版本不同,更易躲过检测  缺点:文件操作明显,易被Process ...

  5. pe结构分析之手工修复导入表

    目录 预备知识 实验目的 实验环境 实验步骤一 实验步骤二 实验步骤三 预备知识 本实验要求实验者具备如下的相关知识. 1.加密外壳中,破坏原程序的输入表是很关键的一步.在脱壳中,需要脱壳者对于pe格 ...

  6. C# 中手动添加Mousewheel鼠标滚轮事件

    如果将窗体或容器控件(如Panel控件)的AutoScroll属性设置为True时,那么当窗体或Panel容不下其中的子控件时就会出现 滚动条,通过移动滚动条可以上下显示出窗体或Panel中的全部内容 ...

  7. 在若依项目中添加导入excel功能

    无论是电子商务网站,还是办公网站,都免不了要把一些excel导入到数据库中的功能,若依已经为此需求提供了很不错的封装与扩展. 前提: 首先,你需要建一张表,来存储你要导入的数据.本例中表名及实例名为: ...

  8. 手动从注册表添加“从这打开CMD”命令

    需求:偶尔需要从文件管理夹打开cmd命令,进行一些简单的批处理. 解决方式:通过运行注册表编辑器来进行手动添加相关信息,达到在按住shift键后右键可实现打开"从这打开CMD"命令 ...

  9. 优化二、XWPFDocument 生成doc、docx 功能优化(循环数据可不用手动添加)可在表格中插入图片

    接上一篇文章 注:Consts 类放到了 第三篇文章里面 ** 一.优化点: ** 优化过后 直接调用 CreateWordPoiUtils 中listToArray 方法 即可: 参数为 对象集合 ...

最新文章

  1. 2008年清华大学计算机研究生机试真题
  2. 图像分类_04神经网络最优化过程:反向传播+代码实现
  3. 【Flink】ValidationException: Comparison is only supported for numeric types and comparable types
  4. C#取真实IP地址及分析
  5. 跟着杨中科学习asp.net之dom
  6. 【算法】合并两个有序链表
  7. sql server日期时间转字符串
  8. laravel 条形码
  9. 纸片人「活」了。Meta AI新作:只需几分钟,手绘小人有了灵魂
  10. 闪耀暖暖的3D建模真好吗?
  11. 淘宝店铺装修教程之下载淘宝视频及分析视频地址中的高逼格信息
  12. 一欧拉函数(Euler‘s totient function)
  13. Python 和 Java、PHP、C、C#、C++等其他语言的对比?
  14. 细线表格-今日小说排行榜
  15. 我的世界潜影盒计算机存储器,我的世界:很多人以为自己了解潜影盒,其实他们只看到了表面!...
  16. 使用CAD旋转复制命令绘制图形
  17. 【英语语法】五种基本语句
  18. 2021年N1叉车司机模拟考试题库软件及N1叉车司机全国真题汇总
  19. 跨VLAN远程开机功能实现
  20. html控制树莓派小车,用家里旧的红外遥控器控制树莓派小车

热门文章

  1. 利用FriendlyElec友善电子R2S软路由进行PPPoE拨号上网
  2. vr全景适合那些行业
  3. 使用python制作一个简易的远控终端
  4. 循环结构以及循环关键字
  5. 【笔记】Android 使用自定义矢量图,ps文件转矢量图
  6. 【转载】国内首个!南京过江隧道实现无人驾驶智能养护
  7. Zotero如何在word中引用跳转到参考文献/建立超链接
  8. SQL中 isnull()用法总结
  9. 关于翻书插件turn.js的运用
  10. linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上