Jeb軟件簡單分析


         Jeb是一款分析Android軟件的利器,即使app軟件高度混淆代碼(一種軟件保護機制),它都能夠很好的理清邏輯。Jeb是用Java語言寫的一門軟件,比較貼合Android軟件的分析,因為Android大部分代碼也是Java編寫(Native 層用C++編寫)。

         網上有修改關鍵文件的教程,卻沒有如何定位到該文件的說明,所以感覺就是做現成的事情,沒有真正的研究價值。

         我之前都是分析其他類型的軟件,它們大部分可以用ollydbg(32位程序分析調試軟件),或者x64_dbg(64位程序分析調試軟件)分析,C#(感覺和Java的結構類似)軟件可以用dnSpy等軟件分析,由於比較難改代碼,沒怎么深入研究。現在嘗試研究Java軟件,分析邏輯。

        本次要達到的目的:

           1>定位破解點,順便分析邏輯

     2>嘗試修改字節碼文件

     3>分析破解作者使用Javaagent的機制

        下面切入正題:

過期的軟件界面如下圖,點擊ok后,軟件退出,根本無法使用。

 

        破解軟件的常規思路是到安裝目錄去查找可疑文件,尤其是一些ini文件,通常情況下,一些軟件會把注冊信息保存到該類型文件下,作為重啟驗證(該類型軟件最難搞定)的訪問文件。我們到安裝目錄搜尋資料,可以發現….\bin\configuration\org.eclipse.osgi目錄下有很多結構類似的文件,它們的子目錄和最里面的文件結構類似。現在的疑問是:軟件為什么要創建那么多的相似文件,主要還是軟件如何匹配這些文件來執行相關操作。

現在做出推測:如果把根目錄org.eclipse.osgi刪除,軟件應該會報錯。

測試結果:軟件沒有報錯,依舊運行,同時發現再次生成org.eclipse.osgi目錄及里面的文件,那么,這些文件是從哪里創建過來的呢?使用JDK自帶的工具搜集信息。步驟如下:

   1.從bin目錄運行jeb.exe軟件(禁用腳本運行,腳本運行為破解版)。

   2.打開cmd運行窗口,執行jps –l,結果如下(1492為jeb軟件的pid):

         3.在cmd窗口執行jinfo 1492后,打印出很多相關信息,重要信息如下:

         其中的org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar文件是jeb軟件啟動時調用的入口jar包。如果我們轉到該jar文件的同目錄,啟動cmd窗口(shift+右鍵->在此處打開命令窗口),執行java –jar org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar命令,jeb軟件便可以啟動。如果加入verbose參數,執行該命令啟動jeb軟件,則會打印出相關的類加載信息。

         4.執行java –jar –verbose org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar >> E:\jeb_analysize.txt 命令,將打印信息存於jeb_analysize.txt文件,便於查找相關信息。

重要信息如下:這個信息和軟件的底部輸出一樣。

現在做出推測:該信息是軟件加載上面的類時出現的,重要的代碼邏輯應該在里面。到底是哪個類呢?

        選擇與該信息最近的一個類分析:

[Loaded com.pnfsoftware.jeb.client.installer.SoftwareUpdater from file:/E:/Program Files/jeb-2.2.7/bin/configuration/org.eclipse.osgi/114/0/.cp/libs/jeb.jar]

        該jar包與軟件更新有關,與下面的輸出信息吻合得很好,此jar包為分析邏輯的關鍵。同時也會發現,該信息存在於org.eclipse.osgi目錄下,這就意味着,如果要破解該軟件的使用期限,則必須找到它的根源,從本質上解決問題。現在的問題是:該jeb.jar是從哪個jar包中復制過來的(一般不會通過解密文件產生)?

         5.定位該jar包。

記得Windows下有一個叫notepad++的軟件可以搜索目錄中的文件,找到里面的字符串。使用該軟件搜索到的信息如下:

        圖片中除了org.eclipse.osgi目錄(自動生成的文件除外),就是com.pnfsoftware.jeb.rcpclient_2.2.7.201608151620.jar文件了。打開查看文件如下:

        可以看到該jeb.jar確實存在,現在做一個測試,進一步確定該文件為org.eclipse.osgi目錄下文件生成的根源,在jeb.jar里面插入任意文件,只要能區分就行,然后刪除org.eclipse.osgi目錄(重新生成的文件較少,便於查找,也便於排除干擾)。

