首页
社区
课程
招聘
[原创]利用auxv控制canary
发表于: 2019-12-10 17:11 6416

[原创]利用auxv控制canary

2019-12-10 17:11
6416

利用绕过canary的另一种方法。通过修改AUXV(Auxiliary Vector)结构体使 canary 值可控。因为在ld的时候,canary是通过AUXV中的一个成员生成的。

题目文件
(文件在附件中也上传了)

发现upx有壳,upx -d一下(附件中depack文件时脱壳后的),然后发现脱壳后的程序有canary

脱壳后的main函数,很明显gets有个栈溢出。但是有canary,这里通过修改AUXV中的AT_RANDOM来控制我们的canary,后面会介绍。

简言之,canary是由ld.so进行初始化的,而这个值又是通过Auxiliary Vector
参考
https://www.elttam.com.au/blog/playing-with-canaries/
auxv结构可以在elf/elf.h里看到:

这是一个entry struct,以AT_HWCAP为例,这个结构体就会是p64(entry_type_no) + a_un
这个a_type的取值可以参见源码,以下列举部分

我们关注的是这里面的AT_RANDOM,在libc中,它和生成canary有着紧密的关系。

也就是说,canary是通过dl_random上设置的。
通过测试和文章分析可知,AUXV结构体中AT_RANDOM的值对应了canary的值(The value is a pointer to sixteen random bytes provided by the kernel. The dynamic linker uses this to implement a stack canary)

上面的这篇文章也介绍了通过程序获取auxv的方法

其中,type传入auxv的a_type即可。

我们可以写一个带canary的程序,编译的时候gcc的选项带上-fstack-protector-all

然后看一下AT_RANDOM这个地址的值。

还有比较重要的是,程序一开始AT_RANDOMAT_EXECFNAT_PLATFORM和其他的值都会被 push 到栈上。
最后基本可以知道canary的起源是如下的方式:

也就是说,如果我们可以在ld之前修改auxv struct,当程序调用ld后,我们就能控制canary了。

关于修改auxv细节
The auxv structure above is everything. The at_random address gdb tells you is found using that structure. So, you CANNOT just use the address of at_random info auxv to see if the at_random is modified. Actually, at_random's address is contained in that structure, it is like p64(0x19) + p64(at_random_addr). To actually modify the at_random, the only thing you can do is to modify that address followed by the 0x19 number in the auxv. Changed it to point to some address which we already know the contents. (I used the address which is initiated to zero here)
大意就是我们要修改at_random的那个指针,确保这个指针指向的内容我们已知或者可控。

upx壳是有意义的,其不仅提供了RWX段。而且我们可以在没有被脱壳解密的情况下,没有被载入前覆盖掉auxv。第一次加载壳的时候可以输入长为0x4096的字符串,前八位则要求必须是12345678才能过 check。接下来解壳之后就可以溢出到auxv。
注意,我们覆写auxv的时候不需要把每个种类的Elf64_auxv_t都写上,除了必要的AT_RANDOM外,详见exp。

sub_40099E是start第一个运行的函数。
程序刚进入这个函数后就pop rsi,而后rsp在读入之前就没有变

我们在0x4009E1下断点,第一次断下来的时候,rsi就是buf的起始地址了
第一次断在0x4009E1的时候

然后查看栈上auxv的距离

我们发现0x7fffffffe1a8地址处保存了RANDOM的指针,距buf偏移为0x03a8-0x8
我们修改的时候还要修改其a_type,也就是0x7fffffffe1a0地址处表示的0x19.
0x7fffffffe0b0地址开始就是auxv的开始地址,之前和env数组有一个0的分隔。我们在覆盖的时候,不必将auxv每一个a_type对应的值都覆写上。
0x7fffffffde80处的1保存的是argc(参数个数)。0x7fffffffde88则是argv

控制canary之后,我们只要通过ROP,在RWX段用gets写入shellcode,然后执行即可。

经测试,auxv覆盖的时候,下面的成员值一定要保证正确覆写

其他成员不写上调试的时候也没有出问题

https://github.com/D-I-E/writeups/tree/master/2017-ctfs/20170602-TCTF-Final/pwn-upxof
https://qianfei11.github.io/2019/02/15/%E7%BB%95%E8%BF%87ELF%E7%9A%84%E5%AE%89%E5%85%A8%E9%98%B2%E6%8A%A4%E6%9C%BA%E5%88%B6Canary/#2017-TCTF-Final-upxof
https://www.elttam.com.au/blog/playing-with-canaries/


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-12-11 12:42 被微笑明天编辑 ,原因: modify exp format
上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//