2012-11-19 88 views
0

我想計算我的應用程序(在我的APK中)中特定文件(活動)的CRC或MD5,以便我可以在另一個文件中比較該值確保第一個文件沒有被篡改。如何使用我的APK計算特定文件的CRC32/MD5

我可以這樣做嗎?是的,你能指導我嗎?

例如:

假設我有文件A.java和B.java。我想計算A.java CRC32/MD5並將此值存儲在B.java中,以便當B.java執行時重新計算A.java並將其與已知值進行比較

回答

2

您不能這樣做。在Android上沒有單獨的類文件,你會得到一個包含所有類和庫的DEX文件。你必須計算classes.dex文件的哈希值並將其存儲在資源文件中,因爲將它放入類文件中將改變整體散列值。然而,如果我反編譯你的應用程序並改變你的classes.dex,我也可以改變資源,所以這並不真正提供任何真正的保護。當然,您可以嘗試混淆或隱藏該值以使其更難,但有些工具會查找CRC/MessageDigest引用,並且只需掛鉤它們即可每次返回相同的值。

+0

感謝您的洞察力,我如何計算DEX文件的哈希值?只要是黑客的手工工作,我就很好。我只是不希望像luckypatcher這樣的工具破解我的應用程序 – Snake

+1

您可以使用'Context.getApplicationInfo()。sourceDir'來查找APK和lokk的classes.dex裏面的內容(提示:一個APK是一個zip文件) 。然後只需使用MessageDigest來計算散列。當然,像Lucky Patcher這樣的東西可以直接修改dalvik緩存,所以你不會使用這種方法來檢測它。爲了解決這個問題,你可以做一些小技巧,比如用DexFile手動加載和優化東西,計算散列並與實際緩存中的內容進行比較,但除非你需要特定的工具/漏洞利用,否則通常是不值得的。 –

+0

已接受。這就是我想要做的。我想特意繞過幸運補丁。所以你說這個哈希計算不會對此有幫助?你有鏈接教程或指針如何做手動加載/優化或處理緩存。我覺得你讓我更接近,我只需要提示pleaaaaase :) – Snake

1

將A.java的內容變爲字符串使用java.io.BufferedReader並按以下步驟操作:

public byte[] getMD5(String fileAContents) throws NoSuchAlgorithmException { 
    MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 
    messageDigest.update(fileAContents.getBytes()); 
    return messageDigest.digest(); 
} 
+0

謝謝,但是當我的代碼在apk文件打包時執行時,文件的路徑是什麼?而且應該是。 Java或。類。我需要它在運行時計算 – Snake

1
public static void calculate(Context context) { 

    try { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 

     ZipInputStream fis = get(context); 
     System.out.println("fis: " + fis); 

     byte[] dataBytes = new byte[1024]; 

     int nread = 0; 
     while ((nread = fis.read(dataBytes)) != -1) { 
      md.update(dataBytes, 0, nread); 
     }; 
     byte[] mdbytes = md.digest(); 

     //convert the byte to hex format method 1 
     StringBuffer sb = new StringBuffer(); 
     for (int i = 0; i < mdbytes.length; i++) { 
      sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); 
     } 

     System.out.println("Digest(in hex format):: " + sb.toString()); 

     //convert the byte to hex format method 2 
     StringBuffer hexString = new StringBuffer(); 
     for (int i=0;i<mdbytes.length;i++) { 
      String hex=Integer.toHexString(0xff & mdbytes[i]); 
      if(hex.length()==1) hexString.append('0'); 
      hexString.append(hex); 
     } 
     System.out.println("Digest(in hex format):: " + hexString.toString()); 

     if(fis!=null){ 
      fis.close(); 
     } 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

public static ZipInputStream get(Context context){ 

     // Get the path to the apk container. 
    String apkPath = context.getApplicationInfo().sourceDir; 
    JarFile containerJar = null; 

    try { 

     // Open the apk container as a jar.. 
     containerJar = new JarFile(apkPath); 

     // Look for the "classes.dex" entry inside the container. 
     ZipEntry zzz = containerJar.getEntry("classes.dex"); 

     // If this entry is present in the jar container 
     if (zzz != null) { 

      System.out.println("long " + zzz.getCrc()); 

      // Get an Input Stream for the "classes.dex" entry 
      InputStream in = containerJar.getInputStream(zzz); 

      ZipInputStream zin = new ZipInputStream(in); 

      return zin; 
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (containerJar != null) 
      try { 
       containerJar.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 

    return null; 
} 
相關問題