最后發現org.eclipse.osgi目錄下的jeb.jar中確實有我們插入的文件,由此驗證該jeb.jar來自於com.pnfsoftware.jeb.rcpclient_2.2.7.201608151620.jar包中,為破解逆向的重點。

          6.分析代碼。

       解壓縮jeb.jar文件,然后使用jd-gui軟件轉到SoftwareUpdater.class,具體路徑參照 com.pnfsoftware.jeb.client.installer.SoftwareUpdater結構。

         在該類中除了一些實現解壓縮包的代碼,並沒有找到具體的信息,確實有些沮喪,但從打印的信息看,該類確實執行了啊。該怎么辦呢?我們會考慮到該類的引用,一旦引用該類,則相關的類成員變量和成員方法便有可能初始化,這個時候可以搜索 “new SoftwareUpdater”,但我直接搜索SoftwareUpdater即可。重要信息如下:

        通過 “The software update reported”字符串(軟件底部輸出的信息與下面的代碼匹配),可以證明此處是一個分析的重點。 

       7.分析重要代碼

        由於“The software update reported”字符串在start()方法體中,分析查找調用該方法的地方,作為下一步分析的依據,調用處之上之下都要分析。

          start()方法什么時候被調用執行的呢?可以使用jd-gui軟件搜索方法.start(),但軟件不好使,無法進一步縮小搜索范圍,同時也存在大量的start()方法,無法進行區分,該方法自然行不通。那該用什么樣的方法呢?思路如下:

傳統的調用方法方式如下:

         1.使用關鍵字new 類名(),產生的引用變量很快用來訪問成員變量,成員方法。

         2.類中的方法前有static,則可以用 “類名.方法名”的訪問方法,或者“類名.變量” 訪問變量。它們都用到類名,所以可以直接搜索類名(AbstractClientContext),以便進一步縮小范圍,然后嘗試找到該變量與start()方法之間的聯系。

         在搜索中並沒有找到該類型變量與start()方法的聯系,這是不是太沮喪啦?難道這是要得到一個悲傷的結局嗎?我堅信start()方法一定被調用執行啦,信念的力量真的很強大,堅持吧,我們要的是各種各樣的思維,方法不唯一,需要的是耐心,毅力和決心,以及對知識的反復整合和驗證。

        我意外的想到Java中的繼承,接口和抽象類,尤其繼承比較熟悉,再次搜索(AbstractClientContext),結果發現如下代碼:

        對於類繼承,子類自然具有父類的各種特性,子類可以擴展自己的功能,也可以改寫父類的方法,重要的是子類可以調用自己不存在,而父類存在的方法。可以猜測這里的子類NE調用父類AbstractClientContext里的start()方法。

        這一次直接搜索NE,查找到可疑文件,將整頁文件復制粘貼到editplus軟件,查找start()方法,在排除掉無用的那一部分,就是值得分析研究的啦!找到的信息如下截圖:

        現在驗證一下猜測:我們單擊(NE)localObject4).start()里面的start()方法(圖1),跳轉到圖2,說明調用的是該方法,在單擊super.Start()方法,就跳轉到含“The software update reported”字符串的地方(圖3),表明猜測正確。

圖1

圖2

圖3

        在搜索NE的過程中也發現了nR繼承NE,如下截圖:

         難道nR類也有調用start()的嫌疑嗎?我們也用操作NE的方法試試,看看有沒有意外收獲。

         搜索過程中發現很多文件含“nR”,將那些聯系不大的文件排除,實際感覺可用的也不多。但遺憾的是,並沒有找到相關變量調用start()方法。不過也好,省去分析那么多文件的麻煩。

         發現(NE)localObject4).start()代碼以上已經到頂峰(分析到main方法),以下是一些腳本啟動相關的代碼,都不重要。只能向下分析 (“The software update reported”以下),畢竟彈窗顯示的錯誤信息是在該信息提示后出現,重點應該在后面。

