Преглед изворни кода

VM Binary File unpacker done. ASM fudgery started

LH пре 3 година
родитељ
комит
65457948c6

+ 10 - 0
QuickStuff/src/main/java/QuickVerifyCrap/ASMFucker.java

@@ -0,0 +1,10 @@
+package QuickVerifyCrap;
+
+public class ASMFucker {
+    public static void main(String[] args) {
+        for(int i=-32768;i<32768;i++)
+        {
+            System.out.println("ld AL, #"+i);
+        }
+    }
+}

+ 28 - 0
SenaBitWiggler/ASMQuälcode.txt

@@ -0,0 +1,28 @@
+asm opcodes:
+
+nop: 0x0000
+
+ld:
+
+Load Value into Register
+ld AL #CONSTANT: xx14 (0-127)
+
+Values itieriert von -32768-32767 in file.
+
+ld suffixes: AL 14, AH 10, X 18, Y 1C
+
+
+
+LSB Or-In
+0x03: (????, Y) Load from Address, (offset based on register Y?)
+0x02: (????, X) Load from Address, (offset based on register X?)
+0x01: (????): Load From Address, absolute
+0x00: Immediate
+
+
+
+LD specialcases:
+ld xh, @(1,y) = 010e, Regel rausfinden, Riect nach dem MSByte für die bra-adresse
+
+st:
+Selbe Logik wie für ld bei Multibyte-Opcodes

+ 1 - 1
SenaBitWiggler/BigVMAppFormat.txt

@@ -2,7 +2,7 @@
 0x08 = const UNKNOWN uint16 as 0x0018
 0x0a = sZCodeInWords uint32
 0x0e = szConstantsInWords uint16
-0x10 = unknown uint16  globals size?
+0x10 = globals uint16  globals size?
 0x12 = szStack uint16 //(only lower byte used)
 0x14 = addrMain uint16 ?
 0x16 = flgUnknown uint16 (lower byte only, got to trace it back)

+ 0 - 5
SenaBitWiggler/build.gradle

@@ -23,11 +23,6 @@ repositories{
 }
 
 dependencies{
-	compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.+'
-	compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.+'
-	compile group: 'org.apache.logging.log4j', name: 'log4j-iostreams', version: '2.+'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.+'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '2.+'
     compile "org.yaml:snakeyaml:1.14"
     compile("com.google.guava:guava:31.0.1-jre")
 }

+ 169 - 34
SenaBitWiggler/src/main/java/de/nplusc/izc/senabitwiggler/EntryPoint.java

@@ -2,9 +2,9 @@ package de.nplusc.izc.senabitwiggler;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Strings;
+import com.google.common.primitives.Ints;
 import com.google.common.primitives.Longs;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
+import com.google.common.primitives.Shorts;
 import org.yaml.snakeyaml.Yaml;
 
 import java.io.*;
@@ -17,7 +17,6 @@ import java.util.Arrays;
 
 public class EntryPoint
 {
-    private static Logger l = LogManager.getLogger();
     public static void main(String[] args)
     {
         if(args.length!=4)
@@ -28,7 +27,21 @@ public class EntryPoint
         boolean extract = args[0].equalsIgnoreCase("extract");
         boolean immport = args[0].equalsIgnoreCase("import");
 
-        if(!(extract||immport))
+        boolean regularfuckery = extract||immport;
+
+        boolean vmexport = args[0].equalsIgnoreCase("extractvm");
+        boolean importvm = args[0].equalsIgnoreCase("importvm");
+
+        boolean vmfuckery = vmexport||importvm;
+
+
+
+
+        boolean incoming = immport|importvm;
+
+        boolean outgoing = extract||vmexport;
+
+        if(!(extract||immport||vmexport||importvm))
         {
             printUsage();
             return;
@@ -37,11 +50,16 @@ public class EntryPoint
         boolean shorty = args[1].equalsIgnoreCase("short");
         boolean longy = args[1].equalsIgnoreCase("long");
 
-        if(!(shorty||longy))
+        if(!(shorty||longy)&&regularfuckery)
         {
             printUsage();
             return;
         }
+        else if(vmfuckery)
+        {
+            shorty = false;
+            longy = false;
+        }
 
         if(shorty)
         {
@@ -50,16 +68,21 @@ public class EntryPoint
         }
 
         File input = new File(args[2]);
-        if(immport&&input.exists())
+        if(incoming&&input.exists())
         {
             System.out.println("Refusing to overwrite a existing firmware archive. Use a fresh name instead");
             return;
         }
-        if(extract&&!input.exists())
+        if(outgoing&&!input.exists())
         {
             System.out.println("Can't extract thin air. Give a file please");
         }
 
+        if(outgoing)
+        {
+            makeSureThatOutFolderIsCreated(args[3]);
+        }
+
         if(extract)
         {
             if(longy)
@@ -72,16 +95,17 @@ public class EntryPoint
                 }
             }
         }
-        else
+        else if(immport)
         {
-            if(immport)
+            if(longy)
             {
-                if(longy)
-                {
-                    assembleFirmware(input,args[3]);
-                }
+                assembleFirmware(input,args[3]);
             }
         }
+        else if(vmexport)
+        {
+            extractVmImage(input,args[3]);
+        }
     }
 
     private static void assembleFirmware(File output, String inputfolder)
