没有开kaslr、开启smep和smap,不能ret2usr。
https://elixir.bootlin.com/linux/latest/source/include/linux/fs.h#L921
fown_struct 结构体
write每向 llseek + *(mydata+0x10000) + mydata
进行写操作,内容为用户空间传过去的值。同时 *(mydata + 0x10008) 处的值增大。
可以拷贝对应的 struct file 结构体 0xc8 位置的指针指向的内容(前0x28字节)到用户空间。
在满足条件的情况下将内核空间 llseek + have_use + mydata
处的内容传给用户空间。
llseek用来同过设置 file->f_ops
设置 write()
和 read()
读写的位置。
1.控制地址写的位置的主要是:file->f_pos(以下简称llseek)、以及 *(mydata+0x10000) 处存储的值。
2.通过多次的 write 配合 lseek,可以实现将 (mydata+0x10008) 一直增大,配合lseek,触发在write 函数中的一个溢出,可以实现对于 (mydata+0x10000) 和 *(mydata+0x10008) 这两个关键位置的劫持。
3.劫持 (mydata+0x10000) 和 (mydata+0x10008) 后,配合read函数进行任意地址读,爆破 file 结构体的地址,读取0x98大小,最后8个字节即为 file->f_cred
指向当前进程的 cred 结构体。
4.通过计算偏移,重新设置 lseek 和 *(mydata+0x10000) ,配合write函数做任意地址写,目标地址为我们爆破出的 cred 结构体的地址。
5.将当前进程的cred结构体前0x28写成全0,达到提权的目的。
效果:
qemu
-
system
-
x86_64 \
-
m
256M
\
-
kernel bzImage \
-
initrd core.cpio \
-
append
"root=/dev/ram rw console=ttyS0 oops=panic panic=1 nokaslr"
\
-
cpu qemu64,
+
smep,
+
smap \
-
nographic \
-
monitor
/
dev
/
null \
-
gdb tcp::
1234
qemu
-
system
-
x86_64 \
-
m
256M
\
-
kernel bzImage \
-
initrd core.cpio \
-
append
"root=/dev/ram rw console=ttyS0 oops=panic panic=1 nokaslr"
\
-
cpu qemu64,
+
smep,
+
smap \
-
nographic \
-
monitor
/
dev
/
null \
-
gdb tcp::
1234
mount
-
t proc none
/
proc
mount
-
t sysfs none
/
sys
mount
-
t devtmpfs devtmpfs
/
dev
chown root:root flag
chmod
400
flag
exec
0
<
/
dev
/
console
exec
1
>
/
dev
/
console
exec
2
>
/
dev
/
console
insmod mychrdev.ko
chmod
777
/
dev
/
mychrdev
echo
-
e
"\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
setsid cttyhack setuidgid
1000
sh
poweroff
-
d
0
-
f
mount
-
t proc none
/
proc
mount
-
t sysfs none
/
sys
mount
-
t devtmpfs devtmpfs
/
dev
chown root:root flag
chmod
400
flag
exec
0
<
/
dev
/
console
exec
1
>
/
dev
/
console
exec
2
>
/
dev
/
console
insmod mychrdev.ko
chmod
777
/
dev
/
mychrdev
echo
-
e
"\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
setsid cttyhack setuidgid
1000
sh
poweroff
-
d
0
-
f
struct
file
{
union {
struct llist_node fu_llist;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
struct inode
*
f_inode;
/
*
cached value
*
/
const struct file_operations
*
f_op;
/
*
*
Protects f_ep_links, f_flags.
*
Must
not
be taken
from
IRQ context.
*
/
spinlock_t f_lock;
enum rw_hint f_write_hint;
atomic_long_t f_count;
unsigned
int
f_flags;
fmode_t f_mode;
struct mutex f_pos_lock;
loff_t f_pos;
/
/
偏移
0x68
struct fown_struct f_owner;
const struct cred
*
f_cred;
/
/
这里指向当前进程的cred结构体,偏移
0x90
struct file_ra_state f_ra;
u64 f_version;
void
*
f_security;
/
*
needed
for
tty driver,
and
maybe others
*
/
void
*
private_data;
/
*
Used by fs
/
eventpoll.c to link
all
the hooks to this
file
*
/
struct list_head f_ep_links;
struct list_head f_tfile_llink;
struct address_space
*
f_mapping;
errseq_t f_wb_err;
errseq_t f_sb_err;
/
*
for
syncfs
*
/
} __randomize_layout
__attribute__((aligned(
4
)));
/
*
lest something weird decides that
2
is
OK
*
/
struct
file
{
union {
struct llist_node fu_llist;
struct rcu_head fu_rcuhead;
} f_u;
struct path f_path;
struct inode
*
f_inode;
/
*
cached value
*
/
const struct file_operations
*
f_op;
/
*
*
Protects f_ep_links, f_flags.
*
Must
not
be taken
from
IRQ context.
*
/
spinlock_t f_lock;
enum rw_hint f_write_hint;
atomic_long_t f_count;
unsigned
int
f_flags;
fmode_t f_mode;
struct mutex f_pos_lock;
loff_t f_pos;
/
/
偏移
0x68
struct fown_struct f_owner;
const struct cred
*
f_cred;
/
/
这里指向当前进程的cred结构体,偏移
0x90
struct file_ra_state f_ra;
u64 f_version;
void
*
f_security;
/
*
needed
for
tty driver,
and
maybe others
*
/
void
*
private_data;
/
*
Used by fs
/
eventpoll.c to link
all
the hooks to this
file
*
/
struct list_head f_ep_links;
struct list_head f_tfile_llink;
struct address_space
*
f_mapping;
errseq_t f_wb_err;
errseq_t f_sb_err;
/
*
for
syncfs
*
/
} __randomize_layout
__attribute__((aligned(
4
)));
/
*
lest something weird decides that
2
is
OK
*
/
struct fown_struct {
rwlock_t lock;
/
*
protects pid, uid, euid fields
*
/
/
/
unsigned
int
=
4
?
struct pid
*
pid;
/
*
pid
or
-
pgrp where SIGIO should be sent
*
/
/
/
8
enum pid_type pid_type;
/
*
Kind of process group SIGIO should be sent to
*
/
/
/
4
kuid_t uid, euid;
/
*
uid
/
euid of process setting the owner
*
/
/
/
unsigned
int
*
2
=
4
*
2
int
signum;
/
*
posix.
1b
rt signal to be delivered on IO
*
/
/
/
int
4
};
struct fown_struct {
rwlock_t lock;
/
*
protects pid, uid, euid fields
*
/
/
/
unsigned
int
=
4
?
struct pid
*
pid;
/
*
pid
or
-
pgrp where SIGIO should be sent
*
/
/
/
8
enum pid_type pid_type;
/
*
Kind of process group SIGIO should be sent to
*
/
/
/
4
kuid_t uid, euid;
/
*
uid
/
euid of process setting the owner
*
/
/
/
unsigned
int
*
2
=
4
*
2
int
signum;
/
*
posix.
1b
rt signal to be delivered on IO
*
/
/
/
int
4
};
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课