向下主要分析必須執行的邏輯和可疑方法(register,license等等),跳過版權信息代碼,重要截圖如下:

    圖1 

                                                  

  圖2        

          Java字節碼如何修改呢?我通過百度搜索,發現一個Javassit類庫,它可以編輯和創建Java字節碼。

學習Javassit主要完成:

         1.第三方類庫的導入和調用。

         2.學習Javassit的語法。

         3.完成AbstractClientContext.class文件里的getExpirationTimestamp()方法修改。

        Javassit的jar包導入eclipse軟件,並沒有什么難度,百度一下自然有方法,其實Google的搜索引擎更強大,只是不習慣英文而放棄了。我一直有一種認為:人的記憶力太有限了,用來記住那些常用的就行了,對於不常用的,有一個模糊的記憶,大概就行了,關鍵在於有一種好的邏輯能力,去分析問題,能夠有解決問題的方法,或者知道如何去獲取解決問題的相關信息。

         從百度找到的javassit信息是散亂的,不成體系的,於我而言,並不重要。我的側重點在於學習常用語法,完成本次字節碼的修改。我選擇學習語法跟上實際例子,同時動筆,這樣加深我對Javassit的感情,難道不覺得,我正在試圖尋找真愛嗎?努力和付出不知能否換來她的千百次中相遇的一個回眸,期待的眼神,企盼的心靈正在千百個默默的堅持中。

         學習中,我是一部分一部分的寫,一部分一部分的調試,一部分一部分的修改,就這樣循環往復,直到對應的代碼通過為止(查錯和修改是非常痛苦的事情,我甘願在悲傷的故事里翱翔,尋找真愛)。

       下面是javassit修改字節碼的java源碼,在不同的機器上可能或多或少有一些錯誤,吃點感冒葯就好了,並無大礙。

package ctClass;

 

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import javassist.CannotCompileException;

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

import javassist.NotFoundException;

 

public class Pool_Exercise {

 

       public static void main(String[] args) {

      

       ClassPool pool = ClassPool.getDefault();//默認系統搜索類庫

        try {

         pool.insertClassPath("C:\\Users\\shyx\\Desktop\\jeb.jar");//取jar文件

         CtClass  ct =  pool.get("com.pnfsoftware.jeb.client.Licensing");//取類名(包名.類名)

         CtMethod meth = ct.getDeclaredMethod("getExpirationTimestamp",null); //取修改方法

         meth.setBody("return 6000000000;"); 

         FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\shyx\\Desktop\\Licensing.class"));//輸出字節碼文件

      fos.write(ct.toBytecode());

      fos.close();                   

              } catch (NotFoundException e) {

                     e.printStackTrace();

       } catch (CannotCompileException e) {

              }catch (Exception e) {

                     e.printStackTrace();

              }

       }

}

 

         如果直接修改原始的jeb.jar文件,會出現圖1錯誤,message顯示表明:sha1的存在,致使拋出異常。那該怎么辦呢?我們打開jar包里MEAT-INF\MANIFEST.MF文件。內容見圖2。既然該文件存在,我們把它刪除,應該就可以啦!但結果表明此法行不通。還有什么辦法呢?

         圖1

         圖2

         我直接把jeb.jar 解包,刪除MEAT-INF目錄,然后用jar 命令重新打包,效果見圖3。

     圖3

具體操作:轉到解包后的文件夾,啟用cmd窗口(shift+右鍵指定選項),然后執行jar –cvf jeb.jar 。

          最后運行程序,沒有報錯,生成Licensing.class文件,使用jd-gui打開查看getExpirationTimestamp()方法,結果如下:

           

                                                                              

         最后將修改后的文件替換掉原文件(選擇WinRAR軟件的存儲模式),測試通過,但含有“The software update reported”字符串,挑剔的我不喜歡,果斷去掉吧!

       我們現在需要修改AbstractClientContext.class文件里的bool1,去掉里面的嘆號(圖1)。這里使用JavaBite軟件(功能比較有限,不太喜歡使用)修改邏輯就行了。