@@ -174,26 +198,9 @@ public class EntryPoint
         }
     }
 
-
-    private static byte[] LongToRawBytes(long l)
-    {
-        byte[] tmp = Longs.toByteArray(l);
-        return new byte[]{tmp[7],tmp[6],tmp[5],tmp[4]};
-    }
-
-
-
     private static void extractFirmwareLong(File input, String output) throws InputInvalidException {
         byte filler = 0x00;
-        File od = (new File(output));
-        if(!(od.exists()&&od.isDirectory()))
-        {
-            if(!od.mkdirs())
-            {
-                System.err.println("WTF! somethint ate shit");
-                return;
-            }
-        }
+
 
 
         try (RandomAccessFile f = new RandomAccessFile(input,"r")) {
@@ -324,20 +331,124 @@ public class EntryPoint
         }
     }
 
+    private static void extractVmImage(File input, String output)
+    {
+        byte filler = 0x00;
+        try (RandomAccessFile f = new RandomAccessFile(input,"r")) {
+            VMImageHeader h = new VMImageHeader();
+
+            long len = f.length()/2;
+            if(len>Integer.MAX_VALUE)
+            {
+                System.out.println("Ugggh, File too big");
+                return;
+            }
+
+            short[] checksumarray = new short[(int)len];
+
+            for(int i=0;i<len;i++)
+            {
+                checksumarray[i]=f.readShort();
+            }
+            if(xorsum(checksumarray)!=0)
+            {
+                System.out.println("Smells like Dead Beef, the data seems to be corrupt");
+            }
+            f.seek(0);
+
+
+
+            byte[] magic = new byte[8];
+            f.read(magic);
+
+            h.setHeader(magic);
+
+            byte[] shortPants = new byte[2];
+            byte[] integer = new byte[4];
+            f.read(shortPants);
+            h.setUnknownMagic(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+
+            f.read(integer);
+            h.setSizeCodeInWords(Longs.fromBytes(filler,filler,filler,filler,integer[0],integer[1],integer[2],integer[3]));
+            f.read(shortPants);
+            h.setSzConstantsInWords(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setSzGlobalsInWords(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setSzStack(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setAddressMain(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setUnknownFlag(Shorts.fromBytes(shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setSyscallCompatId(Ints.fromBytes(filler,filler,shortPants[0],shortPants[1]));
+            byte[] trapsets = new byte[8];
+            f.read(trapsets);
+            h.setTrapSet(trapsets);
+            h.setTrapSetStringlied(bytesToHex(trapsets));
+            f.read(integer);
+            h.setSizeFileInWords(Longs.fromBytes(filler,filler,filler,filler,integer[0],integer[1],integer[2],integer[3]));
+            f.read(shortPants);
+            h.setChksum(Shorts.fromBytes(shortPants[0],shortPants[1]));
+            f.read(shortPants);
+            h.setUnknown_parameter_b(Shorts.fromBytes(shortPants[0],shortPants[1]));
+            f.read(integer);
+            h.setEtcetcaddress(Longs.fromBytes(filler,filler,filler,filler,integer[0],integer[1],integer[2],integer[3]));
+
+            f.read(shortPants);
+            h.setUnknown_twiddled_bits(Shorts.fromBytes(shortPants[0],shortPants[1]));
+
+            Yaml y = new Yaml();
+
+            y.dump(h, new FileWriter(new File(output+File.separator+"header.yml")));
+
+            f.seek(0);
+
+            RandomAccessFile hdrRaw = new RandomAccessFile(output+File.separator+"header.bin","rw");
+            byte[] header = new byte[0x30];
+            f.read(header);
+            hdrRaw.write(header);
+            byte[] code = new byte[(int)h.getSizeCodeInWords()*2];
+            f.read(code);
+            RandomAccessFile codeRaw = new RandomAccessFile(output+File.separator+"code.bin","rw");
+            codeRaw.write(code);
+
+            byte[] constants = new byte[h.getSzConstantsInWords()*2];
+            f.read(constants);
+            RandomAccessFile dataRaw = new RandomAccessFile(output+File.separator+"data.bin","rw");
+            dataRaw.write(constants);
+
+
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+
 
 
     private static void printUsage()
     {
         System.out.println("Usage:");
-        System.out.println("program DIRECTION VARIANT FILE FOLDER");
-        System.out.println("DIRECTION: extract OR import");
+        System.out.println("program MODE VARIANT FILE FOLDER");
+        System.out.println("DIRECTION: extract, import, extractVM, importVM");
+        System.out.println("extract: Extracts a Sena Firmware image");
+        System.out.println("Import: Imports a Sena Firmware Image");
+        System.out.println("extractvm Extracts a BlueCore exe-file");
+        System.out.println("importvm Reglues a BlueCore exe-file");
         System.out.println("Variant: short OR long");
         System.out.println("only long supported so far. short header needs more information");
 
     }
 
 
-
+    private static byte[] LongToRawBytes(long l)
+    {
+        byte[] tmp = Longs.toByteArray(l);
+        return new byte[]{tmp[7],tmp[6],tmp[5],tmp[4]};
+    }
 
     private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
     public static String bytesToHex(byte[] bytes) {
@@ -349,6 +460,30 @@ public class EntryPoint
         }
         return new String(hexChars);
     }
+
+    private static void makeSureThatOutFolderIsCreated(String output)
+    {
+        File od = (new File(output));
+        if(!(od.exists()&&od.isDirectory()))
+        {
+            if(!od.mkdirs())
+            {
+                System.err.println("WTF! somethint ate shit");
+                return;
+            }
+        }
+    }
+
+    public static short xorsum(short[] filewords)
+    {
+        short xorsum = 0;
+        for(int i=0;i<filewords.length;i++)
+        {
+            xorsum ^= filewords[i];
+        }
+        return xorsum;
+    }
+
 }
 
 

+ 148 - 0
SenaBitWiggler/src/main/java/de/nplusc/izc/senabitwiggler/VMImageHeader.java

@@ -0,0 +1,148 @@
+package de.nplusc.izc.senabitwiggler;
+
+public class VMImageHeader {
+    private byte[] header;
+    private int unknownMagic;
+    private long sizeCodeInWords;
+    private int szConstantsInWords;
+    private int szGlobalsInWords;
+    private int szStack; // only 1 byte used;
+    private int addressMain;
+    private short unknownFlag;
+    private int syscallCompatId;
+    private byte[] trapSet;
+    private String trapSetStringlied;
+    private long sizeFileInWords;
+    private short chksum; // xorsum, result at end of file should be zero;
+    private int unknown_parameter_b;
+    private long etcetcaddress;
+    private int unknown_twiddled_bits;
+
+    public byte[] getHeader() {
+        return header;
+    }
+
+    public void setHeader(byte[] header) {
+        this.header = header;
+    }
+
+    public int getUnknownMagic() {
+        return unknownMagic;
+    }
+
+    public void setUnknownMagic(int unknownMagic) {
+        this.unknownMagic = unknownMagic;
+    }
+
+    public long getSizeCodeInWords() {
+        return sizeCodeInWords;
+    }
+
+    public void setSizeCodeInWords(long sizeCodeInWords) {
+        this.sizeCodeInWords = sizeCodeInWords;
+    }
+
+    public int getSzConstantsInWords() {
+        return szConstantsInWords;
+    }
+
+    public void setSzConstantsInWords(int szConstantsInWords) {
+        this.szConstantsInWords = szConstantsInWords;
+    }
+
+    public int getSzGlobalsInWords() {
+        return szGlobalsInWords;
+    }
+
+    public void setSzGlobalsInWords(int szGlobalsInWords) {
+        this.szGlobalsInWords = szGlobalsInWords;
+    }
+
+    public int getSzStack() {
+        return szStack;
+    }
+
+    public void setSzStack(int szStack) {
+        this.szStack = szStack;
+    }
+
+    public int getAddressMain() {
+        return addressMain;
+    }
+
+    public void setAddressMain(int addressMain) {
+        this.addressMain = addressMain;
+    }
+
+    public short getUnknownFlag() {
+        return unknownFlag;
+    }
+
+    public void setUnknownFlag(short unknownFlag) {
+        this.unknownFlag = unknownFlag;
+    }
+
+    public long getSizeFileInWords() {
+        return sizeFileInWords;
+    }
+
+    public void setSizeFileInWords(long sizeFileInWords) {
+        this.sizeFileInWords = sizeFileInWords;
+    }
+
+    public short getChksum() {
+        return chksum;
+    }
+
+    public void setChksum(short chksum) {
+        this.chksum = chksum;
+    }
+
+    public int getUnknown_parameter_b() {
+        return unknown_parameter_b;
+    }
+
+    public void setUnknown_parameter_b(int unknown_parameter_b) {
+        this.unknown_parameter_b = unknown_parameter_b;
+    }
+
+    public long getEtcetcaddress() {
+        return etcetcaddress;
+    }
+
+    public void setEtcetcaddress(long etcetcaddress) {
+        this.etcetcaddress = etcetcaddress;
+    }
+
+    public int getUnknown_twiddled_bits() {
+        return unknown_twiddled_bits;
+    }
+
+    public void setUnknown_twiddled_bits(int unknown_twiddled_bits) {
+        this.unknown_twiddled_bits = unknown_twiddled_bits;
+    }
+
+    public byte[] getTrapSet() {
+        return trapSet;
+    }
+
+    public void setTrapSet(byte[] trapSet) {
+        this.trapSet = trapSet;
+    }
+
+    public String getTrapSetStringlied() {
+        return trapSetStringlied;
+    }
+
+    public void setTrapSetStringlied(String trapSetStringlied) {
+        this.trapSetStringlied = trapSetStringlied;
+    }
+
+    public int getSyscallCompatId() {
+        return syscallCompatId;
+    }
+
+    public void setSyscallCompatId(int syscallCompatId) {
+        this.syscallCompatId = syscallCompatId;
+    }
+}