mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-27 02:40:51 +01:00
reimplement expression prediction + fixes
This commit is contained in:
parent
13b1bd055e
commit
4d7bc7ff62
@ -1,5 +1,6 @@
|
|||||||
package gearth.misc.packetrepresentation;
|
package gearth.misc.packetrepresentation;
|
||||||
|
|
||||||
|
import gearth.misc.packetrepresentation.prediction.StructurePredictor;
|
||||||
import gearth.protocol.HPacket;
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -9,15 +10,18 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
// for all the logistics behind bytes-string conversion
|
// for all the logistics behind bytes-string conversion
|
||||||
public class PacketStructure {
|
public class PacketStringUtils {
|
||||||
|
|
||||||
private static String replaceAll(String templateText, String regex,
|
private static String replaceAll(String templateText, String regex,
|
||||||
Function<Matcher, String> replacer) {
|
Function<Matcher, String> replacer) {
|
||||||
Pattern pattern = Pattern.compile(regex);
|
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
|
||||||
Matcher matcher = pattern.matcher(templateText);
|
Matcher matcher = pattern.matcher(templateText);
|
||||||
StringBuffer result = new StringBuffer();
|
StringBuffer result = new StringBuffer();
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
matcher.appendReplacement(result, replacer.apply(matcher));
|
matcher.appendReplacement(
|
||||||
|
result,
|
||||||
|
Matcher.quoteReplacement(replacer.apply(matcher))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
matcher.appendTail(result);
|
matcher.appendTail(result);
|
||||||
return result.toString();
|
return result.toString();
|
||||||
@ -129,6 +133,10 @@ public class PacketStructure {
|
|||||||
else return;
|
else return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static String predictedExpression(HPacket packet) {
|
||||||
|
StructurePredictor structurePredictor = new StructurePredictor(packet);
|
||||||
|
return structurePredictor.getExpression();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean structureEquals(HPacket packet, String struct) {
|
public static boolean structureEquals(HPacket packet, String struct) {
|
||||||
if (packet.isCorrupted()) return false;
|
if (packet.isCorrupted()) return false;
|
@ -0,0 +1,111 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction;
|
||||||
|
|
||||||
|
import gearth.misc.packetrepresentation.PacketStringUtils;
|
||||||
|
import gearth.misc.packetrepresentation.prediction.checkers.TypeChecker;
|
||||||
|
import gearth.misc.packetrepresentation.prediction.checkers.TypeCheckerProducer;
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StructurePredictor {
|
||||||
|
|
||||||
|
HPacket packet;
|
||||||
|
String structure; // null if not found/ didnt try to find
|
||||||
|
|
||||||
|
public StructurePredictor(HPacket packet) {
|
||||||
|
this.packet = packet;
|
||||||
|
if (packet.isCorrupted()) {
|
||||||
|
structure = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
predictStructure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SubStructure {
|
||||||
|
int previous;
|
||||||
|
String type;
|
||||||
|
double logScore;
|
||||||
|
|
||||||
|
public SubStructure(int previous, String type, double logScore) {
|
||||||
|
this.previous = previous;
|
||||||
|
this.type = type;
|
||||||
|
this.logScore = logScore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void predictStructure() {
|
||||||
|
List<TypeChecker> typeCheckers = TypeCheckerProducer.getValidators(packet);
|
||||||
|
|
||||||
|
SubStructure[] dynamic = new SubStructure[packet.getBytesLength() - 6 + 1];
|
||||||
|
dynamic[0] = new SubStructure(-1, "", 0.0);
|
||||||
|
|
||||||
|
int index = 6;
|
||||||
|
while (index < packet.getBytesLength()) {
|
||||||
|
double currentLogScore = dynamic[index - 6].logScore;
|
||||||
|
for (TypeChecker typeChecker : typeCheckers) {
|
||||||
|
if (typeChecker.canRead(index)) {
|
||||||
|
double score = typeChecker.score(index);
|
||||||
|
double newScore = currentLogScore + Math.log(score);
|
||||||
|
int nextIndex = typeChecker.nextIndex(index) - 6;
|
||||||
|
if (dynamic[nextIndex] == null || newScore > dynamic[nextIndex].logScore) {
|
||||||
|
dynamic[nextIndex] = new SubStructure(
|
||||||
|
index - 6,
|
||||||
|
typeChecker.getStructCode(),
|
||||||
|
newScore
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
SubStructure current = dynamic[dynamic.length - 1];
|
||||||
|
while (current.previous != -1) {
|
||||||
|
stringBuilder.append(current.type);
|
||||||
|
current = dynamic[current.previous];
|
||||||
|
}
|
||||||
|
|
||||||
|
structure = stringBuilder.reverse().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExpression() {
|
||||||
|
if (structure == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return PacketStringUtils.toExpressionFromGivenStructure(packet, structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStructure() {
|
||||||
|
return structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
HPacket[] packets = new HPacket[] {
|
||||||
|
new HPacket("{l}{u:500}{i:20}"),
|
||||||
|
new HPacket(4002, "test"),
|
||||||
|
new HPacket(4002, "test", 0, true),
|
||||||
|
new HPacket(4002, "test", "testtsd", 54452, true, false),
|
||||||
|
new HPacket(4002, "test", 46564554, "testtsd", 54452, true, false),
|
||||||
|
new HPacket(4002, "test", 0, 46564554, "testtsd", 54452, true, false),
|
||||||
|
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, true, false),
|
||||||
|
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, ""),
|
||||||
|
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, ""),
|
||||||
|
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, 0),
|
||||||
|
new HPacket(4002, -1, (byte) 5, "test", 0, 46564554, "testtsd", -1, 54452, false, true, 0),
|
||||||
|
new HPacket(4002, "", 20, 0),
|
||||||
|
new HPacket(4002, 1),
|
||||||
|
new HPacket(4002, 0, 0),
|
||||||
|
new HPacket(4002, 0, 0, 42, false),
|
||||||
|
new HPacket(4002, 0, "")
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
for (HPacket packet : packets) {
|
||||||
|
StructurePredictor structurePredictor = new StructurePredictor(packet);
|
||||||
|
System.out.println(structurePredictor.getStructure());
|
||||||
|
System.out.println(structurePredictor.getExpression());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
public class BooleanChecker extends TypeChecker<Boolean> {
|
||||||
|
|
||||||
|
BooleanChecker(HPacket hPacket) {
|
||||||
|
super("B", hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return index >= 6 && index < hPacket.getBytesLength() &&
|
||||||
|
(hPacket.toBytes()[index] == 1 || hPacket.toBytes()[index] == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
// A [0] byte is not very likely to be a boolean
|
||||||
|
// A [1] byte is not very likely to be a boolean, but a little bit more
|
||||||
|
|
||||||
|
// 0.6 may seem pretty high but 4 bytes in a row would get score 0.6*0.6*0.6*0.6, which is low
|
||||||
|
return get(index) ? 0.6 : 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean get(int index) {
|
||||||
|
return hPacket.readBoolean(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
public class ByteChecker extends TypeChecker<Byte> {
|
||||||
|
|
||||||
|
ByteChecker(HPacket hPacket) {
|
||||||
|
super("b", hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return index >= 6 && index < hPacket.getBytesLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
// A byte is never likely to be parsed as a literal byte, only rarely
|
||||||
|
|
||||||
|
return 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Byte get(int index) {
|
||||||
|
return hPacket.readByte(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + 1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class IntegerChecker extends TypeChecker<Integer> {
|
||||||
|
|
||||||
|
IntegerChecker(HPacket hPacket) {
|
||||||
|
super("i", hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return index >= 6 && !(index + 4 > hPacket.getBytesLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
int value = get(index);
|
||||||
|
|
||||||
|
|
||||||
|
int ushortTest = hPacket.readUshort(index);
|
||||||
|
int ushortTest2 = hPacket.readUshort(index + 2);
|
||||||
|
// if 4 bytes reads like xy[0][0] or xy[0][1], it is very unlikely to be an actual integer
|
||||||
|
if (ushortTest != 0 && (ushortTest2 == 0 || ushortTest2 == 256 || ushortTest2 == 1 || ushortTest2 == 257)) {
|
||||||
|
return 0.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 bytes that read [0][0][1][0] are also unlikely to be an integer
|
||||||
|
if (value == 256) {
|
||||||
|
return 0.04;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 bytes that read [0][2]xy could be a string
|
||||||
|
if (ushortTest >= 2 && ushortTest <= 6 && StringChecker.canReadString(hPacket, index)) {
|
||||||
|
return (1 - StringChecker.scoreString(hPacket.readString(index)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if 4 bytes read "abcd", it will most likely be part of a string
|
||||||
|
// so check if bytes are common
|
||||||
|
byte[] asBytes = hPacket.readBytes(4, index);
|
||||||
|
char[] asChars = new String(asBytes, StandardCharsets.ISO_8859_1).toCharArray();
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (StringChecker.isCommon(asChars[i], asBytes[i]) == 2) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count == 4) {
|
||||||
|
return 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// also this
|
||||||
|
if (StringChecker.canReadString(hPacket, index - 1)) {
|
||||||
|
String s = hPacket.readString(index - 1);
|
||||||
|
if (s.length() > 2 && s.length() < 10) {
|
||||||
|
if (StringChecker.scoreString(s) > 0.5) {
|
||||||
|
return 1 - StringChecker.scoreString(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when ordering, it often appears that integers are placed before strings/booleans/etc
|
||||||
|
// in the case of empty strings or false booleans, it is as good as always the integer that comes first
|
||||||
|
// so we'll try to respect that here with a small score adjust, which doesnt affect anything else than ordering
|
||||||
|
double offset = ((double)index) / 1000000000;
|
||||||
|
|
||||||
|
// since -1 has a byte arrangement barely used by other packets, we can assign full score
|
||||||
|
if (value == -1) {
|
||||||
|
return 1 - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
return 0.99 - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the value is not 0, but the last byte is 0/1, we assign a little less score
|
||||||
|
// to keep the possibility open for a boolean
|
||||||
|
if (value % 256 == 0) {
|
||||||
|
return 0.87 - offset;
|
||||||
|
}
|
||||||
|
if (value != 1 && value % 256 == 1) {
|
||||||
|
return 0.88 - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= -1) {
|
||||||
|
return 0.92 - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.8 - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer get(int index) {
|
||||||
|
return hPacket.readInteger(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + 4;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class StringChecker extends TypeChecker<String> {
|
||||||
|
|
||||||
|
StringChecker(HPacket hPacket) {
|
||||||
|
super("s", hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return canReadString(hPacket, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
return scoreString(get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get(int index) {
|
||||||
|
return hPacket.readString(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + get(index).length() + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 = very common
|
||||||
|
// 1 = a bit common
|
||||||
|
// 0 = rare
|
||||||
|
public static int isCommon(char c, byte b) {
|
||||||
|
if (c == '\n' || c == '\r' ||c == '\t') {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int uByte = (((int)b) + 256) % 256;
|
||||||
|
|
||||||
|
if (uByte >= 32 && uByte <= 126) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double scoreString(String s) {
|
||||||
|
byte[] asBytes = s.getBytes(StandardCharsets.ISO_8859_1);
|
||||||
|
char[] asChars = s.toCharArray();
|
||||||
|
|
||||||
|
if (s.equals("")) {
|
||||||
|
return 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = s.length();
|
||||||
|
double score = 1;
|
||||||
|
|
||||||
|
double[] penalties = new double[]{
|
||||||
|
(-1.0/(len*0.3+2) + 0.5),
|
||||||
|
(-1.0/(len+2)) + 1,
|
||||||
|
s.length() == 1 ? 0.9 : (s.length() == 2 ? 0.98 : 1.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
score *= penalties[isCommon(
|
||||||
|
asChars[i],
|
||||||
|
asBytes[i]
|
||||||
|
)];
|
||||||
|
|
||||||
|
if (score < 0.001) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canReadString(HPacket packet, int index) {
|
||||||
|
int l = packet.getBytesLength();
|
||||||
|
return index >= 6 && !(index + 2 > l || packet.readUshort(index) + 2 + index > l);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
public abstract class TypeChecker<T> {
|
||||||
|
|
||||||
|
protected String structCode;
|
||||||
|
protected HPacket hPacket;
|
||||||
|
|
||||||
|
protected TypeChecker(String structCode, HPacket hPacket) {
|
||||||
|
this.structCode = structCode;
|
||||||
|
this.hPacket = hPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean canRead(int index);
|
||||||
|
|
||||||
|
public abstract double score(int index);
|
||||||
|
|
||||||
|
abstract T get(int index);
|
||||||
|
|
||||||
|
// -1 if cant read
|
||||||
|
public int nextIndex(int index) {
|
||||||
|
if (!canRead(index)) return -1;
|
||||||
|
return nextIndexSafe(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract int nextIndexSafe(int index);
|
||||||
|
|
||||||
|
public String getStructCode() {
|
||||||
|
return structCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TypeCheckerProducer {
|
||||||
|
|
||||||
|
public static List<TypeChecker> getValidators(HPacket packet) {
|
||||||
|
return Arrays.asList(
|
||||||
|
new BooleanChecker(packet),
|
||||||
|
new ByteChecker(packet),
|
||||||
|
new IntegerChecker(packet),
|
||||||
|
new StringChecker(packet)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -4,7 +4,7 @@ import gearth.misc.StringifyAble;
|
|||||||
import gearth.misc.harble_api.HarbleAPI;
|
import gearth.misc.harble_api.HarbleAPI;
|
||||||
import gearth.misc.harble_api.HarbleAPIFetcher;
|
import gearth.misc.harble_api.HarbleAPIFetcher;
|
||||||
import gearth.misc.packetrepresentation.InvalidPacketException;
|
import gearth.misc.packetrepresentation.InvalidPacketException;
|
||||||
import gearth.misc.packetrepresentation.PacketStructure;
|
import gearth.misc.packetrepresentation.PacketStringUtils;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -27,11 +27,11 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
public HPacket(String packet) {
|
public HPacket(String packet) {
|
||||||
try {
|
try {
|
||||||
packetInBytes = PacketStructure.fromString(packet).packetInBytes;
|
packetInBytes = PacketStringUtils.fromString(packet).packetInBytes;
|
||||||
} catch (InvalidPacketException e) {
|
} catch (InvalidPacketException e) {
|
||||||
packetInBytes = new byte[0];
|
packetInBytes = new byte[0];
|
||||||
// will be corrupted
|
// will be corrupted
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public HPacket(int header) {
|
public HPacket(int header) {
|
||||||
@ -75,11 +75,11 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return PacketStructure.toString(packetInBytes);
|
return PacketStringUtils.toString(packetInBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean structureEquals(String structure) {
|
public boolean structureEquals(String structure) {
|
||||||
return PacketStructure.structureEquals(this, structure);
|
return PacketStringUtils.structureEquals(this, structure);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int isEOF() {
|
public int isEOF() {
|
||||||
@ -269,11 +269,6 @@ public class HPacket implements StringifyAble {
|
|||||||
replaceByte(index + i, bytes[i]);
|
replaceByte(index + i, bytes[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// if (i < bytes.length) {
|
|
||||||
// appendBytes(Arrays.copyOfRange(bytes, i, bytes.length));
|
|
||||||
// fixLength();
|
|
||||||
// }
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HPacket replaceUShort(int index, int ushort) {
|
public HPacket replaceUShort(int index, int ushort) {
|
||||||
@ -515,7 +510,7 @@ public class HPacket implements StringifyAble {
|
|||||||
if (HarbleAPIFetcher.HARBLEAPI != null &&
|
if (HarbleAPIFetcher.HARBLEAPI != null &&
|
||||||
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
|
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
|
||||||
if (msg.getStructure() != null) {
|
if (msg.getStructure() != null) {
|
||||||
return PacketStructure.toExpressionFromGivenStructure(this, msg.getStructure());
|
return PacketStringUtils.toExpressionFromGivenStructure(this, msg.getStructure());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toExpression();
|
return toExpression();
|
||||||
@ -527,269 +522,7 @@ public class HPacket implements StringifyAble {
|
|||||||
*/
|
*/
|
||||||
public String toExpression() {
|
public String toExpression() {
|
||||||
if (isCorrupted()) return "";
|
if (isCorrupted()) return "";
|
||||||
|
return PacketStringUtils.predictedExpression(this);
|
||||||
boolean[] mask = new boolean[packetInBytes.length];
|
|
||||||
String[] resultTest = new String[packetInBytes.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
mask[i] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
resultTest[0] = "{l}";
|
|
||||||
resultTest[4] = "{u:"+headerId()+"}";
|
|
||||||
|
|
||||||
outerloop:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 1; i++) {
|
|
||||||
int potentialstringlength = readUshort(i);
|
|
||||||
if ((potentialstringlength >= 0 && potentialstringlength < 3) || potentialstringlength > packetInBytes.length - i - 2) continue;
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (mask[j]) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = i+2; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (readByte(j) >= 0 && readByte(j) < 6) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 2 + potentialstringlength >= packetInBytes.length - 3 ||
|
|
||||||
(packetInBytes[i+2+potentialstringlength] >= 0 &&
|
|
||||||
packetInBytes[i+2+potentialstringlength] < 6 )) {
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}";
|
|
||||||
i += (1 + potentialstringlength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO add special case for seperated 5, 6 and 7 bytes here
|
|
||||||
// long live the shitty code.
|
|
||||||
|
|
||||||
//5
|
|
||||||
out:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 4; i++) {
|
|
||||||
for (int j = i; j < i+5; j++) {
|
|
||||||
if (mask[j]) {
|
|
||||||
i = j;
|
|
||||||
continue out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!mask[i-1] || (i+5 < packetInBytes.length && !mask[i+5])) continue;
|
|
||||||
|
|
||||||
if ((readByte(i) == 0 || readByte(i) == 1) && (readInteger(i+1) > 1 || readInteger(i+1) < 0)) {
|
|
||||||
//decide the first byte to be the a boolean
|
|
||||||
resultTest[i] = "{b:"+(readBoolean(i) ? "true" : "false")+"}";
|
|
||||||
resultTest[i+1] = "{i:"+readInteger(i+1)+"}";
|
|
||||||
for (int j = i; j < i+5; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// //6
|
|
||||||
// out:
|
|
||||||
// for (int i = 6; i < packetInBytes.length - 5; i++) {
|
|
||||||
// for (int j = i; j < i+6; j++) {
|
|
||||||
// if (mask[j]) {
|
|
||||||
// i = j;
|
|
||||||
// continue out;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (i+6 < packetInBytes.length && !mask[i+6]) continue;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// //7
|
|
||||||
// out:
|
|
||||||
// for (int i = 6; i < packetInBytes.length - 6; i++) {
|
|
||||||
// for (int j = i; j < i+7; j++) {
|
|
||||||
// if (mask[j]) {
|
|
||||||
// i = j;
|
|
||||||
// continue out;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (i+7 < packetInBytes.length && !mask[i+7]) continue;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
lp22:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 3; i++) {
|
|
||||||
for (int j = i; j < i + 4; j++) {
|
|
||||||
if (mask[j]) {
|
|
||||||
continue lp22;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int num = readInteger(i);
|
|
||||||
if (num == -1 || (num >= 0 && num < 256)) {
|
|
||||||
for (int j = i; j < i+4; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
resultTest[i] = "{i:"+num+"}";
|
|
||||||
i += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
boolean changed = true;
|
|
||||||
boolean isfirst = true;
|
|
||||||
|
|
||||||
while (changed) {
|
|
||||||
changed = false;
|
|
||||||
// filtering strings
|
|
||||||
outerloop:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 1; i++) {
|
|
||||||
int potentialstringlength = readUshort(i);
|
|
||||||
if ((potentialstringlength >= 0 && potentialstringlength < 3) || potentialstringlength > packetInBytes.length - i - 2) continue;
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (mask[j]) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = i+2; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (readByte(j) >= 0 && readByte(j) < 6) continue outerloop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 2 + potentialstringlength >= packetInBytes.length - 3 ||
|
|
||||||
(packetInBytes[i+2+potentialstringlength] >= 0 &&
|
|
||||||
packetInBytes[i+2+potentialstringlength] < 6 )) {
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
changed = true;
|
|
||||||
resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}";
|
|
||||||
i += (1 + potentialstringlength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isfirst) {
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 6; i < packetInBytes.length; i++) {
|
|
||||||
if (!mask[i]) count++;
|
|
||||||
}
|
|
||||||
if (count > 300) return "";
|
|
||||||
}
|
|
||||||
isfirst = false;
|
|
||||||
|
|
||||||
// filtering integers
|
|
||||||
boolean hasfoundsomtin = true;
|
|
||||||
while (hasfoundsomtin) {
|
|
||||||
hasfoundsomtin = false;
|
|
||||||
outerloop2:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 3; i++) {
|
|
||||||
for (int j = i; j < i + 4; j++) {
|
|
||||||
if (mask[j]) {
|
|
||||||
continue outerloop2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i + 4 == packetInBytes.length || mask[i+4] || mask[i-1]) {
|
|
||||||
if (packetInBytes[i+1] == 2) { //could be an unfiltered string; don't filter yet
|
|
||||||
if (((packetInBytes[i+2] >= '0' && packetInBytes[i+2] <= '9') ||
|
|
||||||
(packetInBytes[i+2] >= 'a' && packetInBytes[i+2] <= 'z') ||
|
|
||||||
(packetInBytes[i+2] >= 'A' && packetInBytes[i+2] <= 'Z')) &&
|
|
||||||
((packetInBytes[i+3] >= '0' && packetInBytes[i+3] <= '9') ||
|
|
||||||
(packetInBytes[i+3] >= 'a' && packetInBytes[i+3] <= 'z') ||
|
|
||||||
(packetInBytes[i+3] >= 'A' && packetInBytes[i+3] <= 'Z'))) {
|
|
||||||
changed = true;
|
|
||||||
for (int j = i; j < i + 4; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
hasfoundsomtin = true;
|
|
||||||
resultTest[i] = "{i:"+readInteger(i)+"}";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
continue ;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (int j = i; j < i + 4; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
hasfoundsomtin = true;
|
|
||||||
changed = true;
|
|
||||||
resultTest[i] = "{i:"+readInteger(i)+"}";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (readInteger(i) < 65536) {
|
|
||||||
for (int j = i; j < i + 4; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
hasfoundsomtin = true;
|
|
||||||
resultTest[i] = "{i:"+readInteger(i)+"}";
|
|
||||||
changed = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// filtering strings
|
|
||||||
|
|
||||||
outerloop3:
|
|
||||||
for (int i = 6; i < packetInBytes.length - 1; i++) {
|
|
||||||
int potentialstringlength = readUshort(i);
|
|
||||||
if (potentialstringlength > packetInBytes.length - i - 2) continue;
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (mask[j]) continue outerloop3;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = i+2; j < potentialstringlength+i+2; j++) {
|
|
||||||
if (readByte(j) >= 0 && readByte(j) < 6) continue outerloop3;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = i; j < potentialstringlength+i+2; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
}
|
|
||||||
resultTest[i] = "{s:\""+readString(i).replace("\"", "\\\"")+"\"}";
|
|
||||||
i += (1 + potentialstringlength);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int opeenvolging = 0;
|
|
||||||
for (int i = 6; i < packetInBytes.length; i++) {
|
|
||||||
if (!mask[i]) {
|
|
||||||
opeenvolging++;
|
|
||||||
if (opeenvolging == 4) return "";
|
|
||||||
if (i+1 == packetInBytes.length || mask[i+1]) {
|
|
||||||
for (int j = i - opeenvolging + 1; j <= i; j++) {
|
|
||||||
mask[j] = true;
|
|
||||||
if (packetInBytes[j] == 1 || packetInBytes[j] == 0) {
|
|
||||||
resultTest[j] = "{b:"+(packetInBytes[j] == 1 ? "true" : "false")+"}";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resultTest[j] = "{b:"+((((int)packetInBytes[j])+256)%256)+"}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opeenvolging = 0;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if all values in mask are true, go further
|
|
||||||
for (boolean bool : mask) {
|
|
||||||
if (!bool) return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder expression = new StringBuilder();
|
|
||||||
for (int i = 0; i < resultTest.length; i++) {
|
|
||||||
if (resultTest[i] != null) expression.append(resultTest[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return expression.toString().replace("{i:0}{b:false}{b:true}", "{s:\"\"}{i:1}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -816,7 +549,7 @@ public class HPacket implements StringifyAble {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
HPacket packet = new HPacket("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}{d:1.4}");
|
HPacket packet = new HPacket("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}{d:1.4}");
|
||||||
|
|
||||||
String str = PacketStructure.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
String str = PacketStringUtils.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
||||||
|
|
||||||
HPacket packetverify = new HPacket(str);
|
HPacket packetverify = new HPacket(str);
|
||||||
|
|
||||||
|
@ -28,14 +28,27 @@ public class InjectionController extends SubForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPacketIncomplete(String line) {
|
private boolean isPacketIncomplete(String line) {
|
||||||
int unmatchedBraces = 0;
|
boolean unmatchedBrace = false;
|
||||||
for (int i = 0; i < line.length(); i++)
|
|
||||||
if (line.charAt(i) == '{')
|
|
||||||
unmatchedBraces++;
|
|
||||||
else if (line.charAt(i) == '}')
|
|
||||||
unmatchedBraces--;
|
|
||||||
|
|
||||||
return unmatchedBraces != 0;
|
boolean ignoreBrace = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < line.length(); i++) {
|
||||||
|
if (unmatchedBrace && line.charAt(i) == '"' && line.charAt(i - 1) != '\\') {
|
||||||
|
ignoreBrace = !ignoreBrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ignoreBrace) {
|
||||||
|
if (line.charAt(i) == '{'){
|
||||||
|
|
||||||
|
unmatchedBrace = true;
|
||||||
|
}
|
||||||
|
else if (line.charAt(i) == '}') {
|
||||||
|
unmatchedBrace = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unmatchedBrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HPacket[] parsePackets(String fullText) {
|
private HPacket[] parsePackets(String fullText) {
|
||||||
|
Loading…
Reference in New Issue
Block a user