Windows PE第6章 栈与重定位表
第六章 栈与重定位表
本章主要介绍栈和代码重定位。站和重定位表两者并没有必然的联系,但都和代码有关。栈描述的是代码运行过程中,操作系统为调度程序之间相互调用关系,或临时存放操作数而设置的一种数据结构。重定位表则是在一个PE中的代码被加载到任意一个内存地址时,用来描述相关操作数地址变化规律的数据结构。通过重定位技术,代码运行在内存中的任意位置时,可以避免因操作数的定位错误而导致失败。
6.1栈
前面基本概念直接过...
程序在运行的时候会为系统分配一块内存区域作为栈,由栈选择子SS和栈定指针(esp)来确定当前栈的大小,CPU则直接操作EBP来存取数据。
内存中栈结构如下:
压栈时根据压入的数据类型的字节大小,将ESP减少相应的字节数,如压入一个双子,则ESP-4。
相反出栈的时候是esp增加相应的字节数,如弹出一个双字,则esp+4。
6.1.1 栈的应用场合
(1)保存临时的值
Push eax
......
Pop eax
(2)保存程序现场
CALL _subPrg
当指令执行时,会将紧跟在CALL指令后面的下一条指令地址压入栈,以便于程序在调用完以后,能正确放回到主程序继续运行<shell code 常用>。
(3)
传递函数参数
看下面的MessageBox调用反汇编
下面是压栈以后的示意图。
当子程序结束以后,会调用ret指令返回,eip随之被弹出。为了平衡栈,需要调用者使用如下语句将传入的参数一一弹出:
Add esp,0010h ;4个整型
(4)存放过程中的局部变量
进入一个过程后,会定义很多局部变量,而局部变量的存放处也是栈。为局部变量在栈中申请的内存区域成为缓冲区。当过程结束以后,局部变量将从栈中删除,恢复到进入过程最初状态。也就是说,局部变量在过程结束以后就自动被释放了,原因是CPU调整了栈的栈顶指针esp。
6.1.3 栈溢出
所谓栈溢出,是指由于程序没有考虑栈中定义的局部数据块的大小,而向该数据块写入了过多的数据,从而导致数据越界,覆盖了栈中的已存在的其他数据的技术。这里可以shellcode,细节不说了,之前单独总结过这里。后面都是基本定义,直接跳过,直接看重定位。
6.2 代码重定位
代码重定位是把可执行代码从内存的一个地方移动到另一个地方去,保证该部分代码还能正常执行的一种技术。用于补丁和病毒程序开发。
6.2.1 重定位的提出
可执行代码从内存的一个地方移动到另一个地方,所有的字节均保持不变;如果代码指令中的某些操作数不跟随着地址发生改变,势必会导致程序运行出错。这里的某些操作是指那些使用了绝对地址定位的程序指令中的操作数。如下:
从上面可以看出,全局变量访问直接采用了绝对地址。如果直接把这部分机器码拷贝到另一个位置,直接执行会出问题的,因为需要我们重新给代码定位才可以。
6.2.2 实现重定位的方法
先看书上的姿势:
是这样的,大体就是用相对偏移来算的,然后下面给了特长一段来解释这个,看了半天有点晕,我自己大体猜了下,然后用C++还原了这个场景。
C++代码(就直接拿上面用过的那个例子):
然后看下反汇编:
注意被圈上的那一行,后面那个***ds:[00104F18h]是直接用的映地址写的,每次编译都是随机的,我看上面书上的意思是可以根据栈弹出来的位置,也就是函数里面的某个位置来偏移过去,于是我们可以验证下,直接还是看上面红色框的部分,注意这两个值:
前面是代码地址,后面是全局变量地址,我在想,这两个差是不是固定的,于是就夺取了几组,发现差真的是固定的。
00C815D4 mov eax,dword ptr ds:[00C94F18h] 13944
000515D4 mov eax,dword ptr ds:[00064F18h] 13944
000F15D4 mov eax,dword ptr ds:[00104F18h] 13944
so应该大体知道啥姿势了,于是模拟一发:
先计算下偏移量:
得到如下结果:
pFunAddMark = 0x001a15c0 {TEST_CPP_.exe!wmain(int, wchar_t * *)}
pnNumber = 0x001b4f18 {TEST_CPP_.exe!int g_nNumber} {1111}
然后字节尝试测试一发:
这样看来结果没啥问题,如果我没理解错书上的那一坨汇编的话,应该就是这么个意思,如果理解有误希望大家留言提醒我,一起学习。
6.3 PE头文件中的重定位表
重定位信息是在编译的时候,由编译器生成并被保留在可执行文件中。当程序执行前,操作系统会根据这些重定位信息对代码予以修正,复杂的操作由编译器和操作系统代替程序完成。程序被装入内存时,其基址是由字段IMAGE——OPTIONAL_HEADER32.imageBase决定的:
但是,如果当装载时该位置已经被别的程序使用,那么操作系统就有权重新选择一个基地址。这时候就需要对所有的重定位信息进行修正,而修正的依据就是PE中的重定位表。
6.3.1 重定位表定义
重定位表为数据目录中注册的数据类型之一,其描述信息处于数据目录项的第6个目录项中:
通过上面,得到信息:
重定位表所在地址RVA=0x00018000
重定位表数据大小 =0x000010C4
结合这个:
说明存在了.reloc段。
然后根据RVA计算FOA:
FOA = 0x12C00
6.3.2 重定位表项IMAGE_BASE_RELOCATION
与导入表类似,重定位表指针指向的位置是一个数组,而不像导出表一样只有一个结构。这个数组中的每一项都是如下结构:
IMAGE_BASE_RELOCATION STRUCT
VirtualAddress dd ? ;重定位内存页的起始RVA
SizeOfBlock dd ? ;重定位块的长度
IMAGE_BASE_RELOCATION ENDS
解释下这两项:
MAGE_BASE_RELOCATION.VirtualAddress
+0000h,双字。重定位块RVA.由于直接寻址指令较多,所以在一些PE文件中,存在大量的需要修正的重定位地址。按照常规计算,每个地址占4字节,如果有n个重定位项,那么需要总的空间为4*n字节。重新审视直接寻址中的地址发现,在一页中的所有地址只需要12位(因为Win32页面大小为10000h,也就是4096字节,即2的12次方)。
而这12位只需要用两个字就能表达出来。如果有n个重定位项,则只需要2*n个地址+4字节页面起始RVA+4字节的本业的重定位项长度。将以上两种情况的表达式:
Sum0=4*n
Sum1=2*n+4+4
很明显,当有大量的重定位地址时,Sum0远大于Sum1。事实上,为了节约存储空间,重定位表的存储方式选择第二种方式。字段IMAGE_BASE_RELOCATION.VirtualAddress就是表达式Sum1中的第一个4,也就是页面起始RVA。
IMAGE_BASE_RELOCATION.SizeOfBlock
+0004h,双字。重定位块中重定位表项长度。该字段是表达式Sum1里的第二个4.
数组和数组之间并不是相邻的。比如页面1的IMAGE_BASE_RELOCATION后并不是页面2的IMAGE_BASE_RELOCATION,而是页面1的所有重定位表项;每个项大小为一个字,每个字的高四位被用来说明此重定位的类型,剩下的十二位才是需要重定位的数据在页面中的地址。高四位含义如下:
在实际的PE文件中,我们只能看到0和3这两种情况,也就是说要么是对其用的,要么是需要全部修正的。
6.3.3 重定位表的结构
Windows PE第6章 栈与重定位表的更多相关文章
- Windows Pe 第三章 PE头文件(下)
3.5 数据结构字段详解 3.5.1 PE头IMAGE_NT_HEADER的字段 1.IMAGE_NT_HEADER.Signature +0000h,双字.PE文件标识,被定义为00004550 ...
- Windows Pe 第三章 PE头文件(中)
这一章的上半部分大体介绍了下PE文件头,下半部分是详细介绍里面的内容,这一章一定要多读几遍,好好记记基础概念和知识,方便之后的学习. 简单回忆一下: 3.4 PE文件头部解析 3.4.1 DOS M ...
- Windows Pe 第三章 PE头文件(上)
第三章 PE头文件 本章是全书重点,所以要好好理解,概念比较多,但是非常重要. PE头文件记录了PE文件中所有的数据的组织方式,它类似于一本书的目录,通过目录我们可以快速定位到某个具体的章节:通过P ...
- Reverse Core 第二部分 - 16&17章 - 基址重定位表&.reloc节区
第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x00 前言 这几天忙着挖邮箱漏洞,吃火锅,马上要被关禁闭,看书进度比较 ...
- PE结构之重定位表
什么是重定位: 重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你占用,你必须转移到别的地址,这就需要基址重定位.你可能会问,不是说过每个进程都有自己独立的虚拟地址空 ...
- PE知识复习之PE的重定位表
PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思. 如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234. 如果Im ...
- PE文件 03 重定位表
0x01 重定位表结构 重定位表是由数据目录表中的第六个成员指出的: typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; D ...
- PE格式第七讲,重定位表
PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...
- WindowsPE权威指南-PE文件头中的重定位表
PE加载的过程 任何一个EXE程序会被分配4GB的内存空间,用户层处理低2G的内存,驱动处理高2G的内存. 1.双击EXE程序,操作系统开辟一个4GB的空间. 2.从ImageBase决定了加载后的基 ...
随机推荐
- 主机回来以及,简单的环境配置(RTX3070+CUDA11.1+CUDNN+TensorRT)
紧接着前几天的事: 特殊的日子,想起了当年的双(1080TI)显卡装机实录 和 炼丹炉买不起了:聊一聊这段日子的显卡行情 之后,决定买一台整机玩玩. 而现在,主机终于回!来!了!主机回来干什么,当然是 ...
- 面试必备——Java多线程与并发(二)
1.synchroized相关(锁的是对象,不是代码) (1)线程安全问题的主要原因 存在共享数据(也称临界资源) 存在多线程共同操作这些共享数据 解决:同一时刻有且只有一个线程在操作共享数据,其他线 ...
- 虚拟机安装centos系统【史上最详细的】
因为文章中有很多的图片,在博客园中还需要单张上传,所以使用了将markdown的文件链接存入网盘中让大家下载 windows系统请使用Typora软件打开 如果不知道Typora是什么软件,请在百度搜 ...
- C# 读取Word文本框中的文本、图片和表格(附VB.NET代码)
[概述] Word中可插入文本框,在文本框中可添加文本.图片.表格等内容.本篇文章通过C#程序代码介绍如何来读取文本框中的文本.图片和表格等内容.附VB.NET代码,有需要可作参考. [程序环境] 程 ...
- GET跟POST的区别
GET.POST的区别: 一.GET在浏览器后退时候,可以还原表单大部分数据,POST当浏览器后退时,表单数据将会丢失 二.GET产生的 URL 请求地址可以 Bookmark,而POST不可以 三. ...
- 技术分享PPT整理(一):Bootstrap基础与应用
最近在复习的时候总感觉有些知识点总结过,但是翻了一下博客没有找到,才想起来有一些内容是放在部门的技术分享里的,趁这个时候跳了几篇相对有价值的梳理一下,因为都是PPT,所以内容相对零散,以要点和图片为主 ...
- 1 [main] DEBUG Sigar - no sigar-amd64-winnt.dll in java.library.path org.hyperic.sigar.SigarException: no sigar-amd64-winnt.dll in java.library.path
github上一个java项目,在myeclipse中运行正常,生成jar后,运行报错: 1 [main] DEBUG Sigar - no sigar-amd64-winnt.dll in java ...
- MIT 6.824拾遗(一)聊聊basic-paxos
前言 The Paxos algorithm, when presented in plain English, is very simple. ------ Lamport,<Paxos Ma ...
- SSH&SSM
SSH和SSM的区别 SSH是Spring+Struts+Hibernate的缩写,是一种Web应用程序开源框架.框架系统分为四层:表选层.业务逻辑层.数据持久层和模块层.SSM是Spring+Spr ...
- Hive中静态分区和动态分区总结
目录 背景 第一部分 静态分区 第二部分 动态分区 第三部分 两者的比较 第四部分 动态分区使用的问题 参考文献及资料 背景 在Hive中有两种类型的分区:静态分区(Static Partitioni ...