PE学习笔记二:节的操作

节表:

节表确定了节数据的属性,数量,大小等等;

BYTE name,节的自定义名字,常见.text等等,但这并不是固定的,多数加壳程序可以修改节的名字;

uniom{DWORD VirtualSize} Misc 在内存中实际的大小

DWORD VirtualAddress 在内存中的偏移,他加上扩展PE头中的ImageBase就是在内存中真正的地址;(换句话说,他是在内存中的)

DWORD SizeOfRawData 节在文件中的大小

DWORD PointerToRawData 节区在文件中的偏移 (换句话说,他是在文件中的)

DWORD Charactetistics 节的属性  //属性这种东西,就是将字节中的数据转化为二进制,然后对着属性表查看每一个标志位

注意:没有初始化的变量,在文件中是没有位置的;
但是他在内存中是有位置的;
所以在内存中的实际大小会大于在文件中的大小;展开数据时,以MAX的值为准;


----------------------------------------------------------
所谓的RVA还有FOA

RVA:在内存中的相对地址;
内存中的地址减去扩展PE头中IMAGE_BASE起始地址,得到这个差值;

要从未展开到内存中的文件中找到一个全局变量的地址,就是这节课的学习重点;使用差值和拉伸量,计算出在第几个节中;

回到文件系统这个节和偏移量找到全局变量修改即可;

---------------------------------------------------------

在PE空白区添加代码;

直接写代码是不存在的,因为目标文件编译之后都是一堆的0和1;

再上一步,就是硬编码;

所以我们的目标其实是将硬编码注入到目标的PE文件中;(注入的文件要是直接CALL)
也就是E8开头的CALL;

然后通过jmp指令跳回去,也就是E9指令;

首先,通过VS写出代码,到反汇编,复制出硬编码指令;

如果CALL是间接CALL(FF),则使用直接CALL的形式,CALL间接的地址;

间接地址与硬编码的转化形式:

地址-直接CALL本身所在的地址-5;

那么我们要运行的这个代码地址在哪?打开OD,进入user32模块,寻找我们要调用的那个函数,ctrl+N到函数列表,找到他的地址;现在还在第一阶段,所以这个做法仅对本机生效;

E8地址并不是直接用winhex拖入文件得到的地址,而是要在内存中的地址,也就是IMAGE_BASE+偏移;

复制出CALL的硬编码;

然后通过JMP跳回,复制出JMP的硬编码;这也就是我们需要添加的代码;

地址-跳转所在的地址-5;

入口:扩展PE头中有一个程序的入口,用IMAGE_BASE+这个入口的偏移,就是程序的入口;我们用JMP跳回入口;


改好之后就可以执行了吗?

不行,因为没人调用他;

所以我们要把程序入口点改成这里,运行完了再跳回去;

这个步骤简单,只要把入口地址改成我们硬编码的头地址即可;

在投机取巧的CALL地址时,我可以使用找到目标地址,直接书写CALL指令,然后复制出硬编码的形式进行操作;


-----------------------------------------------
扩大节:

使用的工具是UE

最好不要扩大前面的节,否则要修改的地方太多了;所以我们原则上只扩大最后一个节;

1,分配一块新的空间大小S,直接右键插入即可;

2,N="(SizeOfRawData或者VirtualSize内存对齐后的值+S)"
改的时候按照16进制加,别瞎加
这里,谁大选谁作为计算单位;
将最后一个节的SizeOfRawData和VirtualSize修改为N

SizeOfRawData:最后一个节在文件中对齐的大小
VirtualSize:最后一个节在内存中对齐的大小

3,修改SizeOfImage的大小

我们扩大节肯定是为了加执行代码,所以如果节属性中没有可执行的属性,我们还要在属性里修改一下


--------------------------------------------------
新增节:

扩大节有一点小弊端,一是自己的数据和文件原本的数据混在一起;
二是如果原本节的属性是只读,我们还要回去修改,麻烦;

1,首先观察exe节表中,是否有足够的空间,40个字节,能够让我们书写进一个节的属性;

2,在节表中新增成员(第一个节一般是代码节,可执行,所以复制一下美滋滋,不用改属性了)

3,修改PE头中节的数量;

4,修改SizeOfImage的大小;

5,在原有数据的最后,新增一个节的数据,这个数据必须是内存数据的整数倍;

6,修正新增节表的属性


---------------------------------------------------
合并节:

新增节必须要求目标文件节表拥有40个字节的空间能够让我们书写;

有程序没有这40个字节;

方法一:
如果目标程序没有被处理过,那么dos头的部分有一块dos块,这部分的数据是没用的.我们只需要在MZ头的尾部,PE指针位置修改PE开始的位置,然后将其覆盖掉即可.
也就是整个代码向上提;


方法二:
方法一种,如果目标被处理过,dos块和节表都没地方了,就需要用到合并节的方法.

1,按照内存对齐展开;

2,将第一个节的内存大小,文件大小改成一样;

3,将第一个节的属性改为包含所有节的属性;

4,修改节的数量为1;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值