2015-09-27 25 views
0

今天一位朋友問我是否有可能翻轉jar文件,就像我們可以用IDA翻轉可執行文件一樣。如何從RAM內存中存儲和加載類?

答案顯然是「是的」,但由於我很好奇,我需要嘗試。

IDA免費不允許我反編譯JAR文件,但我終於找到CFR和JD。

所以我創建了一個crackMe.jar,它向我們提供密碼,然後解密2個DLL並讀取它們的輸出。

第一個DLL的輸出是一個類文件,它檢查密碼是否正確,第二個DLL的輸出也是一個類文件,在這裏用於擦除這兩個輸出 - 目的是讓它們無法讀取餅乾。

但這的crackme還是太容易裂縫......該裂解裝置只需要修改crackMe.jar的Main.class,保持dll的輸出,然後修改tmp.class和刪除TMP $德爾。類。

我想過要製作另一個DLL來檢查Main.class是否被修改......但是我們可以很容易地破解它。

這就是爲什麼我第一次需要知道是否可以將文件存儲在RAM內存中。

當我們使用CFR時,爲什麼源代碼在java中可讀?我們有辦法對類進行加密並以十六進制執行,而無需使用外部程序來解密它嗎?

即使我們在java中沒有指針,是否可以提取內存中的內容並保留訪問權限? (有可能在C++中?) - 我已經找到了這個主題:https://unix.stackexchange.com/questions/59300/how-to-place-store-a-file-in-memory-on-linux

我們可以管理內存的訪問權嗎?因此,如果程序以管理員身份啓動,那麼CPU是否可以將控制權保留在內存的一部分上,只允許程序讀取它而不是用戶? - https://en.wikipedia.org/wiki/Protection_ring

crackMe.jar的源代碼:

public class Main 
{ 
    public static void main(String[] args) throws Exception 
    { 
     if (new java.io.File(fct("yju!ibq+hifpx")).exists() || new java.io.File(fct("yju+hifpx")).exists()) 
     { 
      new java.io.File(fct("i^y^3aqi")).delete(); 
      new java.io.File(fct("i^y^d/3aqi")).delete(); 
      javax.swing.JOptionPane.showMessageDialog(null, fct("Zkf_qb%qttsjo|onqjyju+hifpxto%qrm)aji3`q^xp")); 
     } 
     String str = javax.swing.JOptionPane.showInputDialog(fct("Jkybw~lzo%mfpxttoi7")); 
     byte[] keyBytes = fct("o^{^").getBytes(); 
     javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, fct("Gittkfxe")); 
     javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(fct("Gittkfxe")); 
     cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKeySpec); 
     java.io.File fileTmp1 = new java.io.File(fct("yju!ibq+hifpx")); 
     java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream(fct("i^y^d/3aqi"))); 
     javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream(fileTmp1)), cipher); 
     int i; 
     if (str != null && str != "") 
     { 
      do 
      { 
       i = bufferedInputStream.read(); 
       if (i != -1) 
        cipherOutputStream.write(i); 
      }while (i != -1); 
     } 
     bufferedInputStream.close(); 
     cipherOutputStream.close(); 
     java.io.File fileTmp2 = new java.io.File(fct("yju+hifpx")); 
     bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream(fct("i^y^3aqi"))); 
     cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream(fileTmp2)), cipher); 
     if (str != null && str != "") 
     { 
      do 
      { 
       i = bufferedInputStream.read(); 
       if (i != -1) 
        cipherOutputStream.write(i); 
      }while (i != -1); 
     } 
     bufferedInputStream.close(); 
     cipherOutputStream.close(); 
     Runtime.getRuntime().exec(fct("o^{^%qrm%") + str); 
     Thread.sleep(200); 
     fileTmp1.delete(); 
     fileTmp2.delete(); 
    } 

    private static String fct(String str) 
    { 
     char[] strC = str.toCharArray(); 
     for (int i = 0, j = str.length(); i < j; i++) 
     { 
      if (i % 2 == 0) 
       strC[i] -= 5; 
      else 
       strC[i] += 3; 
     } 
     return String.valueOf(strC); 
    } 
} 

tmp.class和TMP $ del.class的源代碼

他們不是內部crackMe.jar但是在名稱爲data.dll和data_2.dll的同一文件夾中。

此源代碼已加密。

class tmp 
{ 
    private static String str1, str2 = "Iivfv1$Nvfr^$:Ho\\}%", str3 = "EGq\"", str4 = "W\\xltwkeix\\h%"; 
    private static boolean bool; 

    protected static void setBool(boolean b) 
    { 
     bool = b; 
    } 

    protected static boolean getBool() 
    { 
     return bool; 
    } 

    public static void main(String[] args) 
    { 
     new tmp(true, args[0]); 
    } 

    private static void fct1(int index) 
    { 
     if (index == 0) 
      javax.swing.JOptionPane.showMessageDialog(null, fct5(str2)); 
    } 

