From 6f04213307499482e4a3a4b6b38a65d266c096f8 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Mon, 17 Feb 2025 23:37:30 +0300 Subject: [PATCH] Finally able to detect FW17+ Kernel Map --- .../fs/other/System2/KernelMap.java | 69 +++++++++++++------ .../fs/other/System2/System2Provider.java | 24 +++++-- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/main/java/libKonogonka/fs/other/System2/KernelMap.java b/src/main/java/libKonogonka/fs/other/System2/KernelMap.java index 13e21f2..38c59f3 100644 --- a/src/main/java/libKonogonka/fs/other/System2/KernelMap.java +++ b/src/main/java/libKonogonka/fs/other/System2/KernelMap.java @@ -1,5 +1,5 @@ /* - Copyright 2019-2023 Dmitry Isaenko + Copyright 2019-2025 Dmitry Isaenko This file is part of libKonogonka. @@ -50,8 +50,6 @@ public class KernelMap { public static KernelMap constructKernelMap(byte[] mapBytes, int offset, int maxSize) { KernelMap kernelMap = new KernelMap(); kernelMap.textStartOffset = Converter.getLEint(mapBytes, offset); - if (kernelMap.textStartOffset != 0) - return null; kernelMap.textEndOffset = Converter.getLEint(mapBytes, offset + 0x4); kernelMap.rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8); kernelMap.rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC); @@ -65,38 +63,67 @@ public class KernelMap { kernelMap.initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C); kernelMap.systemRegistersOffset = Converter.getLEint(mapBytes, offset + 0x30); + if (isValid(kernelMap, maxSize)) + return kernelMap; + + return null; + } + + public static KernelMap constructKernelMap17(byte[] mapBytes, int offset, int branchTarget, int maxSize) { + KernelMap kernelMap = new KernelMap(); + final int realOffset = offset + branchTarget; + kernelMap.textStartOffset = Converter.getLEint(mapBytes, offset)+realOffset; + kernelMap.textEndOffset = Converter.getLEint(mapBytes, offset + 0x4)+realOffset; + kernelMap.rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8)+realOffset; + kernelMap.rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC)+realOffset; + kernelMap.dataStartOffset = Converter.getLEint(mapBytes, offset + 0x10)+realOffset; + kernelMap.dataEndOffset = Converter.getLEint(mapBytes, offset + 0x14)+realOffset; + kernelMap.bssStartOffset = Converter.getLEint(mapBytes, offset + 0x18)+realOffset; + kernelMap.bssEndOffset = Converter.getLEint(mapBytes, offset + 0x1C)+realOffset; + kernelMap.ini1Offset = Converter.getLEint(mapBytes, offset + 0x20)+realOffset; // 0x08d000 + kernelMap.dynamicOffset = Converter.getLEint(mapBytes, offset + 0x24)+realOffset; + kernelMap.initArrayStartOffset = Converter.getLEint(mapBytes, offset + 0x28)+realOffset; + kernelMap.initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C)+realOffset; + kernelMap.systemRegistersOffset = Converter.getLEint(mapBytes, offset + 0x30)+realOffset; + + if (isValid(kernelMap, maxSize)) + return kernelMap; + + return null; + } + + private static boolean isValid(KernelMap kernelMap, int maxSize){ // taken from hactool + if (kernelMap.textStartOffset != 0) + return false; if (kernelMap.textStartOffset >= kernelMap.textEndOffset) - return null; + return false; if ((kernelMap.textEndOffset & 0xFFF) > 0) - return null; + return false; if (kernelMap.textEndOffset > kernelMap.rodataStartOffset) - return null; + return false; if ((kernelMap.rodataStartOffset & 0xFFF) > 0) - return null; + return false; if (kernelMap.rodataStartOffset >= kernelMap.rodataEndOffset) - return null; + return false; if ((kernelMap.rodataEndOffset & 0xFFF) > 0) - return null; + return false; if (kernelMap.rodataEndOffset > kernelMap.dataStartOffset) - return null; + return false; if ((kernelMap.dataStartOffset & 0xFFF) > 0) - return null; + return false; if (kernelMap.dataStartOffset >= kernelMap.dataEndOffset) - return null; + return false; if (kernelMap.dataEndOffset > kernelMap.bssStartOffset) - return null; + return false; if (kernelMap.bssStartOffset > kernelMap.bssEndOffset) - return null; + return false; if (kernelMap.bssEndOffset > kernelMap.ini1Offset) - return null; - /* + return false; if (kernelMap.ini1Offset > maxSize - 0x80) - return null; - */ - System.out.println("FOUND AT:" + RainbowDump.formatDecHexString(offset)); - kernelMap.printDebug(); - return kernelMap; + return false; + + return true; } public int getTextStartOffset() { return textStartOffset; } diff --git a/src/main/java/libKonogonka/fs/other/System2/System2Provider.java b/src/main/java/libKonogonka/fs/other/System2/System2Provider.java index b63d8f2..01670df 100644 --- a/src/main/java/libKonogonka/fs/other/System2/System2Provider.java +++ b/src/main/java/libKonogonka/fs/other/System2/System2Provider.java @@ -1,5 +1,5 @@ /* - Copyright 2019-2022 Dmitry Isaenko + Copyright 2019-2025 Dmitry Isaenko This file is part of libKonogonka. @@ -20,7 +20,6 @@ package libKonogonka.fs.other.System2; import libKonogonka.Converter; import libKonogonka.KeyChainHolder; -import libKonogonka.RainbowDump; import libKonogonka.fs.ExportAble; import libKonogonka.fs.other.System2.ini1.Ini1Provider; import libKonogonka.aesctr.InFileStreamProducer; @@ -121,12 +120,27 @@ public class System2Provider extends ExportAble { int branchTarget = (Converter.getLEint(searchField, 0) & 0x00FFFFFF) << 2; int toSkip = branchTarget - 0x1000; - System.out.println("To skip = " + toSkip + " "); if (toSkip != stream.skip(toSkip)) throw new Exception("Unable to skip offset of " + toSkip); - // TODO: really cursed shit - throw new Exception("FW 17+ not supported. WIP"); + byteBuffer.clear(); + + for (int j = 0; j < 8; j++) { + byte[] block = new byte[0x200]; + int actuallyRead; + if ((actuallyRead = stream.read(block)) != 0x200) + throw new Exception("Read failure " + actuallyRead); + byteBuffer.put(block); + } + + searchField = byteBuffer.array(); + + for (int i = 0; i < 0x1000; i += 4) { + kernelMap = KernelMap.constructKernelMap17(searchField, i, branchTarget, header.getSection0size()); + if (kernelMap != null) + return; + } + System.out.println(); } else { for (int i = 0; i < 0x1000; i += 4) {