Few optimizations
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Dmitry Isaenko 2025-02-16 23:18:52 +03:00
parent 80152e119c
commit 620ae15693
2 changed files with 106 additions and 77 deletions

View file

@ -26,32 +26,77 @@ import org.apache.logging.log4j.Logger;
public class KernelMap { public class KernelMap {
private final static Logger log = LogManager.getLogger(KernelMap.class); private final static Logger log = LogManager.getLogger(KernelMap.class);
private final int textStartOffset; private int textStartOffset;
private final int textEndOffset; private int textEndOffset;
private final int rodataStartOffset; private int rodataStartOffset;
private final int rodataEndOffset; private int rodataEndOffset;
private final int dataStartOffset; private int dataStartOffset;
private final int dataEndOffset; private int dataEndOffset;
private final int bssStartOffset; private int bssStartOffset;
private final int bssEndOffset; private int bssEndOffset;
private final int ini1Offset; private int ini1Offset;
private final int dynamicOffset; private int dynamicOffset;
private final int initArrayStartOffset; private int initArrayStartOffset;
private final int initArrayEndOffset; private int initArrayEndOffset;
private int systemRegistersOffset; // 17.0.0+
public KernelMap(byte[] mapBytes, int offset){ private KernelMap() { }
textStartOffset = Converter.getLEint(mapBytes, offset);
textEndOffset = Converter.getLEint(mapBytes, offset + 0x4); /**
rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8); * Construct KernelMap
rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC); *
dataStartOffset = Converter.getLEint(mapBytes, offset + 0x10); * @return null if mapBytes is an invalid data set and KernelMap object otherwise
dataEndOffset = Converter.getLEint(mapBytes, offset + 0x14); */
bssStartOffset = Converter.getLEint(mapBytes, offset + 0x18); public static KernelMap constructKernelMap(byte[] mapBytes, int offset, int maxSize) {
bssEndOffset = Converter.getLEint(mapBytes, offset + 0x1C); KernelMap kernelMap = new KernelMap();
ini1Offset = Converter.getLEint(mapBytes, offset + 0x20); kernelMap.textStartOffset = Converter.getLEint(mapBytes, offset);
dynamicOffset = Converter.getLEint(mapBytes, offset + 0x24); if (kernelMap.textStartOffset != 0)
initArrayStartOffset = Converter.getLEint(mapBytes, offset + 0x28); return null;
initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C); kernelMap.textEndOffset = Converter.getLEint(mapBytes, offset + 0x4);
kernelMap.rodataStartOffset = Converter.getLEint(mapBytes, offset + 0x8);
kernelMap.rodataEndOffset = Converter.getLEint(mapBytes, offset + 0xC);
kernelMap.dataStartOffset = Converter.getLEint(mapBytes, offset + 0x10);
kernelMap.dataEndOffset = Converter.getLEint(mapBytes, offset + 0x14);
kernelMap.bssStartOffset = Converter.getLEint(mapBytes, offset + 0x18);
kernelMap.bssEndOffset = Converter.getLEint(mapBytes, offset + 0x1C);
kernelMap.ini1Offset = Converter.getLEint(mapBytes, offset + 0x20); // 0x08d000
kernelMap.dynamicOffset = Converter.getLEint(mapBytes, offset + 0x24);
kernelMap.initArrayStartOffset = Converter.getLEint(mapBytes, offset + 0x28);
kernelMap.initArrayEndOffset = Converter.getLEint(mapBytes, offset + 0x2C);
kernelMap.systemRegistersOffset = Converter.getLEint(mapBytes, offset + 0x30);
// taken from hactool
if (kernelMap.textStartOffset >= kernelMap.textEndOffset)
return null;
if ((kernelMap.textEndOffset & 0xFFF) > 0)
return null;
if (kernelMap.textEndOffset > kernelMap.rodataStartOffset)
return null;
if ((kernelMap.rodataStartOffset & 0xFFF) > 0)
return null;
if (kernelMap.rodataStartOffset >= kernelMap.rodataEndOffset)
return null;
if ((kernelMap.rodataEndOffset & 0xFFF) > 0)
return null;
if (kernelMap.rodataEndOffset > kernelMap.dataStartOffset)
return null;
if ((kernelMap.dataStartOffset & 0xFFF) > 0)
return null;
if (kernelMap.dataStartOffset >= kernelMap.dataEndOffset)
return null;
if (kernelMap.dataEndOffset > kernelMap.bssStartOffset)
return null;
if (kernelMap.bssStartOffset > kernelMap.bssEndOffset)
return null;
if (kernelMap.bssEndOffset > kernelMap.ini1Offset)
return null;
/*
if (kernelMap.ini1Offset > maxSize - 0x80)
return null;
*/
System.out.println("FOUND AT:" + RainbowDump.formatDecHexString(offset));
kernelMap.printDebug();
return kernelMap;
} }
public int getTextStartOffset() { return textStartOffset; } public int getTextStartOffset() { return textStartOffset; }
@ -67,39 +112,6 @@ public class KernelMap {
public int getInitArrayStartOffset() { return initArrayStartOffset; } public int getInitArrayStartOffset() { return initArrayStartOffset; }
public int getInitArrayEndOffset() { return initArrayEndOffset; } public int getInitArrayEndOffset() { return initArrayEndOffset; }
//taken from hactool
public boolean isValid(long maxSize) { // section0 size
if (textStartOffset != 0)
return false;
if (textStartOffset >= textEndOffset)
return false;
if ((textEndOffset & 0xFFF) > 0)
return false;
if (textEndOffset > rodataStartOffset)
return false;
if ((rodataStartOffset & 0xFFF) > 0)
return false;
if (rodataStartOffset >= rodataEndOffset)
return false;
if ((rodataEndOffset & 0xFFF) > 0)
return false;
if (rodataEndOffset > dataStartOffset)
return false;
if ((dataStartOffset & 0xFFF) > 0)
return false;
if (dataStartOffset >= dataEndOffset)
return false;
if (dataEndOffset > bssStartOffset)
return false;
if (bssStartOffset > bssEndOffset)
return false;
if (bssEndOffset > ini1Offset)
return false;
if (ini1Offset > maxSize - 0x80)
return false;
return true;
}
public void printDebug() { public void printDebug() {
log.debug("_ Kernel map _\n" + log.debug("_ Kernel map _\n" +
" .text Start Offset " + RainbowDump.formatDecHexString(textStartOffset) + "\n" + " .text Start Offset " + RainbowDump.formatDecHexString(textStartOffset) + "\n" +
@ -113,6 +125,7 @@ public class KernelMap {
" INI1 Offset " + RainbowDump.formatDecHexString(ini1Offset) + "\n" + " INI1 Offset " + RainbowDump.formatDecHexString(ini1Offset) + "\n" +
" Dynamic Offset " + RainbowDump.formatDecHexString(dynamicOffset) + "\n" + " Dynamic Offset " + RainbowDump.formatDecHexString(dynamicOffset) + "\n" +
" Init array Start Offset " + RainbowDump.formatDecHexString(initArrayStartOffset) + "\n" + " Init array Start Offset " + RainbowDump.formatDecHexString(initArrayStartOffset) + "\n" +
" Init array End Offset " + RainbowDump.formatDecHexString(initArrayEndOffset)); " Init array End Offset " + RainbowDump.formatDecHexString(initArrayEndOffset) + "\n" +
" System registers offset (FW 17.0.0+) " + RainbowDump.formatDecHexString(systemRegistersOffset));
} }
} }

View file

@ -18,7 +18,9 @@
*/ */
package libKonogonka.fs.other.System2; package libKonogonka.fs.other.System2;
import libKonogonka.Converter;
import libKonogonka.KeyChainHolder; import libKonogonka.KeyChainHolder;
import libKonogonka.RainbowDump;
import libKonogonka.fs.ExportAble; import libKonogonka.fs.ExportAble;
import libKonogonka.fs.other.System2.ini1.Ini1Provider; import libKonogonka.fs.other.System2.ini1.Ini1Provider;
import libKonogonka.aesctr.InFileStreamProducer; import libKonogonka.aesctr.InFileStreamProducer;
@ -112,13 +114,27 @@ public class System2Provider extends ExportAble {
throw new Exception("Read failure " + actuallyRead); throw new Exception("Read failure " + actuallyRead);
byteBuffer.put(block); byteBuffer.put(block);
} }
byte[] searchField = byteBuffer.array(); byte[] searchField = byteBuffer.array();
for (int i = 0; i < 1024; i += 4) {
kernelMap = new KernelMap(searchField, i); if (Converter.getLEint(searchField, 3) == 0x14){ // If FW 17.0.0+
if (kernelMap.isValid(header.getSection0size())) // Calculate new location of the 'kernel beginning'
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");
}
else {
for (int i = 0; i < 0x1000; i += 4) {
kernelMap = KernelMap.constructKernelMap(searchField, i, header.getSection0size());
if (kernelMap != null)
return; return;
} }
}
throw new Exception("Kernel map not found"); throw new Exception("Kernel map not found");
} }