changeset 38:c4113cdfbaa6

Initial implementation of DexDump.
author Mario Torre <neugens.limasoftware@gmail.com>
date Fri, 18 Mar 2011 00:52:22 +0100
parents a14d5c5cd8f2
children 3e21c5b61980
files src/main/java/org/icedrobot/daneel/tools/DexDump.java src/main/java/org/icedrobot/daneel/tools/SHA1Checker.java
diffstat 2 files changed, 296 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/icedrobot/daneel/tools/DexDump.java	Fri Mar 18 00:52:22 2011 +0100
@@ -0,0 +1,168 @@
+/*
+ * Daneel - Dalvik to Java bytecode compiler
+ * Copyright (C) 2011  IcedRobot team
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file is subject to the "Classpath" exception:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library.  Thus, the terms and
+ * conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under terms
+ * of your choice, provided that you also meet, for each linked independent
+ * module, the terms and conditions of the license of that module.  An
+ * independent module is a module which is not derived from or based on
+ * this library.  If you modify this library, you may extend this exception
+ * to your version of the library, but you are not obligated to do so.  If
+ * you do not wish to do so, delete this exception statement from your
+ * version.
+ */
+
+package org.icedrobot.daneel.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import joptsimple.OptionException;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+
+import org.icedrobot.daneel.DaneelException;
+
+/**
+ * Java version of dexdump.
+ * Reads a dex file, decompiles using Daneel and dump the requested
+ * information on the output.
+ */
+public class DexDump {
+
+    private static enum DexOption {
+
+        CHECKSUM("c", "verifies the checksum and prints the result"),
+        HELP("h", "print a brief help");
+
+        final private String option;
+        final private String description;
+        DexOption(String option, String description) {
+            this.option = option;
+            this.description = description;
+        }
+
+        /**
+         * @return the option
+         */
+        public String getOption() {
+            return option;
+        }
+
+        /**
+         * @return the description
+         */
+        public String getDescription() {
+            return description;
+        }
+    }
+
+    /**
+     * Configure the options that DexDump understands.
+     * Please, refer to the Android version for the complete list.
+     */
+    static OptionParser parser;
+    static {
+        parser = new OptionParser() {
+            {
+                accepts(DexOption.HELP.getOption(),
+                        DexOption.HELP.getDescription());
+                accepts(DexOption.CHECKSUM.getOption(),
+                        DexOption.CHECKSUM.getDescription());
+            }
+        };
+    }
+
+    private String[] args;
+    private DexDump(String[] args) {
+        this.args = args;
+    }
+
+    private void printHelp() {
+        try {
+            System.out.println("DexDump: [-c] ClassFile.dex");
+            parser.printHelpOn(System.out);
+        } catch (IOException ex) {
+            throw new DaneelException(ex);
+        }
+    }
+
+    private void checkOptions(File dexFile, OptionSet options) {
+        if (options.has(DexOption.HELP.getOption())) {
+            printHelp();
+
+        } else if (options.has(DexOption.CHECKSUM.getOption())) {
+            SHA1Checker checker = new SHA1Checker();
+            try {
+                checker.execute(dexFile);
+                
+            } catch (IOException ex) {
+                Logger.getLogger(DexDump.class.getName()).log(Level.SEVERE,
+                        "Unexpected Exception", ex);
+            }
+        }
+    }
+
+    private void execute() {
+        
+        OptionSet options;
+        try {
+            options = parser.parse(args);
+        } catch (OptionException ex) {
+            printHelp();
+            return;
+        }
+
+        List<String> files =  options.nonOptionArguments();
+        if (files.size() != 1) {
+            if (files.isEmpty()) {
+                System.out.println("DexDump: no input file given");
+            } else {
+                System.out.println("DexDump: too many arguments");
+            }
+            printHelp();
+            return;
+        }
+
+        File dexFile = new File(files.get(0));
+        if (!dexFile.exists()) {
+            System.out.println("DexDump: invalid input file: " + dexFile);
+            printHelp();
+            return;
+        }
+
+        checkOptions(dexFile, options);
+    }
+
+    public static void main(String[] args) {
+        DexDump dexDump = new DexDump(args);
+        dexDump.execute();
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/icedrobot/daneel/tools/SHA1Checker.java	Fri Mar 18 00:52:22 2011 +0100
@@ -0,0 +1,128 @@
+/*
+ * Daneel - Dalvik to Java bytecode compiler
+ * Copyright (C) 2011  IcedRobot team
+ *
+ * This program 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.
+ *
+ * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file is subject to the "Classpath" exception:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library.  Thus, the terms and
+ * conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under terms
+ * of your choice, provided that you also meet, for each linked independent
+ * module, the terms and conditions of the license of that module.  An
+ * independent module is a module which is not derived from or based on
+ * this library.  If you modify this library, you may extend this exception
+ * to your version of the library, but you are not obligated to do so.  If
+ * you do not wish to do so, delete this exception statement from your
+ * version.
+ */
+
+package org.icedrobot.daneel.tools;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.security.MessageDigest;
+import org.icedrobot.daneel.DaneelException;
+import org.icedrobot.daneel.dex.DexDumperHelper;
+import org.icedrobot.daneel.dex.DexSharedSecrets;
+
+/**
+ * Checks the DEX SHA-1 signature.
+ */
+public class SHA1Checker {
+
+    private static final int SKIP_TO = 8 + 4 + 20;
+
+    private byte[] calculateSHASignature(ByteBuffer dexFileBuffer) {
+        try {
+            MessageDigest md = MessageDigest.getInstance("SHA-1");
+            md.update(dexFileBuffer);
+            return md.digest();
+
+        } catch (Exception ex) {
+            throw new DaneelException(ex);
+        }
+    }
+
+    private String convertToHex(byte[] data) {
+        StringBuilder hexString = new StringBuilder();
+        for (int i = 0; i < data.length; i++) {
+            hexString.append(Integer.toHexString(0xFF & data[i]));
+        }
+        return hexString.toString();
+    }
+
+    private boolean compareSignature(byte[] expected, byte[] found) {
+
+        boolean result = false;
+        String expectedString = convertToHex(expected);
+        String foundString = convertToHex(found);
+
+        if (!expectedString.equals(foundString)) {
+            System.out.println("Checksum doesn't match!");
+            System.out.println("found:\t\t" + expectedString);
+            System.out.println("expected:\t" + foundString);
+        } else {
+            System.out.println("Checksum verified: " + foundString);
+            result = true;
+        }
+        return result;
+    }
+
+    void execute(File dexFile) throws IOException {
+
+        System.out.println("processing: " + dexFile);
+
+        RandomAccessFile dexFileAccess = new RandomAccessFile(dexFile, "r");
+        FileChannel dexFileChannel = dexFileAccess.getChannel();
+
+        ByteBuffer dexFileBufferExpected =
+                dexFileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
+                                   dexFile.length());
+
+        DexDumperHelper helper = DexSharedSecrets.getDexDumper();
+        byte[] hash = helper.getSignature(dexFileBufferExpected);
+
+        ByteBuffer dexFileBufferFound = dexFileBufferExpected.duplicate();
+        dexFileBufferFound.position(SKIP_TO);
+
+        byte[] chash = calculateSHASignature(dexFileBufferFound);
+        compareSignature(hash, chash);
+    }
+
+    public static void main(String [] args) {
+        try {
+            SHA1Checker checker = new SHA1Checker();
+
+            String dexFileName = args[0];
+            File dexFile = new File(dexFileName);
+
+            checker.execute(dexFile);
+
+        } catch (Exception ex) {
+            throw new DaneelException(ex);
+        }
+    }
+}