当前位置:首页|资讯

【pwn20 2024羊城杯初赛 logger】

作者:K3yB0ard发布时间:2024-10-07

2024羊城杯初赛的一道pwn。有关C语言的异常捕获机制。

首先看一下程序保护

checksec

程序没开pie保护。

看一下main逻辑:

main

像是菜单题,menu如下:

menu

两种选项trace和warn

trace

trace函数就是在log中最新的空缺位置记录一条新的log,每条最多16个字节,最多可以写入9条log,看一下data段上的log

data

发现log数组其实只有128个字节大小,只能存放8个log,那么第九个log就会溢出覆盖到src中。这里我们有控制src为任意16字节的数据的能力。

warn

warn函数中我们最多输入0x100字节数据到buf中,然而buf数组为0x10长,此处存在栈溢出漏洞,若判断read读入的字节数量大于16,程序判断出现了overflow异常,并使用throw主动抛出异常。

C语言的异常处理在IDA中表示为try catch块,和java的很像,同时也是递归处理的,若子函数没有catch来处理异常,则由调用子函数的母函数catch处理,若母函数不处理则继续向上抛出直到异常被catch处理。

这里直接看汇编就可以在IDA中看到try catch了

warn-asm

warn函数在可能抛出异常的地方使用了try但是并没有catch语句来处理异常,因此异常正常会被向上抛出寻求main函数处理

mian_warn

可以看到main函数在调用warn时使用的try标注用于标识此处可能出现异常。

main_catch

可以看到main函数中有一个catch块,写着owned by 0x401A32用于处理上面try的地方发现的异常,此处异常处理函数直接打印了时间和错误信息,同时我们也可以看上面warn的代码可以知道传入异常处理函数的消息为src变量,即一个用于表示溢出的 'Buffer Overflow'字符串。

这道题目的考点就在于对catch异常处理函数的劫持,将其从一个catch劫持到另一个catch。

我们仔细审查程序可以发现程序中main下面有这样一段代码:

magic catch

此处异常处理函数后面在printf之后还有一个system,其跟printf第二个参数一样,是一个字符串信息。若我们将main的异常处理函数劫持到这个catch,即0x401bc7处,就会执行到这个system,若system可控,则可以执行任意指令进而getshell,我们可以先看一下,若将异常处理函数劫持到此,这里system的参数是什么:

劫持catch处理函数的方式也很简单,因为程序在爆出异常之后会向上抛出寻求catch,其实际上就是在main函数返回地址开始向后寻找catch块的,只要我们劫持main返回地址使其第一个catch块为我们上面讨论的magic catch即可,此处由于函数不是主动执行ret来从栈帧返回的,而是因为throw了异常而强制去mian中寻找catch来处理异常,因此不会遇到canary的校验问题,若catch异常处理函数也可控,则此类方式也可以绕过canary的检查执行任意代码。

劫持方式:利用warn中的栈溢出漏洞覆盖warn返回地址为magic catch地址,断点打在0x401c07的system处:

值得注意的是这里用于栈溢出的垃圾数据最好填一个可写地址,否则会报错,例如我全部填字符“a”:

error

可以看到这里会报错,原因在于我们输入的0x6161616161616161被当作了地址,而这是非法地址,因此报错,所以我们前面垃圾数据随便填一个可写的地址就行了,脚本中填的是一个bss地址。

gdb break

可以看到成功劫持程序的catch处理块了,这里system的参数正好是src,即程序自定义的那个用于表示栈溢出的字符串。此处若我们利用trace的数组边界判断漏洞,溢出覆写src为/bin/sh,那么这里system就会执行/bin/sh从而得到shell了。

完整exp:

exp攻击结果:

exp result

By  Del0n1x

Keyboard


Copyright © 2024 aigcdaily.cn  北京智识时代科技有限公司  版权所有  京ICP备2023006237号-1