247 lines
10 KiB
Java
247 lines
10 KiB
Java
/*
|
|
Copyright 2019-2020 Dmitry Isaenko
|
|
|
|
This file is part of Konogonka.
|
|
|
|
Konogonka 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.
|
|
|
|
Konogonka 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 Konogonka. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package libKonogonka.Tools.NPDM;
|
|
|
|
import libKonogonka.LoperConverter;
|
|
|
|
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 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 LinkedList<Integer> rawData;
|
|
// Kernel flags
|
|
private boolean kernelFlagsAvailable;
|
|
private int kernelFlagCpuIdHi,
|
|
kernelFlagCpuIdLo,
|
|
kernelFlagThreadPrioHi,
|
|
kernelFlagThreadPrioLo;
|
|
// Syscall Masks as index | mask - order AS IS. [0] = bit5; [1] = bit6
|
|
private LinkedHashMap<Byte, byte[]> syscallMasks; // Index, Mask
|
|
// MapIoOrNormalRange
|
|
private LinkedHashMap<byte[], Boolean> mapIoOrNormalRange; // alt page+num, RO flag
|
|
// MapNormalPage (RW)
|
|
private byte[] mapNormalPage; // TODO: clarify is possible to have multiple
|
|
// InterruptPair
|
|
private LinkedHashMap<Integer, byte[][]> interruptPairs; // Number; irq0, irq2
|
|
// Application type
|
|
private int applicationType;
|
|
// KernelReleaseVersion
|
|
private boolean isKernelRelVersionAvailable;
|
|
private int kernelRelVersionMajor,
|
|
kernelRelVersionMinor;
|
|
// Handle Table Size
|
|
private int handleTableSize;
|
|
// Debug flags
|
|
private boolean debugFlagsAvailable,
|
|
canBeDebugged,
|
|
canDebugOthers;
|
|
|
|
public KernelAccessControlProvider(byte[] bytes) throws Exception{
|
|
if (bytes.length < 4)
|
|
throw new Exception("ACID-> KernelAccessControlProvider: too small size of the Kernel Access Control");
|
|
|
|
rawData = new LinkedList<Integer>();
|
|
|
|
interruptPairs = new LinkedHashMap<>();
|
|
syscallMasks = new LinkedHashMap<Byte, byte[]>();
|
|
mapIoOrNormalRange = new LinkedHashMap<byte[], Boolean>();
|
|
|
|
int position = 0;
|
|
// Collect all blocks
|
|
for (int i = 0; i < bytes.length / 4; i++) {
|
|
int block = LoperConverter.getLEint(bytes, position);
|
|
position += 4;
|
|
|
|
rawData.add(block);
|
|
|
|
//RainbowHexDump.octDumpInt(block);
|
|
|
|
int type = getMinBitCnt(block);
|
|
|
|
switch (type){
|
|
case KERNELFLAGS:
|
|
kernelFlagsAvailable = true;
|
|
kernelFlagCpuIdHi = block >> 24;
|
|
kernelFlagCpuIdLo = block >> 16 & 0b11111111;
|
|
kernelFlagThreadPrioHi = block >> 10 & 0b111111;
|
|
kernelFlagThreadPrioLo = block >> 4 & 0b111111;
|
|
//System.out.println("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.
|
|
//System.out.println("SYSCALLMASK ind: "+maskTableIndex);
|
|
|
|
for (int k = 28; k >= 5; k--) {
|
|
mask[k-5] = (byte) (block >> k & 1); // Only 1 or 0 possible
|
|
//System.out.print(mask[k-5]);
|
|
}
|
|
//System.out.println();
|
|
syscallMasks.put(maskTableIndex, mask);
|
|
break;
|
|
case MAPIOORNORMALRANGE:
|
|
byte[] altStPgNPgNum = new byte[24];
|
|
//System.out.println("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
|
|
//System.out.print(altStPgNPgNum[k-7]);
|
|
}
|
|
mapIoOrNormalRange.put(altStPgNPgNum, (block >> 31 & 1) != 0);
|
|
//System.out.println();
|
|
break;
|
|
case MAPNORMALPAGE_RW:
|
|
//System.out.println("MAPNORMALPAGE_RW\t");
|
|
mapNormalPage = new byte[24];
|
|
for (int k = 31; k >= 8; k--){
|
|
mapNormalPage[k-8] = (byte) (block >> k & 1);
|
|
//System.out.print(mapNormalPage[k-8]);
|
|
}
|
|
//System.out.println();
|
|
break;
|
|
case INTERRUPTPAIR:
|
|
//System.out.println("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;
|
|
//System.out.println("APPLICATIONTYPE "+applicationType);
|
|
break;
|
|
case KERNELRELEASEVERSION:
|
|
//System.out.println("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;
|
|
//System.out.println("HANDLETABLESIZE "+handleTableSize);
|
|
break;
|
|
case DEBUGFLAGS:
|
|
debugFlagsAvailable = true;
|
|
canBeDebugged = (block >> 17 & 1) != 0;
|
|
canDebugOthers = (block >> 18 & 1) != 0;
|
|
//System.out.println("DEBUGFLAGS "+canBeDebugged+" "+canDebugOthers);
|
|
break;
|
|
default:
|
|
System.out.println("UNKNOWN\t\t"+block+" "+type);
|
|
}
|
|
}
|
|
}
|
|
|
|
private int getMinBitCnt(int value){
|
|
int minBitCnt = 0;
|
|
while ((value & 1) != 0){
|
|
value >>= 1;
|
|
minBitCnt++;
|
|
}
|
|
return minBitCnt;
|
|
}
|
|
public LinkedList<Integer> getRawData() { return rawData; }
|
|
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; }
|
|
}
|