Skip to content

Commit

Permalink
- Try different synchronization for status output
Browse files Browse the repository at this point in the history
- Better credits
  • Loading branch information
hammer-83 committed Oct 21, 2024
1 parent 095d5e8 commit c1d6ea2
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 50 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,14 @@ IntelliJ Maven project files are located in a private local folder of IntelliJ.
* In addition, for all the modules that have the above-mentioned dependencies, click on `+ (Add) -> Library` button and add `bdjstack` library dependency. Make sure it is moved in the top position above SDK 11 entry. This setting used to be commited to version control and could be simply reverted, but in recent updates, it has to be performed every time.

## Credits
There are so many who decided to share the knowledge with the community to make this project possible. Please see the Credits section in the [Webkit PS5 Exploit repo](https://github.com/Cryptogenic/PS5-IPV6-Kernel-Exploit#contributors--special-thanks). None of this would be possible without all these contributors. Additionally, big thanks to [psxdev](https://github.com/psxdev) and [John Törnblom](https://github.com/john-tornblom) for their work specifically on BD-J. Finally, the FTP payload is based off work from [pReya](https://github.com/pReya/ftpServer).
There are so many who decided to share the knowledge with the community to make this project possible.
- [Andy "theflow" Nguyen](https://github.com/theofficialflow) for discovering and sharing BD-J vulnerabilities without which none of the work in this repo would be possible.
- Specter for his Webkit implementations of PS5 kernel access which served as a base for Java implementation: [IPV6](https://github.com/Cryptogenic/PS5-IPV6-Kernel-Exploit) and [UMTX](https://github.com/PS5Dev/PS5-UMTX-Jailbreak/).
- [Flat_z](https://github.com/flatz) for pretty much everything of significance that happened in PlayStation scene since as far back as PS3, including the UMTX exploitation strategy contained in this repo.
- [Cheburek3000](https://github.com/cheburek3000) for contributing an alternative implementation of UMTX exploitation.
- [bigboss](https://github.com/psxdev) and [John Törnblom](https://github.com/john-tornblom) for their work specifically in BD-J area.
- All the other contributors to Specter's Webkit implementations: [ChendoChap](https://github.com/ChendoChap), [Znullptr](https://twitter.com/Znullptr), [sleirsgoevy](https://twitter.com/sleirsgoevy), [zecoxao](https://twitter.com/notnotzecoxao), [SocracticBliss](https://twitter.com/SocraticBliss), SlidyBat, [idlesauce](https://github.com/idlesauce).
Sample BD-J payloads in this repositories are adaptations of the following work:
- FTP server by [pReya](https://github.com/pReya/ftpServer).
- Mini Tennis by [Edu4Java](http://www.edu4java.com/en/game/game0-en.html).
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<xlet.className>org.ps5jb.loader.LoaderXlet</xlet.className>

<!-- 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>2.0.1</xlet.version>
<xlet.version>2.1.0</xlet.version>
</properties>

<modules>
Expand Down
66 changes: 41 additions & 25 deletions xlet/src/main/java/org/ps5jb/loader/RemoteLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public RemoteLogger(String server, int port, int timeout) {
/**
* Terminates the remote logger by closing the socket.
*/
public void close() {
public synchronized void close() {
if (loggerSocket != null) {
loggerSocket.close();
loggerSocket = null;
Expand All @@ -56,25 +56,33 @@ public void close() {
* @param len Number of bytes in the buffer to send (typically, {@code buffer.length}).
*/
public void sendBytes(byte[] buffer, int len) {
if (loggerSocket != null) {
try {
// Send in small chunks otherwise there may be an exception that packet is too large.
// This is a UDP protocol constraint
int i = 0;
while (i < len) {
int curLen = Math.min(len - i, 1024);
DatagramPacket sendPacket = new DatagramPacket(buffer, i, curLen, InetAddress.getByName(loggerServer), loggerPort);
loggerSocket.send(sendPacket);
i += curLen;
}
} catch (Throwable e) {
Screen.println("Network data could not be sent");
Screen.getInstance().printStackTrace(e);
Throwable ex = null;

// Do not attempt network logging after failure (assume host down)
close();
synchronized (this) {
if (loggerSocket != null) {
try {
// Send in small chunks otherwise there may be an exception that packet is too large.
// This is a UDP protocol constraint
int i = 0;
while (i < len) {
int curLen = Math.min(len - i, 1024);
DatagramPacket sendPacket = new DatagramPacket(buffer, i, curLen, InetAddress.getByName(loggerServer), loggerPort);
loggerSocket.send(sendPacket);
i += curLen;
}
} catch (Throwable e) {
// Do not attempt network logging after failure (assume host down)
close();

ex = e;
}
}
}

if (ex != null) {
Screen.println("Network data could not be sent", false, false);
Screen.getInstance().printStackTrace(ex);
}
}

/**
Expand All @@ -83,15 +91,23 @@ public void sendBytes(byte[] buffer, int len) {
* @param message String to send.
*/
private void sendString(String message) {
if (loggerSocket != null) {
try {
byte[] buf = message.getBytes("UTF-8");
sendBytes(buf, buf.length);
} catch (Throwable e) {
Screen.println("Network message could not be sent");
Screen.getInstance().printStackTrace(e);
Throwable ex = null;

synchronized (this) {
if (loggerSocket != null) {
try {
byte[] buf = message.getBytes("UTF-8");
sendBytes(buf, buf.length);
} catch (Throwable e) {
ex = e;
}
}
}

if (ex != null) {
Screen.println("Network message could not be sent", false, false);
Screen.getInstance().printStackTrace(ex);
}
}

/**
Expand Down Expand Up @@ -174,7 +190,7 @@ public void debug(String msg) {
}
}
} catch (Throwable e) {
Screen.println("Sending debug message failed");
Screen.println("Sending debug message failed", false, false);
Screen.getInstance().printStackTrace(e);
}
}
Expand Down
65 changes: 44 additions & 21 deletions xlet/src/main/java/org/ps5jb/loader/Screen.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* Encapsulates the capabilities of the screen.
Expand All @@ -22,6 +24,10 @@ public class Screen extends Container {

private static final Screen instance = new Screen();

private AtomicBoolean isPainting = new AtomicBoolean(false);

private AtomicBoolean isDirty = new AtomicBoolean(false);

/**
* Default constructor. Declared as private since this class is singleton.
*/
Expand Down Expand Up @@ -67,14 +73,18 @@ public static void println(String msg, boolean repaint, boolean replaceLast) {
* @param repaint Whether to repaint the screen right away or not.
* @param replaceLast Whether to add a new line or replace the last printed line (useful for progress output).
*/
public synchronized void print(String msg, boolean repaint, boolean replaceLast) {
if (replaceLast && messages.size() > 0) {
messages.remove(messages.size() - 1);
}
messages.add(msg);
if (messages.size() > 48) {
messages.remove(0);
public void print(String msg, boolean repaint, boolean replaceLast) {
synchronized (this) {
if (replaceLast && messages.size() > 0) {
messages.remove(messages.size() - 1);
}
messages.add(msg);
if (messages.size() > 48) {
messages.remove(0);
}
isDirty.set(true);
}

if (repaint) {
repaint();
}
Expand All @@ -85,7 +95,7 @@ public synchronized void print(String msg, boolean repaint, boolean replaceLast)
*
* @param e Exception whose stack trace to print.
*/
public synchronized void printStackTrace(Throwable e) {
public void printStackTrace(Throwable e) {
StringTokenizer st;
StringBuffer sb;

Expand All @@ -106,18 +116,20 @@ public synchronized void printStackTrace(Throwable e) {
sw.close();
}

while (st.hasMoreTokens()) {
String line = st.nextToken();
sb.setLength(0);
for (int i = 0; i < line.length(); ++i) {
char c = line.charAt(i);
if (c == '\t') {
sb.append(" ");
} else {
sb.append(c);
synchronized (this) {
while (st.hasMoreTokens()) {
String line = st.nextToken();
sb.setLength(0);
for (int i = 0; i < line.length(); ++i) {
char c = line.charAt(i);
if (c == '\t') {
sb.append(" ");
} else {
sb.append(c);
}
}
print(sb.toString(), !st.hasMoreTokens(), false);
}
print(sb.toString(), !st.hasMoreTokens(), false);
}
} catch (IOException ioEx) {
printThrowable(e);
Expand All @@ -141,7 +153,16 @@ public void printThrowable(Throwable e) {
* @param g {@code} Graphics code on which the screen data is painted.
*/
@Override
public synchronized void paint(Graphics g) {
public void paint(Graphics g) {
List messagesCopy;
synchronized (this) {
if (isPainting.get() || !isDirty.get()) return;
isPainting.set(true);
isDirty.set(false);

messagesCopy = new ArrayList(messages);
}

g.setFont(FONT);
g.setColor(Color.white);

Expand All @@ -150,10 +171,12 @@ public synchronized void paint(Graphics g) {
int x = 80;
int y = 80;
int height = g.getFontMetrics().getHeight();
for (int i = 0; i < messages.size(); i++) {
String msg = (String) messages.get(i);
for (int i = 0; i < messagesCopy.size(); i++) {
String msg = (String) messagesCopy.get(i);
g.drawString(msg, x, y);
y += height;
}

isPainting.set(false);
}
}
4 changes: 2 additions & 2 deletions xlet/src/main/java/org/ps5jb/loader/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*/
public class Status {
/** Instance of the remote logger to double all the status output over the network */
private static RemoteLogger LOGGER;
private static volatile RemoteLogger LOGGER;

/**
* True if Xlet classes are detected on classpath.
* When <code>true</code>, output is done on Xlet screen; otherwise, it goes to stdout.
*/
private static Boolean inXlet;
private static volatile Boolean inXlet;

/**
* Default constructor. This class should be used statically, so the constructor is declared as private.
Expand Down

0 comments on commit c1d6ea2

Please sign in to comment.