首页
社区
课程
招聘
[原创]linux kernel pwn笔记
发表于: 2018-11-24 01:32 10841

[原创]linux kernel pwn笔记

2018-11-24 01:32
10841

如果存在use after free,就可以利用这些结构体进行提权。

我们来看一下内核中关于tty的源码

将全局变量ptm_drivere de ops 设置成ptm_unix98_ops,

而ptm_unix98_ops是在之前就已经初始化了的一个静态全局变量。

打开一个ptmx时调用的函数:

当打开一个ptmx时候调用这个函数之后利用ptm_driver来初始化。因此当我们可以利用
use after free控制一个tty_struct的时候,ops的位置的是一个全局内核变量ptm_unix98_ops,这个变量可以在kallsyms中读取,这样可以leak kernel 绕过kaslr。

需要申请一个0x1000的fake_file_operations
还需要申请一个fake_tty_operations,之后去伪造其中的ioctl 为xchgeaxesp
具体可以看以前发的那篇kernel的ctf题目。

题目举例:sharif kdb
2018国赛 babydriver

cred结构相信大家是轻车熟路,

通过一个超级粗暴的cred爆破代码带大家看看cred的利用

当我们有了内存的任意读写权限之后

但是这种爆破需要时间太长了

前几天看到一篇文章
http://reverse.put.as/2017/11/07/exploiting-cve-2017-5123/

利用cve-2017-5123waitid的漏洞 先进行内存堆探测,
cve-2017-5123 最最最基础利用可以看我前面的文章,
https://bbs.pediy.com/thread-247014.htm

感觉有必要做一个关于cve-2017-5123的专题,一个很适合练手的cve。

内核堆探测的代码:

waitid去任意写0,触发缺页异常并不会直接触发OOPS,但是会返回fault,这样就可以进行内存堆探测,只要能找到堆的大体位置,并且在上面通过fork,在堆上面分配大量cred结构,这样大大增加命中的几率。但是这里有一个困扰我多年的问题,那就是我找不到办法直接去调试kernel heap,希望大佬们能分享一些实用的工具。而且文章中给出的探测堆地址的代码中,为什么要以0x10000000为单位进行探测我始终不明白。准备接下来一段时间认真读一下linux kernel heap的源码,希望能有所解答。

vma的利用我都发在了这篇文章上,不再重复了,大家可以复现一波,这个cve真的很有意思。
https://www.anquanke.com/post/id/161632

vdso是以页为单位copy到内核地址空间的。如果可以内核地址任意的读,可以页为单位进行爆破vdso的地址。

这是String IPC的例子,首先找到有ELF头的一页,再看这页的偏移0x270的地方对不对。具体的情况可能这个偏移不一样,可以自行dump vdso找偏移进行测试。
有了vdso的地址,我们就可以进行overwrites

vdso overwrite技术

强网杯solid_core里面用到的技术:
劫持prctl中的hook
32位参数不能直接劫持call_usermoderhelper,但是可以先劫持poweroff_cmd这个全局变量,为我们想要执行的命令。需要绕过kaslr。kaslr的seed为0x100000,爆破出poweroff_cmd.这里也是一种绕过kaslr的爆破技术,在通过在ida中找出data段poweroff_cmd的偏移,以seed为单位进行爆破。其实跟通过爆破vdso找出kernel base是一个道理。之后将prctl劫持为orderly_poweroff。这里不详细讲了,可以看出题人大佬的博客。

http://simp1e.leanote.com/post/%E5%BC%BA%E7%BD%91%E6%9D%AF%E5%87%BA%E9%A2%98%E6%80%9D%E8%B7%AF-solid_core

插一句,这个题我用gdb调试的时候,题目给的vmlinux没有debug symbols table,难受的一匹,我只能先在qemu中读出kallsyms 中prctl的地址,然后手动的下段点。之后找hook也是难受的一匹。不知道大佬们有什么好用的办法。

中规中矩的一种方法,当有了kernelbase之后,构造一个内核rop组成的payload,write cr4,但是这个需要一些辅助的利用条件,比如存在ufa,就可以利用tty_struct绕过smep。可以参考之前tty_struct的介绍。

因为使用gdb远程调试内核,所以我一直没找到什么有效的手段查看内核的内存映射。一般就是通过readelf -a vmlinux看看text bss data段的偏移,在kallsyms中看看text段符号表,有些全局变量在ida中找找偏移。但是内核的堆和栈,没有像用户态看起来那么方便。

在这里说一说自己调试的时候是怎么处理的。希望大佬们能跟我分享一下自己的调试技巧。每次做kernel ctf pwn都烦skr人,然后用一些lowB的方法,唉!

对于栈的话没什么,
grep 0 /sys/module/yourmodule/sections/.text
从sys/module中找出text段位置,之后
add-symbol-file ./yourmodule.ko 【address】
加载你的驱动的符号表,之后下断点,x/60gx $rsp就可以看栈的情况。

但是堆的话比较难受,原因是对于内核堆的分配算法 slub slab 伙伴算法,我理解不深,也没有实际去调试过这种题型。做过的ctf题目都是有一个简单的uaf,释放一个堆块,马上将其再申请出来这种。在网上也找不到什么实用工具。

所以我写了一个很简单的小驱动,kmalloc一块地址,因为slub分配方法是 先通过伙伴系统获取一整页大小的虚拟内存,之后将整页分配成固定大小的内存块,根据kmalloc进行堆分配。所以,我想的是包装一个内核的模块,当我们要调试一个kernel的程序的时候,比如,需要申请一块ttystruct,kmalloc(0x2e0),这个时候,我们先在包装的内核模块中kmalloc一块同样大小的地址,将这个地址输出,这样,我们要调试的这块tty_struct就会跟我们内核模块输出的地址在同一页中,方便我们去查看堆。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2018-11-24 01:51 被obfuscation编辑 ,原因:
收藏
免费 8
支持
分享
最新回复 (9)
雪    币: 6064
活跃值: (12624)
能力值: ( LV12,RANK:312 )
在线值:
发帖
回帖
粉丝
2
哈哈  顶顶顶
2018-11-24 07:59
2
雪    币: 47147
活跃值: (20450)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3
感谢分享!
2018-11-24 09:31
0
雪    币: 26245
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
4
66666
2018-11-24 18:55
0
雪    币: 8224
活跃值: (1296)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
感谢分享,大佬们谦虚了
2018-11-25 07:57
0
雪    币: 29
活跃值: (295)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2018-11-26 00:08
0
雪    币: 438
活跃值: (228)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2018-11-26 22:27
0
雪    币: 216
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享!
2018-11-29 21:54
0
雪    币: 61
活跃值: (2390)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2019-2-13 00:51
0
雪    币: 6707
活跃值: (2048)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
用eclipse和ida都可以调试内核,看的方便多了
2019-2-21 16:58
0
游客
登录 | 注册 方可回帖
返回
//