JAVA逆向&反混淆-追查Burpsuite的破解原理(轉)


0x00 摘要:


本系列文章通過對BurpLoader的幾個版本的逆向分析,分析Burpsuite的破解原理,分析Burpsuite認證體系存在的安全漏洞。

0x01 JD-GUI的用途與缺陷:


JD-GUI是一款從JAVA字節碼中還原JAVA源代碼的免費工具,一般情況下使用這款工具做JAVA逆向就足夠了,但是由於其原理是從JAVA字節碼中按照特定結構來還原對應的JAVA源代碼,因此一旦字節碼結構被打亂(比如說使用混淆器),那么JD-GUI就會失去它的作用,如圖為使用JD-GUI打開Burpsuite時的顯示:

enter image description here

顯然,JD-GUI沒能還原JAVA源代碼出來,因為Burpsuite使用了混淆器打亂了字節碼結構 所以,JD-GUI適用於‘沒有使用混淆器’的JAVA字節碼,而缺陷是一旦字節碼結構被打亂,則無法發揮它的作用

0x02 字節碼分析:


Java的字節碼並不像普通的二進制代碼在計算機中直接執行,它通過JVM引擎在不同的平台和計算機中運行。

enter image description here

JVM是一個基於棧結構的虛擬計算機,使用的是JVM操作碼(及其助記符),在這一點上和普通二進制反匯編的過程非常相似。 對Java字節碼進行反編譯其實非常簡單,JDK內置的Javap工具即可完成這項任務。

示例:對Javar.class進行反編

enter image description here

注意javap的-c參數是顯示詳細代碼,否則只顯示method,而按照java的老規矩Javar不要加后綴名 同時你也可以使用eclipse的插件Bytecode Visualizer來反編譯字節碼

enter image description here

注意右面的流程圖,大家在上程序設計導論課時都畫過吧,現在發現它的用途了吧,一眼就看出是一個if-else結構,前兩句定義i變量,然后取i=2壓棧常數1,比對i和1以后就都java.lang.system.out了,一個輸出wooyun,一個輸出lxj616。

0x03 老版本的BurpLoader分析:


隨着Burpsuite的更新,BurpLoader也在跟着進行更新,我們從老版本的BurpLoader入手,簡要分析一下之前老版本的burpsuite破解原理。 本處選用了1.5.01版本的BurpLoader進行分析 首先試着用JD-GUI載入BurpLoader:

enter image description here

成功還原了BurpLoader源代碼,只可惜由於是對burpsuite的patch,所以burpsuite的混淆在burploader里仍然可讀性極差,不過可以推斷burploader本身沒有使用混淆工具。

public static void main(String[] args)
  {
    try
    {
      int ret = JOptionPane.showOptionDialog(null, "This program can not be used for commercial purposes!", "BurpLoader by larry_lau@163.com", 0, 2, null, new String[] { "I Accept", "I Decline" }, null);
      //顯示選擇對話框:這程序是出於學習目的寫的,作者郵箱larry_lau(at)163.com 
      if (ret == 0)  //選擇我同意
      {
        //以下用到的是java反射機制,不懂反射請百度
        for (int i = 0; i < clzzData.length; i++)
        {
          Class clzz = Class.forName(clzzData[i]);
          //是burpsuite的靜態類(名字被混淆過了,也沒必要列出了)
          Field field = clzz.getDeclaredField(fieldData[i]);
         //靜態類中的變量也被混淆過了,也不必列出了
          field.setAccessible(true);
        //訪問private必須先設置這個,不然會報錯

          field.set(null, strData[i]);
        //把變量設置成strData(具體那一長串到底是什么暫不討論)
        }

        Preferences prefs = Preferences.userNodeForPackage(StartBurp.class);
        //明顯preferences是用來存儲設置信息的
        for (int i = 0; i < keys.length; i++)
        {
          // key和val能猜出是什么吧
          String v = prefs.get(keys[i], null);
          if (!vals[i].equals(v))
          {
            prefs.put(keys[i], vals[i]);
          }
        }
        StartBurp.main(args);
      }
    }
    catch (Exception e)
    {
      JOptionPane.showMessageDialog(null, "This program can only run with burpsuite_pro_v1.5.01.jar", "BurpLoader by larry_lau@163.com", 
        0);
    }
  }
}

