Search code examples
javaflutterdartdeserializationdecode

Unknown Encoding/Serialization of Binary Data


So there is this app I used called "War Council" which is used to build Army lists in the ASOIAF mini war game. It has a list export feature which exports a base64 encoded binary blob like so:

EgVXYXRjaBgFICgoAFoHCIVSELagAVoDCJFSWgMIjFJaAwiRUmCm7gFgse4BYMPtAQ==

This can then be re-imported to another app on another phone etc..

When I decode this and xxd it I see:

┌──(admuser㉿wkstation5)-[~]
└─$ xxd decoded2.txt 
00000000: 1209 6a6f 6b69 6e20 6361 7618 0620 2828  ..jokin cav.. ((
00000010: 005a 0708 ac51 10c8 9f01 5a07 08ec 5210  .Z...Q....Z...R.
00000020: c99f 015a 0308 f452 5a03 08ee 5260 90ef  ...Z...RZ...R`..
00000030: 0160 94ef 0160 92ef 01                   .`...`...

Here is another one:

Eglqb2tpbiBjYXYYBiAoKABaBwisURDInwFaBwjsUhDJnwFaAwj0UloDCO5SYJDvAWCU7wFgku8B

┌──(admuser㉿wkstation5)-[~]
└─$ xxd decode.txt 
00000000: 1205 5761 7463 6818 0520 2828 005a 0708  ..Watch.. ((.Z..
00000010: 8552 10b6 a001 5a03 0891 525a 0308 8c52  .R....Z...RZ...R
00000020: 5a03 0891 5260 a6ee 0160 b1ee 0160 c3ed  Z...R`...`...`..
00000030: 01                                       .

In the above Watch list, there should be a nights watch spearman unit that has an Id of 10513 in the War Council data. But cant seem to derive that from the data. If it is in fact using the id to store the unit which im inclined to think it is.

I've done a bit of analysis and the App represents all units as integers. I notice that Watch and jokin cav was the name of the lists I gave them. And it appears to always start with 12 and the 05 or 09 represents the length of the string that follows.

I also tried to decode in dart and java since this was made in the flutter engine which uses dart and compiles into java on android.

import 'dart:convert';

void main() {
    // Your base64 encoded string
    String base64EncodedString = 'EgVXYXRjaBgFICgoAFoHCIVSELagAVoDCJFSWgMIjFJaAwiRUmCm7gFgse4BYMPtAQ==';

    // Decode the base64 string
    String serializedData = utf8.decode(base64.decode(base64EncodedString));

    try {
        // Try to parse the data as JSON
        dynamic deserializedObject = json.decode(serializedData);

        // Check if the deserialized object is a JSON-like map or an array of integers
        if (deserializedObject is Map) {
            print("Deserialized JSON-like object: $deserializedObject");
        } else if (deserializedObject is List) {
        //} else if (deserializedObject is List && deserializedObject.every((element) => element is int)) {
            print("Deserialized array of integers: $deserializedObject");
        } else {
            print("Deserialized data is of unknown type");
        }
    } catch (e) {
        print("Error during deserialization: $e");
    }
}

Java:

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.util.Base64;

public class Base64Decoder {
    public static void main(String[] args) {
        String base64EncodedString = "EgVXYXRjaBgFICgoAFoHCIVSELagAVoDCJFSWgMIjFJaAwiRUmCm7gFgse4BYMPtAQ==";

        try {
            // Decode the base64 string into bytes
            byte[] data = Base64.getDecoder().decode(base64EncodedString);

            // Attempt to deserialize the object
            Object deserializedObject = deserialize(data);
            System.out.println("Deserialized object: " + deserializedObject);
        } catch (IOException | ClassNotFoundException e) {
            System.out.println("Deserialization failed: " + e.getMessage());
        }
    }

    private static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
             ObjectInputStream in = new ObjectInputStream(bis)) {
            return in.readObject();
        }
    }
}

But no luck, both failed.

Curious if anyone knows what type of encoding/serialization this is and how I can decipher it so I can figure out how to programtically build/import lists into this other product I'm working on.

Here is one more sample:

EglWaWN0YXJpb24YCCAoKABaAwi4VFoHCLdUEMOiAVoDCLFUWgMItFRaAwiyVGDT8AFg1PABYNXwAQ==

└─$ xxd enc.txt 
00000000: 1209 5669 6374 6172 696f 6e18 0820 2828  ..Victarion.. ((
00000010: 005a 0308 b854 5a07 08b7 5410 c3a2 015a  .Z...TZ...T....Z
00000020: 0308 b154 5a03 08b4 545a 0308 b254 60d3  ...TZ...TZ...T`.
00000030: f001 60d4 f001 60d5 f001                 ..`...`...

Solution

  • Do any of these look like they match up to what you're expecting

    2: {"Watch"}
    3: 5
    4: 40
    5: 0
    11: {`083f52103f3f01`}
    11: {`083f52`}
    11: {`083f52`}
    11: {`083f52`}
    12: 63
    `3f01603f3f01603f3f010d0a`
    
    
    2: {"jokin cav"}
    3: 6
    4: 40
    5: 0
    11: {`083f51103f3f01`}
    11: {`083f52103f3f01`}
    11: {`083f52`}
    11: {`083f52`}
    12: 63
    `3f01603f3f01603f3f010d0a`
    
    
    
    2: {"Victarion"}
    3: 8
    4: 40
    5: 0
    11: {
      1: 63
      10:EGROUP
    }
    11: {`083f54103f3f01`}
    11: {
      1: 63
      10:EGROUP
    }
    11: {
      1: 63
      10:EGROUP
    }
    11: {
      1: 63
      10:EGROUP
    }
    12: 63
    `3f01603f3f01603f3f010d0a`
    

    This is your data interpreted as Protcol Buffers (designed by google hence might be plausible for a dart app?)

    I did this by (on Windows)

    1. putting you base64s into a file
    2. running CertUtil (certutil -decode in.txt out.bin)
    3. running Protoscope (cat out.bin|protoscope) Protoscope is a go program from here

    Does that help?

    EDIT it looks like a clearer output if you use this app - https://protobuf-decoder.netlify.app/ - just copy/paste in your base64 strings. I've no idea if the numbers are what you expect but the name parts definitely look right to me.