247 lines
10 KiB
Java
247 lines
10 KiB
Java
/*
|
|
Copyright 2019-2022 Dmitry Isaenko
|
|
|
|
This file is part of libKonogonka.
|
|
|
|
libKonogonka is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
libKonogonka is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with libKonogonka. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package libKonogonka.fs.NPDM;
|
|
|
|
import libKonogonka.Converter;
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedList;
|
|
|
|
/*
|
|
NOTE: This implementation is extremely bad for using application as library. Use raw for own purposes.
|
|
|
|
NOTE:
|
|
KAC is set of 4-byes blocks
|
|
Consider them as uInt32 (Read as Little endian)
|
|
Look on the tail of each block (low bits). If tail is equals to mask like 0111111 then such block is related to one of the possible sections (KernelFlags etc.)
|
|
If it's related to the one of the blocks, then we could pick useful data from this block.
|
|
Example:
|
|
36 BYES on this section, then 9 blocks with len = 4-bytes each available
|
|
1 00-01-02-03
|
|
2 04-05-06-07
|
|
3 08-09-10-11
|
|
4 12-13-14-15
|
|
5 16-17-18-19
|
|
6 20-21-22-23
|
|
7 24-25-26-27
|
|
8 28-29-30-31
|
|
9 32-33-34-35
|
|
|
|
Possible patterns are:
|
|
Where '+' is useful data; '0' and '1' in low bytes are pattern.
|
|
Octal | Decimal
|
|
++++++++++++++++++++++++++++0111 | 7 <- KernelFlags
|
|
+++++++++++++++++++++++++++01111 | 15 <- SyscallMask
|
|
+++++++++++++++++++++++++0111111 | 63 <- MapIoOrNormalRange
|
|
++++++++++++++++++++++++01111111 | 127 <- MapNormalPage (RW)
|
|
++++++++++++++++++++011111111111 | 2+47 <- InterruptPair
|
|
++++++++++++++++++01111111111111 | 8191 <- ApplicationType
|
|
+++++++++++++++++011111111111111 | 16383 <- KernelReleaseVersion
|
|
++++++++++++++++0111111111111111 | 32767 <- HandleTableSize
|
|
+++++++++++++++01111111111111111 | 65535 <- DebugFlags
|
|
Other masks could be implemented by N in future (?).
|
|
|
|
Calculation example:
|
|
Dec 1 = 00000000000000000000000000000001
|
|
00100000000000000000000000000111 & 1 = 1
|
|
00010000000000000000000000000011 & 1 = 1
|
|
00001000000000000000000000000001 & 1 = 1
|
|
00000100000000000000000000000000 & 1 = 0
|
|
|
|
TIP: Generate
|
|
int j = 0xFFFFFFFF;
|
|
for (byte i = 0; i < 16; i++){
|
|
j = (j << 1);
|
|
RainbowHexDump.octDumpInt(~j);
|
|
}
|
|
*/
|
|
|
|
public class KernelAccessControlProvider {
|
|
private final static Logger log = LogManager.getLogger(KernelAccessControlProvider.class);
|
|
|
|
private static final int KERNELFLAGS = 3,
|
|
SYSCALLMASK = 4,
|
|
MAPIOORNORMALRANGE = 6,
|
|
MAPNORMALPAGE_RW = 7,
|
|
INTERRUPTPAIR = 11,
|
|
APPLICATIONTYPE = 13,
|
|
KERNELRELEASEVERSION = 14,
|
|
HANDLETABLESIZE = 15,
|
|
DEBUGFLAGS = 16;
|
|
// RAW data
|
|
private final LinkedList<Integer> rawData;
|
|
private final byte[] raw;
|
|
// Kernel flags
|
|
private boolean kernelFlagsAvailable;
|
|
private int kernelFlagCpuIdHi;
|
|
private int kernelFlagCpuIdLo;
|
|
private int kernelFlagThreadPrioHi;
|
|
private int kernelFlagThreadPrioLo;
|
|
// Syscall Masks as index | mask - order AS IS. [0] = bit5; [1] = bit6
|
|
private final LinkedHashMap<Byte, byte[]> syscallMasks; // Index, Mask
|
|
// MapIoOrNormalRange
|
|
private final LinkedHashMap<byte[], Boolean> mapIoOrNormalRange; // alt page+num, RO flag
|
|
// MapNormalPage (RW)
|
|
private byte[] mapNormalPage; // TODO: clarify is possible to have multiple
|
|
|
|
private final LinkedHashMap<Integer, byte[][]> interruptPairs; // Number; irq0, irq2
|
|
|
|
private int applicationType;
|
|
|
|
private boolean isKernelRelVersionAvailable;
|
|
private int kernelRelVersionMajor;
|
|
private int kernelRelVersionMinor;
|
|
|
|
private int handleTableSize;
|
|
// Debug flags
|
|
private boolean debugFlagsAvailable;
|
|
private boolean canBeDebugged;
|
|
private boolean canDebugOthers;
|
|
|
|
public KernelAccessControlProvider(byte[] bytes) throws Exception{
|
|
if (bytes.length < 4)
|
|
throw new Exception("ACID-> KernelAccessControlProvider: too small size of the Kernel Access Control");
|
|
|
|
this.rawData = new LinkedList<>();
|
|
this.raw = bytes;
|
|
this.interruptPairs = new LinkedHashMap<>();
|
|
this.syscallMasks = new LinkedHashMap<>();
|
|
this.mapIoOrNormalRange = new LinkedHashMap<>();
|
|
|
|
// Collect all blocks
|
|
for (int position = 0; position < bytes.length; position += 4) {
|
|
int block = Converter.getLEint(bytes, position);
|
|
|
|
rawData.add(block);
|
|
int type = findBitsCount(block);
|
|
switch (type){
|
|
case KERNELFLAGS:
|
|
kernelFlagsAvailable = true;
|
|
kernelFlagCpuIdHi = block >> 24;
|
|
kernelFlagCpuIdLo = block >> 16 & 0b11111111;
|
|
kernelFlagThreadPrioHi = block >> 10 & 0b111111;
|
|
kernelFlagThreadPrioLo = block >> 4 & 0b111111;
|
|
log.trace("KERNELFLAGS "+kernelFlagCpuIdHi+" "+kernelFlagCpuIdLo+" "+kernelFlagThreadPrioHi+" "+kernelFlagThreadPrioLo);
|
|
break;
|
|
case SYSCALLMASK:
|
|
byte maskTableIndex = (byte) (block >> 29 & 0b111); // declared as byte; max value could be 7; min - 0;
|
|
byte[] mask = new byte[24]; // Consider as bit.
|
|
log.trace("SYSCALLMASK ind: "+maskTableIndex);
|
|
|
|
for (int k = 28; k >= 5; k--) {
|
|
mask[k-5] = (byte) (block >> k & 1); // Only 1 or 0 possible
|
|
log.trace("["+(k-4)+"/24]\t" + mask[k-5]);
|
|
}
|
|
syscallMasks.put(maskTableIndex, mask);
|
|
break;
|
|
case MAPIOORNORMALRANGE:
|
|
byte[] altStPgNPgNum = new byte[24];
|
|
log.trace("MAPIOORNORMALRANGE Flag: "+((block >> 31 & 1) != 0));
|
|
|
|
for (int k = 30; k >= 7; k--){
|
|
altStPgNPgNum[k-7] = (byte) (block >> k & 1); // Only 1 or 0 possible
|
|
log.trace(" " + altStPgNPgNum[k-7]);
|
|
}
|
|
mapIoOrNormalRange.put(altStPgNPgNum, (block >> 31 & 1) != 0);
|
|
break;
|
|
case MAPNORMALPAGE_RW:
|
|
log.trace("MAPNORMALPAGE_RW\t");
|
|
mapNormalPage = new byte[24];
|
|
for (int k = 31; k >= 8; k--){
|
|
mapNormalPage[k-8] = (byte) (block >> k & 1);
|
|
log.trace(" " + mapNormalPage[k-8]);
|
|
}
|
|
break;
|
|
case INTERRUPTPAIR:
|
|
log.trace("INTERRUPTPAIR");
|
|
//RainbowHexDump.octDumpInt(block);
|
|
byte[][] pair = new byte[2][];
|
|
byte[] irq0 = new byte[10];
|
|
byte[] irq1 = new byte[10];
|
|
|
|
for (int k = 21; k >= 12; k--)
|
|
irq0[k-12] = (byte) (block >> k & 1);
|
|
for (int k = 31; k >= 22; k--)
|
|
irq1[k-22] = (byte) (block >> k & 1);
|
|
pair[0] = irq0;
|
|
pair[1] = irq1;
|
|
interruptPairs.put(interruptPairs.size(), pair);
|
|
break;
|
|
case APPLICATIONTYPE:
|
|
applicationType = block >> 14 & 0b111;
|
|
log.trace("APPLICATIONTYPE "+applicationType);
|
|
break;
|
|
case KERNELRELEASEVERSION:
|
|
log.trace("KERNELRELEASEVERSION\t"+(block >> 19 & 0b111111111111)+"."+(block >> 15 & 0b1111)+".X");
|
|
isKernelRelVersionAvailable = true;
|
|
kernelRelVersionMajor = (block >> 19 & 0b111111111111);
|
|
kernelRelVersionMinor = (block >> 15 & 0b1111);
|
|
break;
|
|
case HANDLETABLESIZE:
|
|
handleTableSize = block >> 16 & 0b1111111111;
|
|
log.trace("HANDLETABLESIZE "+handleTableSize);
|
|
break;
|
|
case DEBUGFLAGS:
|
|
debugFlagsAvailable = true;
|
|
canBeDebugged = (block >> 17 & 1) != 0;
|
|
canDebugOthers = (block >> 18 & 1) != 0;
|
|
log.trace("DEBUGFLAGS "+canBeDebugged+" "+canDebugOthers);
|
|
break;
|
|
case 0x20:
|
|
break;
|
|
default:
|
|
log.warn("INVALID ind:0b"+Integer.toBinaryString(block));
|
|
}
|
|
}
|
|
}
|
|
|
|
private int findBitsCount(int value){
|
|
int minBitCnt = 0;
|
|
for (int i = 0; i < 32; i++){
|
|
if((value & 1) == 0)
|
|
break;
|
|
value >>= 1;
|
|
minBitCnt++;
|
|
}
|
|
return minBitCnt;
|
|
}
|
|
public LinkedList<Integer> getRawData() { return rawData; }
|
|
public byte[] getRaw() { return raw; }
|
|
|
|
public boolean isKernelFlagsAvailable() { return kernelFlagsAvailable; }
|
|
public int getKernelFlagCpuIdHi() { return kernelFlagCpuIdHi; }
|
|
public int getKernelFlagCpuIdLo() { return kernelFlagCpuIdLo; }
|
|
public int getKernelFlagThreadPrioHi() { return kernelFlagThreadPrioHi; }
|
|
public int getKernelFlagThreadPrioLo() { return kernelFlagThreadPrioLo; }
|
|
public LinkedHashMap<byte[], Boolean> getMapIoOrNormalRange() { return mapIoOrNormalRange; }
|
|
public byte[] getMapNormalPage() { return mapNormalPage; }
|
|
public LinkedHashMap<Integer, byte[][]> getInterruptPairs() { return interruptPairs; }
|
|
public int getApplicationType() { return applicationType; }
|
|
public boolean isKernelRelVersionAvailable() { return isKernelRelVersionAvailable; }
|
|
public int getKernelRelVersionMajor() { return kernelRelVersionMajor; }
|
|
public int getKernelRelVersionMinor() { return kernelRelVersionMinor;}
|
|
public int getHandleTableSize() { return handleTableSize; }
|
|
public boolean isDebugFlagsAvailable() { return debugFlagsAvailable; }
|
|
public boolean isCanBeDebugged() { return canBeDebugged; }
|
|
public boolean isCanDebugOthers() { return canDebugOthers; }
|
|
public LinkedHashMap<Byte, byte[]> getSyscallMasks() { return syscallMasks; }
|
|
}
|