因此,BurpLoader的原理就是偽造有效的Key來通過檢測,Key的輸入是通過preference來注入的,而我猜測它為了固定Key的計算方法,通過反射把一些環境變量固定成常量了

0x04 新版本的BurpLoader分析:


以下用1.6beta版的BurpLoader進行分析: 首先用JD-GUI嘗試打開BurpLoader:

enter image description here

看來這個版本的BurpLoader對字節碼使用了混淆,這條路走不通了 於是直接讀字節碼吧!

enter image description here

大家可以看到這里的字符串都是混淆過的,每一個都jsr到151去解密

enter image description here

這段解密代碼特點非常明顯,一個switch走5條路,給221傳不同的解密key,這不就是Zelix KlassMaster的算法嗎? 簡單的異或而已,輕松寫出解密機:

public class Verify {
    private static String decrypt(String str) {
        char key[] = new char[] {73,25,85,1,29};
        char arr[] = str.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            arr[i] ^= key[i % 5];
        }
        return new String(arr);
    }

    public static void main (String args[]) {
        System.out.println(decrypt("%x'sdgu4t3#x#`egj\"hs.7%m|/7;hp+l&/S t7tn\5v:j\'}_dx%"));
    }
}

里面的5個密鑰就是上圖bipush的傳參,別忘了iconst_1的那個1 解密出來是:larry.lau.javax.swing.plaf.nimbus.NimbusLook:4

其實這里解密出字符串沒有什么用處,因為我們已經拿到老版本的源代碼了,不過在別的軟件逆向分析中可能會非常有用

0x05 總結&POC


以下為我修改后的BurpLoader,其中的惡意代碼我已經去除,並將修改前的原值輸出,大家可以在添加burpsuite jar包后編譯運行這段代碼

package stratburp;

import burp.StartBurp; 
import java.lang.reflect.Field; 
import java.util.prefs.Preferences; 
import javax.swing.JOptionPane; 

public class startburp 
{ 

  private static final String[] clzzData = { "burp.ecc", "burp.voc", "burp.jfc",  
    "burp.gtc", "burp.zi", "burp.q4c", "burp.pid", "burp.y0b" }; 

  private static final String[] fieldData = { "b", "b", "c", "c", "c", "b", "c", "c" }; 
  private static final String errortip = "This program can only run with burpsuite_pro_v1.5.01.jar"; 
  private static final String[] keys = { "license1", "uG4NTkffOhFN/on7RT1nbw==" }; 

  public static void main(String[] args) 
  { 
    try 
    { 
        for (int i = 0; i < clzzData.length; i++) 
        { 
          Class clzz = Class.forName(clzzData[i]); 
          Field field = clzz.getDeclaredField(fieldData[i]); 
          field.setAccessible(true); 

          //field.set(null, strData[i]); 
          System.out.println(field.get(null));
        } 

        Preferences prefs = Preferences.userNodeForPackage(StartBurp.class); 
        for (int i = 0; i < keys.length; i++) 
        { 
          String v = prefs.get(keys[i], null); 
          System.out.println(prefs.get(keys[i], null));
        } 
        StartBurp.main(args); 
    } 
    catch (Exception e) 
    { 
      JOptionPane.showMessageDialog(null, "This program can only run with burpsuite_pro_v1.5.01.jar", "Notice",0); 
    } 
  } 
}

其效果如截圖所示

enter image description here

其中前8行輸出為之前BurpLoader惡意修改的目標原值(對我的計算機而言),同一台設備運行多少遍都是不變的,后面的key由於我之前運行過BurpLoader因此是惡意修改后的值(但是由於前8行沒有修改因此不能通過Burpsuite驗證),可見BurpLoader其實是使用了同一個密鑰來注冊所有不同計算機的,只不過修改並固定了某些參與密鑰計算的環境變量而已,這大概就是Burpsuite破解的主要思路了,至於最初能用的license是怎么計算出來的,我們以后再研究

 

收藏 

 

http://drops.wooyun.org/tips/2689

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM