此题的代码量很大,看了一整天的逻辑代码,没发现什么问题...
整个函数的逻辑主要是红框中两个指针的循环赋值和调用,其中第一个指针是主功能函数,第二个数组是子功能函数。
函数的漏洞主要在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 ' file = '/bin/sh ' + '