Skip to content

Commit

Permalink
Fixes:
Browse files Browse the repository at this point in the history
- Fixed menu loader not working after jailbreak, though the whole BD-J is not stable after jailbreak. As such, remove klog and jailbreak jars from on-disc JARs for now.
- Remove UMTX config UI and kstack printing, as it is now pretty stable. Can still be enabled via Config class if necessary.
- Fixed a bug where debug settings JAR was not using DMA on 6.xx+.
- Fixed a bug with caching of kernel accessor in pointers even if cache flag was set to false.
- Made offset detection in libgnmawt more resilient to firmware changes (turned out to be unnecessary).
  • Loading branch information
hammer-83 committed Feb 10, 2025
1 parent 9851203 commit 6b8d7f2
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 35 deletions.
10 changes: 0 additions & 10 deletions assembly/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,6 @@
<artifactId>kerneldump</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.ps5jb.xploit</groupId>
<artifactId>jailbreak</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.ps5jb.xploit</groupId>
<artifactId>klogserver</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.ps5jb.xploit.samples</groupId>
<artifactId>dumpclasspath</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<loader.payload.root>jar-payloads</loader.payload.root>

<!-- Do not use the same version as parent project for Xlet because it will be modified less frequently. We only want to burn new disc if Xlet changes -->
<xlet.version>4.0.0</xlet.version>
<xlet.version>4.0.1</xlet.version>
</properties>

<modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private void initGpuBuffers() {
mman.memoryProtect(victimBuffer[0], GpuPMap.DIRECT_MEMORY_PAGE_SIZE, protRO);
victimBufferPteMaskRO = victimBufferPteAddr.read8() & ~(victimBuffer[1].addr() + GpuPMap.DIRECT_MEMORY_OFFSET);

mman.memoryProtect(victimBuffer[0], GpuPMap.DIRECT_MEMORY_PAGE_SIZE, protRW);
mman.memoryProtect(victimBuffer[0], GpuPMap.DIRECT_MEMORY_PAGE_SIZE, protRW);
victimBufferPteInitialRW = victimBufferPteAddr.read8();
} catch (InvalidValueException | OperationNotPermittedException e) {
throw new SdkRuntimeException(e);
Expand Down
11 changes: 10 additions & 1 deletion sdk/src/main/java/org/ps5jb/sdk/core/kernel/KernelPointer.java
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,16 @@ protected void write8impl(long offset, long value) {
* kernel accessor then the new pointer instance will also have it cached.
*/
public KernelPointer inc(long delta) {
long newAddr = this.addr + delta;

// Size is intentionally left unknown
return new KernelPointer(this.addr + delta, null, this.getKernelAccessor());
KernelPointer result;
if (this.cacheKernelAccessor) {
result = new KernelPointer(newAddr, null, this.getKernelAccessor());
} else {
result = new KernelPointer(newAddr, null, false);
}

return result;
}
}
63 changes: 50 additions & 13 deletions sdk/src/main/java/org/ps5jb/sdk/lib/LibGnmAwt.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import org.ps5jb.loader.Status;
import org.ps5jb.sdk.core.Library;
import org.ps5jb.sdk.core.Pointer;
import org.ps5jb.sdk.core.SdkSoftwareVersionUnsupportedException;
import org.ps5jb.sdk.core.kernel.KernelPointer;
import org.ps5jb.sdk.include.machine.PMap;
import org.ps5jb.sdk.include.machine.pmap.PhysicalMap;
import org.ps5jb.sdk.include.machine.pmap.PhysicalMapEntryMask;
import org.ps5jb.sdk.include.sys.proc.Process;
import org.ps5jb.sdk.res.ErrorMessages;

public class LibGnmAwt extends Library {
private Pointer lockFunc;
Expand Down Expand Up @@ -60,28 +62,63 @@ public void resolveInternal(Process curProc) {
removeXo(userPmap, processedPtes, refFuncAddr, refFuncSize);

// Read offsets to target functions from the reference function code
Pointer callToLock = refFuncAddr.inc(0x0E);
lockFunc = Pointer.valueOf(callToLock.addr() + 4 + callToLock.read4());

Pointer callToDma = refFuncAddr.inc(0x74);
dmaFunc = Pointer.valueOf(callToDma.addr() + 4 + callToDma.read4());

Pointer jmpToUnlock = refFuncAddr.inc(0xFF);
unlockFunc = Pointer.valueOf(jmpToUnlock.addr() + 4 + jmpToUnlock.read4());
Pointer callToLock = refFuncAddr.inc(0x0D);
int opcodes = callToLock.read1() & 0xFF;
if (opcodes != 0xE8) {
throw new SdkSoftwareVersionUnsupportedException(ErrorMessages.getClassErrorMessage(
getClass(),
"resolveInternal.unexpectedInstruction",
callToLock.inc(-refFuncAddr.addr()), "0x" + Integer.toHexString(opcodes), "lock"));
}
lockFunc = Pointer.valueOf(callToLock.addr() + 5 + callToLock.read4(1));

Pointer callToDma = refFuncAddr.inc(0x73);
opcodes = callToDma.read1() & 0xFF;
if (opcodes != 0xE8) {
throw new SdkSoftwareVersionUnsupportedException(ErrorMessages.getClassErrorMessage(
getClass(),
"resolveInternal.unexpectedInstruction",
callToDma.inc(-refFuncAddr.addr()), "0x" + Integer.toHexString(opcodes), "dma"));
}
dmaFunc = Pointer.valueOf(callToDma.addr() + 5 + callToDma.read4(1));

Pointer jmpToUnlock = refFuncAddr.inc(0xFE);
opcodes = jmpToUnlock.read1() & 0xFF;
if (opcodes != 0xE9) {
throw new SdkSoftwareVersionUnsupportedException(ErrorMessages.getClassErrorMessage(
getClass(),
"resolveInternal.unexpectedInstruction",
jmpToUnlock.inc(-refFuncAddr.addr()), "0x" + Integer.toHexString(opcodes), "unlock"));
}
unlockFunc = Pointer.valueOf(jmpToUnlock.addr() + 5 + jmpToUnlock.read4(1));

// DMA function also has a synchronization object that changes value when GPU processed the operation.
// Can be used to check for DMA completion.
final Pointer refSyncObjectInstrAddr = dmaFunc.inc(0x112);
final long refSyncInstrSize = 0x28;
removeXo(userPmap, processedPtes, refSyncObjectInstrAddr, refSyncInstrSize);
final long dmaFuncSize = 0x1B5;
removeXo(userPmap, processedPtes, dmaFunc, dmaFuncSize);

// Read offset to the sync object location in library data section
final Pointer syncObjectPtr = Pointer.valueOf(refSyncObjectInstrAddr.addr() + 4 + refSyncObjectInstrAddr.read4());
final Pointer refSyncObjectInstrAddr = dmaFunc.inc(0x10F);
opcodes = refSyncObjectInstrAddr.read2() & 0xFFFF;
if (opcodes != 0x8B4C && opcodes != 0x8B48) {
throw new SdkSoftwareVersionUnsupportedException(ErrorMessages.getClassErrorMessage(
getClass(),
"resolveInternal.unexpectedInstruction",
refSyncObjectInstrAddr.inc(-dmaFunc.addr()), "0x" + Integer.toHexString(opcodes), "syncObj"));
}
final Pointer syncObjectPtr = Pointer.valueOf(refSyncObjectInstrAddr.addr() + 7 + refSyncObjectInstrAddr.read4(3));
syncObject = Pointer.valueOf(syncObjectPtr.read8());

// Read offset to the sync value pointer in library data section
final Pointer refSyncValueInstrAddr = refSyncObjectInstrAddr.inc(0x24);
syncValuePtr = Pointer.valueOf(refSyncValueInstrAddr.addr() + 4 + refSyncValueInstrAddr.read4());
opcodes = refSyncValueInstrAddr.read2() & 0xFFFF;
if (opcodes != 0x8B44) {
throw new SdkSoftwareVersionUnsupportedException(ErrorMessages.getClassErrorMessage(
getClass(),
"resolveInternal.unexpectedInstruction",
refSyncValueInstrAddr.inc(-dmaFunc.addr()), "0x" + Integer.toHexString(opcodes), "syncValue"));
}
syncValuePtr = Pointer.valueOf(refSyncValueInstrAddr.addr() + 7 + refSyncValueInstrAddr.read4(3));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ core.kernel.KernelAccessorAgc.dmaWrite.count=DMA kernel write of {0} bytes faile
core.kernel.KernelAccessorAgc.nonSerializable=AGC kernel accessor is not serializable because it was freed.

lib.LibKernel.sceKernelGetProsperoSystemSwVersion=Call to retrieve the PS5 system version returned an error code: {0}.
lib.LibGnmAwt.resolveInternal.unexpectedInstruction=Unexpected opcode encountered at offset {0} while resolving "{2}": {1}. This firmware version is currently not supported.

include.sys.CpuSet.setAffinity=Unexpected error occurred while attempting to set CPU affinity. Error code: {0}.
include.sys.CpuSet.setAffinity.EINVAL=The level, which or mask argument was not a valid value.
Expand Down
19 changes: 17 additions & 2 deletions xlet/src/main/java/org/ps5jb/loader/jar/menu/MenuLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class MenuLoader extends HContainer implements Runnable, UserEventListene
private boolean terminated = false;
private boolean waiting = false;

private final Ps5MenuLoader ps5MenuLoader;
private Ps5MenuLoader ps5MenuLoader;

private File discPayloadPath = null;
private Thread remoteJarLoaderThread = null;
Expand All @@ -50,6 +50,8 @@ public void run() {
if (discPayloadPath != null) {
try {
loadJar(discPayloadPath, false);
} catch (InterruptedException e) {
// Ignore
} catch (Throwable ex) {
// JAR execution didn't work, notify and wait to return to the menu
Status.printStackTrace("Could not load JAR from disc", ex);
Expand All @@ -66,6 +68,9 @@ public void run() {
}
}

// Reload the menu in case paths to payloads changed after JAR execution
reloadMenuLoader();

// Wait for user input before returning
Status.println("Press X to return to the menu");
waiting = true;
Expand All @@ -76,7 +81,7 @@ public void run() {
initRenderLoop();
}
}
} catch (RuntimeException | Error ex) {
} catch (RuntimeException | Error | IOException ex) {
Status.printStackTrace("Unhandled exception", ex);
terminated = true;
} finally {
Expand Down Expand Up @@ -119,6 +124,16 @@ private Ps5MenuLoader initMenuLoader() throws IOException {
return ps5MenuLoader;
}

private void reloadMenuLoader() throws IOException {
Ps5MenuLoader oldMenuLoader = ps5MenuLoader;

discPayloadList = null;
ps5MenuLoader = initMenuLoader();
ps5MenuLoader.setSelected(oldMenuLoader.getSelected());
ps5MenuLoader.setSelectedSub(oldMenuLoader.getSelectedSub());
ps5MenuLoader.setSubMenuActive(oldMenuLoader.isSubMenuActive());
}

private void initRenderLoop() {
setSize(Config.getLoaderResolutionWidth(), Config.getLoaderResolutionHeight());
setBackground(Color.darkGray);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void run() {
final LibKernel libKernel = new LibKernel();
try {
SdkInit sdk = SdkInit.init(true, true);
KernelPointer kbase = KernelPointer.valueOf(sdk.KERNEL_BASE_ADDRESS);
KernelPointer kbase = KernelPointer.valueOf(sdk.KERNEL_BASE_ADDRESS, false);
KernelOffsets o = sdk.KERNEL_OFFSETS;

qaFlags = kbase.inc(o.OFFSET_KERNEL_DATA + o.OFFSET_KERNEL_DATA_BASE_QA_FLAGS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public boolean switchToAgcKernelReadWrite(boolean onlyIfNecessary) {
synchronized (KernelReadWrite.class) {
KernelAccessor ka = KernelReadWrite.getAccessor(getClass().getClassLoader());
if (!(ka instanceof KernelAccessorAgc)) {
// Note: the DMA writes may only be necessary on 7.xx.
if (!onlyIfNecessary || KERNEL_OFFSETS.SOFTWARE_VERSION >= 0x0600) {
KernelReadWrite.setAccessor(new KernelAccessorAgc(KernelPointer.valueOf(CUR_PROC_ADDRESS)));
result = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public class Config {
// Configuration.
public static final boolean dumpKernelStackPartially = true;
public static final boolean dumpKernelStackPartially = false;
public static final boolean dumpKernelStackOfReclaimThread = false;

public static final boolean toggleSetThreadPriorities = false;
Expand All @@ -17,6 +17,7 @@ public class Config {
public static final boolean toggleUnmappingOnFailure = true;
public static final boolean toggleSprayOnDestroyThread = true;
public static final boolean toggleMainThreadWait = false;
public static final boolean toggleLoggingUi = false;

// Common parameters.
public static final int MAX_EXPLOITATION_ATTEMPTS = 100000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,16 @@ public UmtxExploit() {
//-------------------------------------------------------------------------

public void run() {
LoggingConfiguration loggingUi = LoggingConfiguration.createComponent();
if (!loggingUi.render()) {
DebugStatus.error("UMTX execution aborted");
return;
if (Config.toggleLoggingUi) {
LoggingConfiguration loggingUi = LoggingConfiguration.createComponent();
if (!loggingUi.render()) {
DebugStatus.error("UMTX execution aborted");
return;
}
}

DebugStatus.error("Running the exploit, it may take 20 seconds or 10 minutes. Please be patient...");
DebugStatus.error("Running the exploit. Please be patient...");
DebugStatus.error("Sometimes, the exploit will hang. In this case, the console needs to be powered off and restarted.");

Runnable mainJob = this::exploit;

Expand Down

0 comments on commit 6b8d7f2

Please sign in to comment.