    private static void fct2(int index) 
    { 
     if (index == 0) 
      javax.swing.JOptionPane.showMessageDialog(null, fct5(str4)); 
    } 

    private static void fct3(int index) 
    { 
     new del().start(); 
     if (index == 0 && getBool()) 
     { 
      fct1(0); 
     } 
     else if (index == 1 && !getBool()) 
     { 
      fct2(0); 
     } 
    } 

    private static boolean fct4() 
    { 
     return !bool&&!(fct5(str3).equals(str1)); 
    } 

    private static String fct5(String str) 
    { 
     char[] strC = str.toCharArray(); 
     for (int i = 0, j = str.length(); i < j; i++) 
     { 
      if (i % 2 == 0) 
       strC[i] -= 4; 
      else 
       strC[i] += 9; 
     } 
     return String.valueOf(strC); 
    } 

    protected tmp(boolean bool, String arg) 
    { 
     str1 = arg; 
     setBool(false); 
     if (fct4()) 
     { 
      setBool(true); 
      fct3(0); 
     } 
     else 
     { 
      fct3(1); 
     } 
    } 

    static class del extends Thread 
    { 
     public void run() 
     { 
      try 
      { 
       Thread.sleep(50); 
       byte[] keyBytes = "erase".getBytes(); 
       javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, "Blowfish"); 
       javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("Blowfish"); 
       cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec); 
       java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp.class")); 
       javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("tmp.class")), cipher); 
       int i; 
       do 
       { 
        i = bufferedInputStream.read(); 
        if (i != -1) 
         cipherOutputStream.write(i); 
       }while (i != -1); 
       bufferedInputStream.close(); 
       cipherOutputStream.close(); 
       bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp$del.class")); 
       cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("tmp$del.class")), cipher); 
       do 
       { 
        i = bufferedInputStream.read(); 
        if (i != -1) 
         cipherOutputStream.write(i); 
       }while (i != -1); 
       bufferedInputStream.close(); 
       cipherOutputStream.close(); 
      } 
      catch (Exception e) 
      { 

      } 
     } 
    } 
} 

加密器的源代碼,我有使用創建的DLL文件

該程序永遠不會離開我的電腦,讓黑客無法閱讀。

我們使用它只是爲了將tmp.class和tmp $ del.class加密爲data.dll和data_2.dll。

public class encrypt 
{ 
    public static void main(String[] args) throws Exception 
    { 
     byte[] keyBytes = "java".getBytes(); 
     javax.crypto.spec.SecretKeySpec secretKeySpec = new javax.crypto.spec.SecretKeySpec(keyBytes, "Blowfish"); 
     javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("Blowfish"); 
     cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec); 

     java.io.BufferedInputStream bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp.class")); 
     javax.crypto.CipherOutputStream cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("data.dll")), cipher); 
     int i; 
     do 
     { 
      i = bufferedInputStream.read(); 
      if (i != -1) 
       cipherOutputStream.write(i); 
     }while (i != -1); 
     bufferedInputStream.close(); 
     cipherOutputStream.close(); 

     bufferedInputStream = new java.io.BufferedInputStream(new java.io.FileInputStream("tmp$del.class")); 
     cipherOutputStream = new javax.crypto.CipherOutputStream(new java.io.BufferedOutputStream(new java.io.FileOutputStream("data_2.dll")), cipher); 
     do 
     { 
      i = bufferedInputStream.read(); 
      if (i != -1) 
       cipherOutputStream.write(i); 
     }while (i != -1); 
     bufferedInputStream.close(); 
     cipherOutputStream.close(); 

     System.exit(0); 
    } 
} 

回答

2

是的,可以從內存資源加載Class。您需要編寫自定義類加載器來執行此操作,但該類加載器可以將字節碼加載到byte[]中,並調用其中一個(protecteddefineClass方法。

不過,我不知道這會爲您實現:

  • 如果你想這是你的機器上運行,同時保護您的代碼,這是所有不必要的。只要停止破解器進入你的機器。 (但是,如果你不能這樣做,你就搞砸了,見下面)

  • 如果你在破解者機器上運行的時候試圖保護你的代碼,那麼這將無濟於事。所有的黑客需要做的就是啓動一個調試器,在byte[]準備好撥打defineClass的地方設置一個解密點。

無論你做什麼,如果黑客「擁有」執行平臺,他們可以獲得運行它的應用程序的代碼。 (這同樣適用於任何本地代碼庫。)

+0

類加載器是一個好主意,我沒有考慮它......我的目標是創建一個不到一個小時就無法破解的crackMe。如果程序在字節[]中加載字節碼,破解者無法輕易讀取它,並且在大代碼上,他必須找到他需要放置斷點的位置。謝謝,我會嘗試使用類加載器。 – Tirz

+0

呃。太容易了。如果目標是抓住你的加密字節碼,放置斷點的地方在'ClassLoader.defineClass'方法上。工作30秒。然後調整它以查找調用自定義類加載器的情況。 –