This commit is contained in:
parent
80152e119c
commit
620ae15693
2 changed files with 106 additions and 77 deletions
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue