Shanghai-DCTF-2017-pwn
简单分析
简单说一说
程序漏洞不少,但是因为编译时加入的保护措施,导致大多数漏洞无法利用。比赛时一直惯性思维,认为有canary的函数就不会成功利用栈溢出进行攻击。回头才发现一个点,也算是一个比较少见的知识点,可以绕过canary的防护,从而对程序流程进行控制。
程序流程
flex_md5、flex_sha256、flex_sha1、在test security这个选项中有堆溢出、栈溢出、格式化字符串漏洞
但是格式化字符串漏洞中的格式化串不可控
栈溢出虽然是结构化的写入,但是还是绕不过canary
堆溢出这里是一次溢出无返回,没能找到什么方法能够控制ip
漏洞代码
在401148这个函数处,有一个整型下溢

输入的int会加1后转为unsigned int
在读取charset时,buf在栈上,因此可以造成栈溢出
没有局部变量可以覆盖,且有canary保护
c++ 异常处理机制 (Modern cpp)
异常抛出
使用throw语句可以在代码块中的任何地方抛出异常。throw语句的操作数决定了异常的类型,可以是任何表达式,表达式结果的类型决定了抛出异常的类型。
异常抓取
try块后面的catch块捕获任何异常。可以指定要捕获的异常类型,并且由关键字catch之后的括号中的异常声明确定。
|
|
例子
|
|
g++进行编译,在main函数处出现了异常抓取模块
在division函数处出现了异常抛出模块
关键点
异常抛出后程序会如何执行呢?
异常空间申请

异常抛出

异常抓取
caller(main)中抓取异常
__cxa_begin_catch
异常处理结束
跳转到

函数返回
关键在于,此时的栈从哪里获得?是异常抛出函数division()的栈么,还是main()的栈?
可以看到,这时的栈是main()的栈
但是main()的rbp寄存器从哪里获得?
是在异常抛出函数__cxa_throw()中从division()的栈获得的。
但是,当栈已经发生溢出了呢?
答案是,它不管!
开始日题
整型溢出–>栈溢出–>异常处理–>stack_pivot–>ROP
BUG_401148()异常抛出
flex_md5()异常处理
exp
|
|