如何破解已簽名JAR包

本文版權(quán)歸贛州兆鑫軟件所有,原創(chuàng)未經(jīng)許可禁止轉(zhuǎn)載!
本文僅作學(xué)習(xí)交流目的信姓,提倡軟件正版,反對盜版绸罗!


工欲善其事必先利其器

做事要先掌握大局

  1. 將已簽名包轉(zhuǎn)化為未簽名包从诲;
  2. 定位關(guān)鍵代碼位置左痢;
  3. 修改class文件字節(jié)碼;
  4. 替換class文件重新打包系洛;

不行動總也不能成功

1.將已簽名包轉(zhuǎn)化為未簽名包

如果你用到的Jar文件使用了簽名俊性,它會保證里面的每個class文件不能被修改,所以即使你成功修改了class文件中的字節(jié)碼描扯,得到的Jar也是無法運(yùn)行的定页。這些經(jīng)過簽名的Jar包的META-INF文件夾中一般包含了*.SF和相應(yīng)的*.RSA文件。這些文件記錄Jar包中每個文件的簽名信息绽诚,以保證代碼不被篡改典徊。

使用下面的方法可以重新生成一個未簽名Jar包杭煎。參考自stackoverflow作者Houtman的回答

// 使用JDK編譯代碼
javac JarUnsigner.java

// 執(zhí)行JarUnsigner,如果是同一個文件夾
java -cp . JarUnsigner <inJar> <outJar>

附上源代碼卒落,免得回答被刪

// JarUnsigner.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class JarUnsigner {

  private static final String MANIFEST = "META-INF/MANIFEST.MF";

  public static void main(String[] args){

    if (args.length!=2){
      System.out.println("Arguments: <infile.jar> <outfile.jar>");
      System.exit(1);
    }
    String infile = args[0];
    String outfile = args[1];
    if ((new File(outfile)).exists()){
      System.out.println("Output file already exists:" + outfile);
      System.exit(1);
    }
    try{
      ZipFile zipFile = new ZipFile(infile);
      final ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outfile));
      for (Enumeration e = zipFile.entries(); e.hasMoreElements();) {
        ZipEntry entryIn = (ZipEntry) e.nextElement();

        if (! exclude_file( entryIn.getName() ) ) {

          /* copy the entry as-is */
          zos.putNextEntry( new ZipEntry( entryIn.getName() ));
          InputStream is = zipFile.getInputStream(entryIn);
          byte[] buf = new byte[1024];
          int len;
          while ((len = (is.read(buf))) > 0) {
            zos.write(buf, 0, len);
          }
          zos.closeEntry();

        } else {

          if (MANIFEST.equals(entryIn.getName())){
            /* if MANIFEST, adjust the entry */
            zos.putNextEntry(new ZipEntry(MANIFEST));

            // manifest entries until first empty line. i.e. the 'MainAttributes' section
            // (this method is used so to keep the formatting exactly the same)
            InputStream mIS = zipFile.getInputStream(entryIn);
            BufferedReader in = new BufferedReader(new InputStreamReader(mIS));
            String line = in.readLine();
            byte[] mNL = "\n".getBytes("UTF-8");
            while( line != null && !line.trim().isEmpty() ) {
              zos.write( line.getBytes("UTF-8"));
              zos.write( mNL );
              line = in.readLine();
            }
            zos.write( mNL );
            zos.closeEntry();

          }else{
            /* else: Leave out the Signature files */
          }

        }

      }
      zos.close();
      System.out.println("Successfully unsigned " + outfile);

    }catch(IOException ex){
      System.err.println("Error for file: " + infile);
      ex.printStackTrace();
      System.exit(1);
    }
  }

  /**
   * Exclude .SF signature file
   * Exclude .RSA and DSA (signed version of .SF file) 
   * Exclude SIG-  files  (unknown sign types for signed .SF file)
   * Exclude Manifest file
   * @param filename
   * @return 
   */
  public static boolean exclude_file(String filename){
    return filename.equals("META-INF/MANIFEST.MF") ||
           filename.startsWith("META-INF/SIG-") || 
           filename.startsWith("META-INF/") && ( filename.endsWith(".SF") || filename.endsWith(".RSA") || filename.endsWith(".DSA") );
  }

}


2. 定位代碼關(guān)鍵位置

舉一個需要輸入序列號才能試用的庫文件的例子羡铲,但是為了保護(hù)Jar包作者權(quán)益,對包名進(jìn)行打碼了儡毕。通過Jar包的說明書也切,可以知道如何使用它,就知道是什么地方輸入序列號啦腰湾,要不然是個正常人也沒法用對吧雷恃。例如

// 文檔說這樣子可以驗(yàn)證序列號
authentication.User("333");
authentication.Serial("94306-56191-128286-2967422");

rock & roll

  1. 使用JD反編譯Jar包,然后Save All Sources费坊,具體步驟這里省略倒槐;
  2. 從IDEA新建一個工程,把反編譯的源代碼放到源目錄附井,Jar包可能是經(jīng)過混淆過的讨越,不過這個關(guān)系不大,我們字節(jié)碼都能改羡忘,還怕看不懂混淆谎痢?繼續(xù)往下走
  3. 右擊authentication這個類文件,選擇Find Usages卷雕,快捷鍵一般是Ctrl+G节猿,看到有個叫做p.java的文件用到,做了一些判斷操作Blabla漫雕,看屏幕截圖1:
    屏幕截圖1
  4. 點(diǎn)開這個p.java類搜索到的地方滨嘱,可以看到,它在比較一個返回結(jié)果浸间,然后給出不同的錯誤提示太雨,這個結(jié)果是由一個t.a(三個參數(shù))的方法計算得到,并且看得出來當(dāng)計算結(jié)果的a屬性值為0時就是Licence OK!魁蒜,看屏幕截圖2:
    屏幕截圖2
  5. 好囊扳,我們再來看t.java這個文件的a方法又有什么東東(按住Ctrl鍵,鼠標(biāo)點(diǎn)擊那個t.a)兜看,我們只要保證他得到的結(jié)果的a屬性等于0就好了锥咸,可以看到只有一種情況下a屬性才會等于0,其他時候都是等于-1的细移,到這一步IDEA的使命就完成了搏予,看屏幕截圖3:
    屏幕截圖3

結(jié)果

通過上面5步(取決于不同的包,不一定都是5步)弧轧,我們知道了需要改動t類里面的a方法雪侥,讓它里面操作屬性a時碗殷,值為-1的都改為0就能成功。

3. 修改class文件字節(jié)碼

接下來就要使用dirtyJOE軟件來定位并修改字節(jié)碼了速缨,作者也試過Class Editor, Java Bytecode Editor都因年久失修锌妻,沒改成功。通過查閱JVM文檔我們知道給整數(shù)賦值有幾種指令鸟廓,這里就說兩種:

  • iconst_<i> i可以為 m1,0,1,2,3,4,5从祝,分別設(shè)置的值為-1,0,1,2,3,4,5襟己,指令16進(jìn)制字節(jié)碼分別是02設(shè)置-1引谜,03設(shè)置0,04設(shè)置1擎浴,以此類推
  • bipush <i> i范圍可以是0-255员咽,指令16進(jìn)制字節(jié)碼是10,比如代碼里面有的21就是bipush 21贮预,16字節(jié)碼表示為10 15

let's go

  1. 使用dirtyJOE打開t.class文件贝室,切換到 Methods 頁上,如下圖所示:

    image.png

  2. 雙擊我們需要修改的方法(同名時通過比對方法簽名來區(qū)分)仿吞,進(jìn)入編輯界面滑频,圖中的兩個指令的組合就是將值-1賦值給t$a.a屬性,雙擊圖中的iconst_ml唤冈,字節(jié)碼是02峡迷,改為03,然后回車即可你虹,可以使用Ctrl+F查找多處進(jìn)行修改:

    image.png

  3. 關(guān)閉編輯窗口绘搞,保存修改。

