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;
|
||||
|
||||
import gearth.misc.packetrepresentation.prediction.StructurePredictor;
|
||||
import gearth.protocol.HPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@ -9,15 +10,18 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
// for all the logistics behind bytes-string conversion
|
||||
public class PacketStructure {
|
||||
public class PacketStringUtils {
|
||||
|
||||
private static String replaceAll(String templateText, String regex,
|
||||
Function<Matcher, String> replacer) {
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
|
||||
Matcher matcher = pattern.matcher(templateText);
|
||||
StringBuffer result = new StringBuffer();
|
||||
while (matcher.find()) {
|
||||
matcher.appendReplacement(result, replacer.apply(matcher));
|
||||
matcher.appendReplacement(
|
||||
result,
|
||||
Matcher.quoteReplacement(replacer.apply(matcher))
|
||||
);
|
||||
}
|
||||
matcher.appendTail(result);
|
||||
return result.toString();
|
||||
@ -129,6 +133,10 @@ public class PacketStructure {
|
||||
else return;
|
||||
}
|
||||
}
|
||||
public static String predictedExpression(HPacket packet) {
|
||||
StructurePredictor structurePredictor = new StructurePredictor(packet);
|
||||
return structurePredictor.getExpression();
|
||||
}
|
||||
|
||||
public static boolean structureEquals(HPacket packet, String struct) {
|
||||
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.HarbleAPIFetcher;
|
||||
import gearth.misc.packetrepresentation.InvalidPacketException;
|
||||
import gearth.misc.packetrepresentation.PacketStructure;
|
||||
import gearth.misc.packetrepresentation.PacketStringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -27,11 +27,11 @@ public class HPacket implements StringifyAble {
|
||||
}
|
||||
public HPacket(String packet) {
|
||||
try {
|
||||
packetInBytes = PacketStructure.fromString(packet).packetInBytes;
|
||||
packetInBytes = PacketStringUtils.fromString(packet).packetInBytes;
|
||||
} catch (InvalidPacketException e) {
|
||||
packetInBytes = new byte[0];
|
||||
// will be corrupted
|
||||
e.printStackTrace();
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public HPacket(int header) {
|
||||
@ -75,11 +75,11 @@ public class HPacket implements StringifyAble {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return PacketStructure.toString(packetInBytes);
|
||||
return PacketStringUtils.toString(packetInBytes);
|
||||
}
|
||||
|
||||
public boolean structureEquals(String structure) {
|
||||
return PacketStructure.structureEquals(this, structure);
|
||||
return PacketStringUtils.structureEquals(this, structure);
|
||||
}
|
||||
|
||||
public int isEOF() {
|
||||
@ -269,11 +269,6 @@ public class HPacket implements StringifyAble {
|
||||
replaceByte(index + i, bytes[i]);
|
||||
i++;
|
||||
}
|
||||
//
|
||||
// if (i < bytes.length) {
|
||||
// appendBytes(Arrays.copyOfRange(bytes, i, bytes.length));
|
||||
// fixLength();
|
||||
// }
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceUShort(int index, int ushort) {
|
||||
@ -515,7 +510,7 @@ public class HPacket implements StringifyAble {
|
||||
if (HarbleAPIFetcher.HARBLEAPI != null &&
|
||||
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
|
||||
if (msg.getStructure() != null) {
|
||||
return PacketStructure.toExpressionFromGivenStructure(this, msg.getStructure());
|
||||
return PacketStringUtils.toExpressionFromGivenStructure(this, msg.getStructure());
|
||||
}
|
||||
}
|
||||
return toExpression();
|
||||
@ -527,269 +522,7 @@ public class HPacket implements StringifyAble {
|
||||
*/
|
||||
public String toExpression() {
|
||||
if (isCorrupted()) return "";
|
||||
|
||||
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}");
|
||||
return PacketStringUtils.predictedExpression(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -816,7 +549,7 @@ public class HPacket implements StringifyAble {
|
||||
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}");
|
||||
|
||||
String str = PacketStructure.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
||||
String str = PacketStringUtils.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
||||
|
||||
HPacket packetverify = new HPacket(str);
|
||||
|
||||
|
@ -28,14 +28,27 @@ public class InjectionController extends SubForm {
|
||||
}
|
||||
|
||||
private boolean isPacketIncomplete(String line) {
|
||||
int unmatchedBraces = 0;
|
||||
for (int i = 0; i < line.length(); i++)
|
||||
if (line.charAt(i) == '{')
|
||||
unmatchedBraces++;
|
||||
else if (line.charAt(i) == '}')
|
||||
unmatchedBraces--;
|
||||
boolean unmatchedBrace = false;
|
||||
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user