<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    GalaxyPilot —— D.S


            生命不熄,戰(zhàn)斗不止
    數(shù)據(jù)加載中……

    淺談JAVA程序破解

    淺談JAVA程序破解

    作者:舵手
    申明:如轉(zhuǎn)載請(qǐng)保證文章的完整性以及出處

    ????最近對(duì)JAVA程序的破解比較感興趣,拿幾個(gè)行業(yè)軟件練了一下手,略有心得,拿出來(lái)與菜鳥(niǎo)分享!注意只是一點(diǎn)心得,
    本文并不涉及具體軟件的破解。初學(xué)破解,失誤之處在所難免,敬請(qǐng)高手賜教!
    ????直接進(jìn)入正題,對(duì)JAVA的破可從下面幾方面入手:

    一、反編譯
    ????工具很多,建意用GUI工具,命令行下的JAD很容易因?yàn)椴荒芊淳幾g某一個(gè)方法或某一行代碼而終止整個(gè)文件的反
    編譯,但GUI的工具卻能搞定,雖然反編譯后部分代碼較難看懂,但總比看jvm指命要好得多。而且,GUI的工具多數(shù)有
    批量反編譯功能,且能讓反編譯的文件直接以.java為后綴保存,也是方便之處。
    二、方法調(diào)用
    ????安全意識(shí)強(qiáng)的開(kāi)發(fā)者會(huì)把他的程序進(jìn)行高質(zhì)量的混淆,下面就是一個(gè)例子
    public?static?Object?getRemoteEJBHome(String?OOOoOo00oO0O0O0ooOoOO,?Class?OO0oOO0O0o0oO0o00oOoO)
    throws?NamingException
    {
    try
    {
    ????if(OoO0o0o0O0oo0oO00oOO0?==?null)
    ??OoO0o0o0O0oo0oO00oOO0?=?OoOOoOOO0Oo0OO0OooO0o();
    ????Object?OOOOOo00000OoOoO0O000?=?PortableRemoteObject.narrow(OoO0o0o0O0oo0oO00oOO0.lookup(OOOoOo00oO0O0O0ooOoOO),?OO0oOO0O0o0oO0o00oOoO);
    ????Object?obj?=?OOOOOo00000OoOoO0O000;
    ????return?obj;
    }
    catch(NamingException?OO0Ooo0oOO0OO0OOOoOo0)
    {
    ????System.out.println(OO0Ooo0oOO0OO0OOOoOo0.getMessage());
    ????throw?OO0Ooo0oOO0OO0OOOoOo0;
    }
    }
    這是我見(jiàn)過(guò)的最好的混淆效果,變量都是由大小寫的O和數(shù)字零組程,要看懂這樣的程序基本上是不可能的,可能有
    人會(huì)想到用有意義的變量進(jìn)行替換,當(dāng)然這也是一個(gè)方法,但如果應(yīng)用所包括的class文件數(shù)以千記,那這個(gè)工作量
    是相當(dāng)大的。B/S結(jié)構(gòu)的授權(quán)方式一般都是文件的形式,當(dāng)然,肯定是經(jīng)過(guò)加密的。像下面的license就是經(jīng)過(guò)了RSA
    非對(duì)稱加密算法,要分析license的構(gòu)成,有明文的license就更方便了,而公鑰是直接被寫在class文件中的
    24D568B6A27AEFD683BC7A1CC93D11D074FB6B982A4B6E269712773BE536B40A67F1D345654F659C66D4265F5CE8FE0494B3A
    F33A8299A4F6B0E7500275A27EFF3B6D2E4983F14A9EA38A1AE3394B28A9C6D6924C15027F9B689FD9A3A689A301C4D4EB878
    D75C207F68BAA352F550D8F19876FFA255864FDE8A7E5939202E9F
    那么我們可以用eclipse建一個(gè)JAVA項(xiàng)目,把應(yīng)用的jar加入該項(xiàng)目的庫(kù)搜索路徑,寫一個(gè)自己的類調(diào)用解密方法,得到
    明文license再分析。當(dāng)然,也可以調(diào)用其它一些方法,從調(diào)用參數(shù)和最后的返回值我們也可大概猜對(duì)該方法的作用,
    對(duì)付象上面經(jīng)過(guò)高質(zhì)量混淆的代碼也比較管用。當(dāng)然,我這里只是簡(jiǎn)單的舉兩個(gè)例子,其實(shí)“方法調(diào)用”的妙用還很多,
    自己慢慢琢磨吧!
    三、為class添加代碼
    ????反編譯多數(shù)情況下也只能讓我們看看作者的思路,如果想把反編譯出來(lái)的代碼經(jīng)過(guò)修改后再編譯成class,通常
    是行不通了。而且有時(shí)候必須讓程序運(yùn)行在它本身的環(huán)境才能行,否則一些類無(wú)法得到正確的初始化,“方法調(diào)用”
    也就起不了什么作用。搞過(guò)java的人一定知道javassist,這個(gè)庫(kù)提供了足夠多的方法讓你直接修改class文件,而不
    需要你了解字節(jié)碼的相關(guān)知識(shí),我們可以利用這個(gè)庫(kù)解決上述的問(wèn)題。下面是我寫的一個(gè)修改字節(jié)碼的類,目前還不
    完善,真正要用時(shí)可能需要根據(jù)情況做一些修改。
    import?java.lang.reflect.*;
    import?javassist.*;
    import?java.io.*;
    /**
    ?*?<p>Title:?JAVA?字節(jié)碼修改類</p>
    ?*?<p>Description:?得到類的相關(guān)信息或修改該類</p>
    ?*?<p>Copyright:?Copyright?()?2005</p>
    ?*?@author?舵手
    ?*?@version?1.0
    ?*/
    public?class?ModifyClass?{
    ??private?static?int?call_method;
    ??private?static?String?_class;
    ??private?static?ClassPool?pool;
    ??private?static?CtClass?cc;
    ??private?static?String[]?clas;
    ??/**
    ???*?修改字節(jié)碼中的方法
    ???*?@param?clas[0]?待修改類的方法名
    ???*?@param?clas[1]?修改位置定義
    ???*?@param?clas[2]?使用insertAt方法插放代碼時(shí)行號(hào)參數(shù)
    ???*?@param?clas[3]?修改內(nèi)容
    ???*?@return
    ???*/
    ????private?static?void?modifyMethod()
    ????{
    ????String?_method;
    ????_method?=?clas[0];
    ????????try
    ????????{
    ??????CtClass[]?param?=?new?CtClass[4]?;????????????????
    ??????//param[0]?=?pool.get("");
    ??????//param[1]?=?pool.get("");
    ??????//param[2]?=?pool.get("java.lang.String");
    ??????//param[3]?=?pool.get("java.lang.String");

    ??????CtMethod?cm?=?cc.getDeclaredMethod(_method);
    ??????if?(clas[1].toLowerCase().equals("a"))
    ??????{
    ????????//方法的尾部加入代碼
    ????????cm.insertAfter(clas[3]);
    ??????}
    ??????if?(clas[1].toLowerCase().equals("b"))
    ??????{
    ????????//方法的首部加入代碼
    ????????cm.insertBefore(clas[3]);
    ??????}
    ??????if?(clas[1].toLowerCase().equals("i"))
    ??????{
    ????????System.out.println(cm.insertAt((Integer.valueOf(clas[2]).intValue()),clas[3]));
    ??????}
    ??????cc.writeFile();
    ????????}
    ????????catch(Exception?e)
    ????????{
    ????????????e.printStackTrace();
    ????????}

    ????}
    ??/**
    ???*?在類中增加方法
    ???*?@param?clas[0]?源方法名稱
    ???*?@param?clas[1]?新方法名稱
    ???*?@param?clas[2]?增加類型
    ???*?@param?clas[3]?方法內(nèi)容
    ???*?@return
    ???*/
    ??private?static?void?addMethod()
    ????{
    ????String?_oldmethod;
    ????String?_newmethod;
    ????_oldmethod?=?clas[0];
    ????_newmethod?=?clas[1];
    ????????try
    ????????{
    ??????StringBuffer?newMethodBody?=?new?StringBuffer();
    ????????????if?(clas[2].toLowerCase().equals("c"))
    ????????????{
    ????????//add?new?Method?(copy)
    ????????CtMethod?oldMethod?=?cc.getDeclaredMethod(_oldmethod);
    ????????CtMethod?newMethod?=?CtNewMethod.copy(oldMethod,?_newmethod,?cc,?null);
    ????????newMethodBody.append(clas[3]);
    ????????newMethod.setBody(newMethodBody.toString());
    ????????cc.addMethod(newMethod);
    ????????????}
    ??????if?(clas[2].toLowerCase().equals("r"))
    ??????{
    ????????//add?new?Method?(create)
    ????????CtMethod?newMethod?=?CtNewMethod.make(clas[3],?cc);
    ????????cc.addMethod(newMethod);
    ??????}
    ??????cc.writeFile();

    ????????}
    ????????catch(Exception?e)
    ????????{
    ????????????e.printStackTrace();
    ????????}

    ????}

    ??private?static?void?getMethods(){
    ????CtMethod[]?cms?=?cc.getDeclaredMethods();
    ????System.out.println();
    ????System.out.println(cc.getName()+"?類的所有方法:");
    ????for?(int?i=0?;?i<cms.length?;?i++?)
    ????{
    ??????System.out.println(cms[i].getName());
    ????}
    ??}

    ??private?static?void?getFields(){
    ????CtField[]?cfs?=?cc.getDeclaredFields();
    ????System.out.println();
    ????System.out.println(cc.getName()+"?類的所有屬性:");
    ????for?(int?i=0?;?i<cfs.length?;?i++?)
    ????{
    ??????System.out.println(cfs[i].getName());
    ????}
    ??}
    ??
    ??private?static?void?delMethod(){
    ????try{
    ??????CtMethod?cm?=?cc.getDeclaredMethod(clas[0]);
    ??????cc.removeMethod(cm);
    ????}catch(Exception?e){
    ??????e.printStackTrace();
    ????}
    ??}
    ????public?static?void?main(String[]?args)?{
    ????StringBuffer?buf?=?new?StringBuffer(500);
    ????int?c;
    ????System.out.print("請(qǐng)輸入操作類名:");
    ????try{
    ??????while?((c?=?System.in.read())?!=?13)?{

    ????????buf.append((char)c);
    ??????}
    ??????_class?=?buf.toString();
    ??????pool?=?ClassPool.getDefault();
    ??????cc?=?pool.get(_class);
    ??????buf.delete(0,buf.length());
    ??????System.out.println("***********************************************************");
    ??????System.out.println("可供調(diào)用的方法有:");
    ??????System.out.println("1-modifyMethod,2-addMethod,3-getMethods,4-getFields,5-removeMethod");
    ??????System.out.println("***********************************************************");
    ??????System.out.print("請(qǐng)選擇調(diào)用方法:");
    ??????while?((c?=?System.in.read())?!=?13)?{
    ????????if?(c?==?10)
    ??????????continue;
    ????????buf.append((char)c);
    ??????}
    ??????call_method?=?Integer.parseInt(buf.toString());
    ??????if?(call_method?==?1)
    ??????{
    ????????System.out.println("***********************************************************");
    ????????System.out.println("調(diào)用?modifyMethod?方法參數(shù):");
    ????????System.out.println("方法名稱,插入位置,行號(hào),內(nèi)容");
    ????????System.out.println("***********************************************************");
    ????????buf.delete(0,buf.length());
    ????????while?((c?=?System.in.read())?!=?13)?{
    ??????????if?(c?==?10)
    ????????????continue;
    ??????????buf.append((char)c);
    ????????}
    ????????clas?=?(buf.toString()).split(",");
    ????????modifyMethod();
    ??????}
    ??????buf.delete(0,buf.length());
    ??????if?(call_method?==?2)
    ??????{
    ????????System.out.println("***********************************************************");
    ????????System.out.println("調(diào)用?addMethod?方法參數(shù):");
    ????????System.out.println("源方法,目標(biāo)方法,建立方式,內(nèi)容");
    ????????System.out.println("***********************************************************");
    ????????buf.delete(0,buf.length());
    ????????while?((c?=?System.in.read())?!=?13)?{
    ??????????if?(c?==?10)
    ????????????continue;
    ??????????buf.append((char)c);
    ????????}
    ????????clas?=?(buf.toString()).split(",");
    ????????addMethod();
    ??????}
    ??????if?(call_method?==?3)
    ??????{
    ????????getMethods();
    ??????}
    ??????if?(call_method?==?4)
    ??????{
    ????????getFields();
    ??????}
    ??????if?(call_method?==?5)
    ??????{
    ????????System.out.println("***********************************************************");
    ????????System.out.println("調(diào)用?removeMethod?方法參數(shù):");
    ????????System.out.println("方法名稱");
    ????????System.out.println("***********************************************************");
    ????????buf.delete(0,buf.length());
    ????????while?((c?=?System.in.read())?!=?13)?{
    ??????????if?(c?==?10)
    ????????????continue;
    ??????????buf.append((char)c);
    ????????}
    ????????clas?=?(buf.toString()).split(",");
    ????????delMethod();
    ??????}

    ????}catch(IOException?ioe)
    ????{
    ??????System.out.println();
    ??????ioe.printStackTrace();
    ??????System.exit(0);
    ????}
    ????catch(NotFoundException?nfe)
    ????{
    ??????System.out.println();
    ??????nfe.printStackTrace();
    ??????System.exit(0);
    ????}
    ????catch(NumberFormatException?nfe)
    ????{
    ??????System.out.println();
    ??????nfe.printStackTrace();
    ??????System.exit(0);
    ????}
    ????}
    }

    ????modifyMethod方法用來(lái)在類的指定方法中插入一行或多行代碼,參數(shù)為a時(shí)表示插在方法現(xiàn)有代碼的最后面,為b時(shí)
    表示插在方法現(xiàn)有代碼的最前面,為i時(shí)表時(shí)插在代碼的指定行的前面,這個(gè)行和原代碼中的行沒(méi)有關(guān)系,插入位置
    要插入一次才能確定,為i時(shí)返回的值代表實(shí)際插入位置,由這個(gè)實(shí)際插入位置你可以計(jì)算i的值。在實(shí)際破解中發(fā)現(xiàn),
    用該方法插入一些代碼后,會(huì)使原來(lái)反編譯的不可讀的代碼變的容易讀懂,當(dāng)然,也有可能使本來(lái)可讀性很強(qiáng)的代碼,
    因?yàn)槟悴迦肓艘恍┱Z(yǔ)句而變得不可讀。我常常在關(guān)鍵方法的代碼中插入一些?System.out.println();這樣的代碼來(lái)跟蹤
    程序,還有一點(diǎn)限制,你不能直接用打印輸出的方法來(lái)輸出方法體內(nèi)的局部變量,但你可以對(duì)全局變量進(jìn)行引用操作。
    如果要操作局部變量,目前我所知的方法只能在該類里重建該方法,如果那位有其它的好辦法,也請(qǐng)指點(diǎn)我一下。
    ????addMethod方法在是類中增加一個(gè)新的方法,增加的方式有兩種,這里就不做具體介紹。
    ????其它方法也就不一一解釋了,有興趣的朋友可以研究一下javassist,相信你會(huì)寫出功能更強(qiáng)大的修改class文件的類庫(kù)。
    四、class的修改
    ????在破解過(guò)程中經(jīng)常會(huì)看到rsa非對(duì)稱加密算法,公鑰往往以十六進(jìn)制存放在class文件中,(當(dāng)然,也有對(duì)公鑰加密后存
    放在配置文件中的程序)以便解密已經(jīng)加密過(guò)的信息。前不久破解的一個(gè)J2EE的開(kāi)發(fā)平臺(tái)就是這樣的,license用RSA加密,
    在搞懂了它的算法后,自己構(gòu)件license明文,自己再生成一對(duì)rsa的公私密鑰,用自己的私鑰對(duì)license文明進(jìn)行RSA加密,
    再用十六進(jìn)制編輯器替換程序中所有的公鑰,(當(dāng)然是用你的公鑰替換他的公鑰,不然也沒(méi)法解密)一切就搞定。當(dāng)然,
    我所說(shuō)的只是一個(gè)方面,有時(shí)暴破時(shí)可能還得用到一些JVM的指命,比如你想讓一個(gè)?return?false?的方法?return?ture
    那你就得把相應(yīng)位置的03?AC改為04?AC,位置怎么確定就不用我說(shuō)了吧!
    五、讀JVM指令
    ????沒(méi)有什么可以多說(shuō)的,如果要從jvm指令看懂成程,必須像熟匯編一樣熟悉jvm指令集,還得有一個(gè)工具把class翻譯成
    jvm指令代碼,總不能用十六進(jìn)制編輯器讀代碼嗎?如果真是,那你就太牛了。我這里介紹?bcel?這個(gè)工具,它可以把class
    解釋為jvm指令集并存為html文件,結(jié)果就像下面:
    0??getstatic????????????System.out?Ljava/io/PrintStream;?
    3??ldc??????????????????"is?one"?
    5??invokevirtual????????java.io.PrintStream.println?(Ljava/lang/String;)V(String):void?
    8??getstatic?????????????System.out?Ljava/io/PrintStream;?
    11??ldc??????????????????"is?two"?
    13??invokevirtual????????java.io.PrintStream.println?(Ljava/lang/String;)V(String):void?
    16??getstatic?????????????System.out?Ljava/io/PrintStream;?
    19??ldc??????????????????"is?three"?
    21??invokevirtual????????java.io.PrintStream.println?(Ljava/lang/String;)V(String):void?
    24??getstatic?????????????System.out?Ljava/io/PrintStream;?
    27??ldc??????????????????"is?four"?
    29??invokevirtual????????java.io.PrintStream.println?(Ljava/lang/String;)V(String):void?
    32??return?
    ????這是一個(gè)方法的全部指令,熟悉jvm指令集的話就已經(jīng)能讀懂它在做什么了

    ????發(fā)現(xiàn)有關(guān)JAVA程序破解的文章不是很多,所以本人粗淺的談?wù)摿艘幌翵AVA程序破解時(shí)所用到的一些方法,當(dāng)然,還有很多
    憑經(jīng)驗(yàn)才能找到的靈感,無(wú)法一一列舉,本文質(zhì)在拋磚引玉,望高手能寫一些技術(shù)含量更高的文章供我們這些菜鳥(niǎo)學(xué)習(xí)。

    posted on 2006-04-19 10:54 舵手 閱讀(29013) 評(píng)論(4)  編輯  收藏

    評(píng)論

    # re: 淺談JAVA程序破解  回復(fù)  更多評(píng)論   

    多謝指點(diǎn),這篇文章寫于剛接觸破解之時(shí),所以部分方法沒(méi)有寫到。后來(lái)本打算完善,可人一天比一天變的懶惰,所以就擱置在這里了。
    窮舉私鑰我到?jīng)]有試過(guò),總覺(jué)得太過(guò)渺茫,一般我都是替換公鑰。
    2007-10-19 11:54 | 舵手 QQ:8117892

    # re: 淺談JAVA程序破解  回復(fù)  更多評(píng)論   

    public static Object getRemoteEJBHome(String OOOoOo00oO0O0O0ooOoOO, Class OO0oOO0O0o0oO0o00oOoO)
    throws NamingException
    {

    請(qǐng)問(wèn)這種把包名和變量名稱都替換為OO0oOO0O0o0oO0o00oOoO是使用了什么混淆工具?
    2008-11-10 13:58 | 單飛

    # re: 淺談JAVA程序破解  回復(fù)  更多評(píng)論   

    很崇拜作者

    最近拿到一個(gè)Toefl TPO軟件,Java的,但是Jar被exe4j打包成exe了,運(yùn)行的時(shí)候也不在Temp目錄解壓jar包,不知道該怎么弄了,求助樓主,能否解出Jar或者直接破解

    email:silenceleaf@gmail.com
    2012-09-04 11:11 | silenceleaf

    # re: 淺談JAVA程序破解  回復(fù)  更多評(píng)論   

    我得機(jī)器碼:-bqkfsduaojcgo77nocot13cgjo9d62u0

    不勝感激~
    2012-09-04 11:13 | silenceleaf

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。

    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲色图在线播放| 国产精品亚洲视频| 亚洲成在人线电影天堂色| 色播在线永久免费视频网站| 亚洲国产精品日韩| 国产高潮久久免费观看| 精品国产日韩亚洲一区| 一道本在线免费视频| 免费人成年激情视频在线观看| 黄网站在线播放视频免费观看| 亚洲AV伊人久久青青草原| 成人免费网站视频www| 久久亚洲精品无码播放| 久久免费99精品国产自在现线 | 亚洲国产成人久久综合野外| 国产精品亚洲专一区二区三区| 亚洲精品视频在线看| 毛片免费在线观看| 亚洲精品国产福利在线观看| 黄页网站在线观看免费高清| 亚洲午夜无码久久| 亚洲av无码专区在线观看素人| 国产做国产爱免费视频| 亚洲精品网站在线观看你懂的| 久久精品免费一区二区喷潮| 国产亚洲人成在线播放| 国产啪亚洲国产精品无码| 中文字幕无码免费久久| 亚洲区精品久久一区二区三区| 性盈盈影院免费视频观看在线一区| 极品色天使在线婷婷天堂亚洲| 国产精品亚洲产品一区二区三区 | 日韩精品免费电影| 男女一进一出抽搐免费视频 | 波多野结衣在线免费观看| 亚洲av无码兔费综合| 亚洲日本中文字幕天堂网| 国产免费爽爽视频在线观看| 亚洲精品视频在线观看视频| 国产成人免费a在线资源| 久久黄色免费网站|