漏洞分析技术实践_ROP技术

1. 基础知识

1.1 栈帧

栈帧的定义:栈上保持多个栈帧实体,每个栈帧对应于一个函数执行的环境,这个执行环境主要用于存储函数参数、函数的局部变量、函数执行结束后的返回地址、临时变量和寄存器等。下面将以一个 add 函数为例介绍栈帧,函数源码如下所示:

#include<stdio.h>

int add(int a,int b){
    int c;
    c = a + b;
    printf("%d\n",c);
    return c;
}

int main(){
    int a=0,b=1;
    add(a,b);
    return 0;
}

函数调用过程:(1)main 函数将调用参数 b,a 从右向左依次压入栈中;(2)main 函数中下一条指令的地址压入返回地址;(3)跳转到 add 函数起始地址执行;(4)add 函数先压入 main函数栈帧的 ebp,保存 main 函数的基址;(5)当前 esp 的值保存到 ebp 寄存器,保存 add 函数的基址。

函数返回过程:(1)add 函数的返回值保存在 eax 寄存器中;(2)将 ebp 中 add 函数的基址传递给 esp;(3)将压入的 main 函数栈帧的 ebp 弹出,赋值给ebp;(4)跳转到返回地址,执行main 函数。

1.2 GOT与PLT

内容概述:PLT 与 GOT 是 Linux 的 ELF 格式文件定位全局变量和过程的表。ELF 格式的共享库使用 PIC 技术使代码和数据的引用与地址无关。

全局偏移表(GOT,Global Offset Table):GOT 是定位全局变量和函数的表,表中每一项都是程序要引用的全局变量或函数的地址。对于模块外部引用的全局变量和全局函数,用 GOT 表的表项内容作为地址来间接寻址。对于本模块内的静态变量和静态函数,由于与 GOT 的距离是固定的,用 GOT 表的首地址作为一个基准,用相对于该基准的偏移量来引用。

模块指的是一个程序的编译单元,通常是指一个单独的源文件或者可执行程序或动态链接库(如 .so、.dll 文件)。现代程序通常由多个模块组成,每个模块负责不同的功能或实现不同的部分代码。

过程链接表(PLT,Procedure Linkage Table):PLT 是 Linux ELF 文件中将动态链接的程序进行延迟绑定的表,即函数第一次被调用的时候才进行绑定。每个动态链接的程序和共享库都有一个 PLT 表,表中每一项都是一段代码,对应于程序要引用的全局函数。

程序对某个函数的访问都被调整为对 PLT 入口的访问。每个 PLT 入口项都对应一个 GOT 项,执行函数的过程就是跳转到相应 GOT 项存储的地址的过程。函数第一次调用时,通过 PLT 生成 GOT。函数第二次及后续调用 ,直接使用 GOT。示例

1.3 程序调试

1.3.1 源码编译

 以 print.c 程序作为示例,介绍 GOT 与 PLT 的原理,程序源码如下所示:

void print(char *s)
{
    printf("%s",s);
}

接下来使用-fPIC和-shared设置来编译这个文件,生成动态链接库。其中,-fPIC 是产生地址无关

代码,-shared 是生成共享库,具体指令如下所示:

gcc print.c -o libprint.so -fPIC -shared

编写一个头文件 print.h,来声明这个函数,源代码如下所示:

#ifndef dynamiclink_H
#define dynamiclink_H

void print(char *s);

#endif

在主程序 dynamic.c 中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值