warning

要保證字節(jié)碼的數(shù)量不增多傅物,也不減少夯辖,因?yàn)轭惡皖愔g代碼調(diào)用跟字節(jié)位置關(guān)系密切。不然會導(dǎo)致修改的class文件無法使用董饰。原來一行是1個字節(jié)的蒿褂,繼續(xù)用1個字節(jié),2個的就繼續(xù)兩個卒暂,3個的繼續(xù)保持三個啄栓。

4. 替換class文件重新打包

這是最簡單的一步,將修改好的class文件介却,使用zip壓縮工具替換掉即可谴供。如果是你Windows用戶不推薦使用WinRaR,可以將jar文件(第一步生成的未簽名包)重命名為zip文件齿坷,然后選擇用Windows資源管理器打開桂肌,將修改的class文件復(fù)制粘貼進(jìn)去数焊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市崎场,隨后出現(xiàn)的幾起案子佩耳,更是在濱河造成了極大的恐慌,老刑警劉巖谭跨,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件干厚,死亡現(xiàn)場離奇詭異,居然都是意外死亡螃宙,警方通過查閱死者的電腦和手機(jī)蛮瞄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谆扎,“玉大人挂捅,你說我怎么就攤上這事√煤” “怎么了闲先?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長无蜂。 經(jīng)常有香客問我伺糠,道長,這世上最難降的妖魔是什么斥季? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任训桶,我火速辦了婚禮,結(jié)果婚禮上泻肯,老公的妹妹穿的比我還像新娘渊迁。我一直安慰自己,他們只是感情好灶挟,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布琉朽。 她就那樣靜靜地躺著,像睡著了一般稚铣。 火紅的嫁衣襯著肌膚如雪箱叁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天惕医,我揣著相機(jī)與錄音耕漱,去河邊找鬼。 笑死抬伺,一個胖子當(dāng)著我的面吹牛螟够,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼妓笙,長吁一口氣:“原來是場噩夢啊……” “哼若河!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寞宫,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤萧福,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辈赋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲫忍,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年钥屈,在試婚紗的時候發(fā)現(xiàn)自己被綠了悟民。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡焕蹄,死狀恐怖逾雄,靈堂內(nèi)的尸體忽然破棺而出阀溶,到底是詐尸還是另有隱情腻脏,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布银锻,位于F島的核電站永品,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏击纬。R本人自食惡果不足惜鼎姐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望更振。 院中可真熱鬧炕桨,春花似錦、人聲如沸肯腕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽实撒。三九已至姊途,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間知态,已是汗流浹背捷兰。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留负敏,地道東北人贡茅。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親顶考。 傳聞我的和親對象是個殘疾皇子彤叉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 俗話說:"有錢沒錢,回家過年村怪。"鋼筋水泥澆筑的城市里冷漠的沒有溫馨過新年濃郁的味道秽浇,小橋流水又炊煙四起的故土才是我...
    嘉雁38677閱讀 339評論 3 2
  • 養(yǎng)孩方知,養(yǎng)孩不易甚负,養(yǎng)孩?死好幾回: 孩兒天真可愛柬焕、聰明伶俐,美死梭域; 孩兒不慎吞異物斑举、吃東西卡了一下,嚇?biāo)溃?孩兒...
    紫檸檬2016閱讀 259評論 0 0
  • 文|璇子 希望你多點(diǎn)堅強(qiáng) 方能做自己的鎧甲 不因困難而停步不前 希望你多點(diǎn)謙虛 不忘開始的初心 路方能持續(xù)走得更遠(yuǎn)...
    花非物欲閱讀 173評論 0 6