熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

防止JAVA代碼被反編譯的方法

2013-11-23 18:48:09  來源: Java核心技術 

  我們都知道JAVA是一種解析型語言這就決定JAVA文件編譯後不是機器碼而是一個字節碼文件也就是CLASS文件而這樣的文件是存在規律的經過反編譯工具是可以還原回來的例如DecafeFrontEndYingJAD和Jode等等軟件下面是《Nokia中Short數組轉換算法》

  類中Main函數的ByteCode

   ldc #

   invokestatic #

   astore_

   return

  其源代碼是short [] pixels = parseImage(/efspng);

  我們通過反編譯工具是可以還原出以上源代碼的而通過簡單的分析我們也能自己寫出源代碼的

  JAVA手機網[]第一行ldc #

  ldc為虛擬機的指令作用是壓入常量池的項形式如下

  ldc index

  這個index就是上面的也就是在常量池中的有效索引當我們去看常量池的時候我們就會找到index為的值為String_info裡面存了/efspng

  所以這行的意思就是把/efspn作為一個String存在常量池中其有效索引為

  第二行 invokestatic #

  invokestatic為虛擬機指令作用是調用類(static)方法形式如下

  invokestatic indexbyte indexbyte

  其中indexbyte和indexbyte必須是在常量池中的有效索引而是指向的類型必須有Methodref標記對類名方法名和方法的描述符的引用

  所以當我們看常量池中索引為的地方我們就會得到以下信息

  Class Name : cp_info#

  Name Type : cp_info#

  都是常量池中的有效索引值就是右邊<>中的值再往下跟蹤我就不多說了有興趣的朋友可以去JAVA虛擬機規范

  這裡我簡單介紹一下parseImage(Ljava/lang/String;)[S 的意思

  JAVA手機網[]這就是parseImage這個函數的運行我們反過來看看parseImage的原型就明白了

  short [] parseImage(String)

  那麼Ljava/lang/String;就是說需要傳入一個String對象而為什麼前面要有一個L呢這是JAVA虛擬機用來表示這是一個Object如果是基本類型這裡就不需要有L了然後返回為short的一維數組也就是對應的[S是不是很有意思S對應著Short類型[對應一維數組那有些朋友要問了兩維呢那就[[呵呵是不是很有意思

  好了調用了函數返回的值要保存下來吧那麼就是第三行要做的事情了

  第三行 astore_

  呵呵很簡單的但是卻有文章也是比較容易混亂的地方

  astore_為虛擬機指令作用為將當前reference存儲到局部變量中去而必須是對當前框架的局部變量的有效索引打個比方可能我們這個函數中可能還要用到這個局部變量我們可以通過來找到它例如調用虛擬機指令

  aload_就能得到該值

  第四行 return

  同樣的return也是虛擬機指令了它的作用為從方法返回void

  這裡也就是退出main函數

  

  ok終於啰嗦完畢了有些朋友可能要問這麼復雜才四行就說這麼多呵呵可能是我這人廢話過多當然如果你熟悉了一點就能看懂了通過肉眼就可以反編譯程序了目前所有的反編譯工具都無法做到完美反編譯在有問題的地方還需要人去修正

  好了說了半天如何反編譯我們就來看看如果在你的程序如果防止別人來反編譯好不容易寫好的程序被人反編譯了多郁悶哈哈工欲善其事必先利其器這句話用對了嗎?

  什麼混淆等等的方法我就不說了我這裡主要是要說一種通過添加代碼來在某種程度來避免當前流行的反編譯工具對你的代碼進行反編譯

  方案一

  首先要添加一個參數為Exception類型的函數例如這樣

  public static void Fake(Exception e)

  {

  JAVA手機網[]       etoString();

  }

  一定要有etoString();因為要防止你的混淆器把無用的代碼過濾

  然後在每個類中調用這個函數放在trycatch(Exception e)中的catch裡面例如

  try

  JAVA手機網[]   {

  

  }

  catch (Exception e)

  {

  Fake(e);

  }

  請注意 一定要放在catch才有用其他地方無用

  方案二

  如果以上方法還不夠專業我們再來一個呵呵~

  同樣的我們定義一個類這個類叫做AntiCrack名字好像有點大代碼如下

  public class AntiCrack

  {

  private AntiCrack()

  {

  }

  public static Throwable Fake(Throwable throwable Throwable throwable)

  {

  try

  {

  throwablegetClass()getMethod(initCause new Class[] {

  JAVA手機網[]               javalangThrowableclass

  })invoke(throwable new Object[] {

  throwable

  });

  }

  catch(Exception exception) { }

  return throwable;

  }

  }

  同樣的我們在catch裡面調用該函數例如如下

  try

  {

  //your code here

  }

  catch(IOException ioexception)

  {

  IllegalArgumentException illegalargumentexception = new IllegalArgumentException(ioexceptiontoString());

  AntiCrackfake(illegalargumentexception ioexception);

  throw illegalargumentexception;

  }

  或者也可以這樣

  public class AntiException extends Exception

  {

  public AntiException()

  {

  }

  public AntiException(String s)

  {

  super(s);

  }

  public AntiException(String s Throwable throwable)

  {

  super(s);

  AntiCrackfake(this throwable);

  }

  }

  JAVA手機網[]然後在你的程序裡面

  try

  {

  }

  catch(IoException e)

  {

  throw new AntiException(ioexceptiontoString() ioexception);

  }

  當采用以上方式後任何類只要調用了該函數生成的class反編譯後出錯得不到結果

  DecafeFrontEnd和YingJAD反編譯時都有exception然後無法進行下去大家可以多測試變得反編譯工具建議推薦用第二個方法

  呵呵有什麼問題可以給我mail


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25765.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.