具體操作:使用類加載功能加載字節碼文件,在Methods里找到start()方法,定位到如圖2處,將 “ifne 36”改為“ifeq  36”,改后效果如圖3,最后替換測試效果見圖4。  圖1

圖2

圖3

圖4 

        現在研究一下作者的破解文件,既然要研究作者的代碼,就需要考慮從什么地方開始,這里選擇從windows批處理腳本開始,雖然我不懂,但里面重要的語句並不多,抽出了看看就行啦!

          如果將那些變量具體化,整個重要語句就可以寫成:Java  -javaagent:xxx.jar  –jar  yyy.jar (xxx是我們寫的可運行jar包,yyy是我們軟件的入口jar包)。

現在的重點變為作者的jebloader.jar文件,打開目錄如圖:

 

        里面的javassit類庫已經變成字節碼文件。為什么需要這個類庫呢?因為Javaagent攔截下來的文件需要Javassit類庫支持修改。

        Loader.class和loader$1.class文件內容差不多,容易找到差異,如果不習慣,可以使用Beyond Compare軟件比較。

        在eclipse里面盜版一個,結果沒有成功,就一直停留在代碼的檢查上,還是沒結果,簡直懷疑自己的智商,最后在里面加了toClass()方法成功啦。網上說:Javassit里面使用toBytecode()方法、toClass()方法和writeFile()方法,能夠將里面的CtClass凍結。我認為凍結后的數據不在改變,自然能夠得到我們想要的結果,但使用toBytecode()方法、WriteFile()都沒成功,費解啊!

      下面是我修改后的Java源碼,已去除無用模塊(大部分與作者原文內容一致)。

package simple_agent_javassit;

 

import java.io.ByteArrayInputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.lang.instrument.ClassFileTransformer;

import java.lang.instrument.IllegalClassFormatException;

import java.lang.instrument.Instrumentation;

import java.security.ProtectionDomain;

import javassist.CannotCompileException;

import javassist.ClassPool;

import javassist.CtClass;

import javassist.CtMethod;

import javassist.NotFoundException;

 

public class Agent_Javassit {

 

 public static void premain(String agentOps, Instrumentation inst){

        inst.addTransformer(new ClassFileTransformer() { //開頭照寫

           

    @Override  //重寫transform方法,功能的主體在里面,字節碼加載到虛擬機前進入。

public byte[] transform(ClassLoader loader, String className,

                Class<?> classBeingRedefined, ProtectionDomain protectionDomain,

                    byte[] classfileBuffer) throws IllegalClassFormatException {

                

 className = className.replace("/", "."); //將包名與類名之間的“/”換成“.”

         if (className.equals("com.pnfsoftware.jeb.client.Licensing")) {

            try

                {

                  ClassPool pool = ClassPool.getDefault();

                  CtClass ctx = pool.makeClass(new ByteArrayInputStream(classfileBuffer));//應該是取字節數組流,classfileBuffer應該與className同步。

                   CtMethod a = ctx.getDeclaredMethod("getExpirationTimestamp", null);

                    System.out.println("loader加載100%~");

                    a.setBody("return 6000000000;");

                    ctx.toClass();

                     return ctx.toBytecode();

                  }catch (NotFoundException e){

                  }catch(CannotCompileException e){

                  }catch(Exception e){

                  e.printStackTrace();

                  }

                }

                return new byte[0];

            }

        });

      }

}

        最后創建一個類,里面含一個空的main()方法,用於生成可執行jar包的入口配置參數即可。

 

       結束語寫什么呢?寫那些不曾留住的惋惜,還是美好未來的展望。故事的最后,留下的終究是那個孤獨前行的自己和一堆寫不完的散文詩。

       塵封住記憶,終究需要那些難以忘記的瞬間,給予鼓勵,戰勝困難的決心和勇氣。過去再見,帶走憂郁帶走悲傷,未來是迷是希望是心中的朝陽,是五月的花朵,嬌艷美麗。

 


免責聲明!

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



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