熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

如何保護Java程序

2013-11-15 11:45:52  來源: JSP教程 

  Java是一種跨平台的解釋型語言Java 源代碼編譯中間字節碼存儲於class文件中Class文件是一種字節碼形式的中間代碼該字節碼中包括了很多源代碼的信息例如變量名方法名等因此Java中間代碼的反編譯就變得非常容易目前市場上有許多免費的商用的反編譯軟件都能夠生成高質量的反編譯後的源代碼所以對開發人員來說如何保護Java程序就變成了一個非常重要的挑戰本文首先討論了保護Java程序的基本方法然後對代碼混淆問題進行深入研究最後結合一個實際的應用程序分析如何在實踐中保護Java程序
  
  反編譯成為保護Java程序的最大挑戰
  
  通常CC++等編程語言開發的程序都被編譯成目標代碼這些目標代碼都是本機器的二進制可執行代碼通常所有的源文件被編譯鏈接成一個可執行文件在這些可執行文件中編譯器刪除了程序中的變量名稱方法名稱等信息這些信息往往是由內存地址表示例如如果需要使用一個變量往往是通過這個變量的地址來訪問的因此反編譯這些本地的目標代碼就是非常困難的
  
  Java語言的出現使得反編譯變得非常容易而有效原因如下由於跨平台的需求Java的指令集比較簡單而通用較容易得出程序的語義信息Java編譯器將每一個類編譯成一個單獨的文件這也簡化了反編譯的工作Java 的Class文件中仍然保留所有的方法名稱變量名稱並且通過這些名稱來訪問變量和方法這些符號往往帶有許多語義信息由於Java程序自身的特點對於不經過處理的Java程序反編譯的效果非常好
  
  目前市場上有許多Java的反編譯工具有免費的也有商業使用的還有的是開放源代碼的這些工具的反編譯速度和效果都非常不錯好的反編譯軟件能夠反編譯出非常接近源代碼的程序因此通過反編譯器黑客能夠對這些程序進行更改或者復用其中的程序因此如何保護Java程序不被反編譯是非常重要的一個問題
  
  常用的保護技術
  
  由於Java字節碼的抽象級別較高因此它們較容易被反編譯本節介紹了幾種常用的方法用於保護Java字節碼不被反編譯通常這些方法不能夠絕對防止程序被反編譯而是加大反編譯的難度而已因為這些方法都有自己的使用環境和弱點
  
  隔離Java程序
  
  最簡單的方法就是讓用戶不能夠訪問到Java Class程序這種方法是最根本的方法具體實現有多種方式例如開發人員可以將關鍵的Java Class放在服務器端客戶端通過訪問服務器的相關接口來獲得服務而不是直接訪問Class文件這樣黑客就沒有辦法反編譯Class文件目前通過接口提供服務的標准和協議也越來越多例如 HTTPWeb ServiceRPC等但是有很多應用都不適合這種保護方式例如對於單機運行的程序就無法隔離Java程序這種保護方式見圖所示
  
   
  圖隔離Java程序示意圖
  
  對Class文件進行加密
  
  為了防止Class文件被直接反編譯許多開發人員將一些關鍵的Class文件進行加密例如對注冊碼序列號管理相關的類等在使用這些被加密的類之前程序首先需要對這些類進行解密而後再將這些類裝載到JVM當中這些類的解密可以由硬件完成也可以使用軟件完成
  
  在實現時開發人員往往通過自定義ClassLoader類來完成加密類的裝載(注意由於安全性的原因Applet不能夠支持自定義的ClassLoader)自定義的ClassLoader首先找到加密的類而後進行解密最後將解密後的類裝載到JVM當中在這種保護方式中自定義的ClassLoader是非常關鍵的類由於它本身不是被加密的因此它可能成為黑客最先攻擊的目標如果相關的解密密鑰和算法被攻克那麼被加密的類也很容易被解密這種保護方式示意圖見圖
   
  圖 對Class文件進行加密示意圖
  
  轉換成本地代碼
  
  將程序轉換成本地代碼也是一種防止反編譯的有效方法因為本地代碼往往難以被反編譯開發人員可以選擇將整個應用程序轉換成本地代碼也可以選擇關鍵模塊轉換如果僅僅轉換關鍵部分模塊Java程序在使用這些模塊時需要使用JNI技術進行調用
  
  當然在使用這種技術保護Java程序的同時也犧牲了Java的跨平台特性對於不同的平台我們需要維護不同版本的本地代碼這將加重軟件支持和維護的工作不過對於一些關鍵的模塊有時這種方案往往是必要的
  
  為了保證這些本地代碼不被修改和替代通常需要對這些代碼進行數字簽名在使用這些本地代碼之前往往需要對這些本地代碼進行認證確保這些代碼沒有被黑客更改如果簽名檢查通過則調用相關JNI方法這種保護方式示意圖見圖
  
  代碼混淆
  
   
  圖 轉換成本地代碼示意圖
  
  代碼混淆是對Class文件進行重新組織和處理使得處理後的代碼與處理前代碼完成相同的功能(語義)但是混淆後的代碼很難被反編譯即反編譯後得出的代碼是非常難懂晦澀的因此反編譯人員很難得出程序的真正語義從理論上來說黑客如果有足夠的時間被混淆的代碼仍然可能被破解甚至目前有些人正在研制反混淆的工具但是從實際情況來看由於混淆技術的多元化發展混淆理論的成熟經過混淆的Java代碼還是能夠很好地防止反編譯下面我們會詳細介紹混淆技術因為混淆是一種保護Java程序的重要技術是代碼混淆的示意圖
   
  圖 代碼混淆示意圖
  
  幾種技術的總結
  
  以上幾種技術都有不同的應用環境各自都有自己的弱點是相關特點的比較
  
  混淆技術介紹
  
  表 不同保護技術比較表
   
  到目前為止對於Java程序的保護混淆技術還是最基本的保護方法Java混淆工具也非常多包括商業的免費的開放源代碼的Sun公司也提供了自己的混淆工具它們大多都是對Class文件進行混淆處理也有少量工具首先對源代碼進行處理然後再對Class進行處理這樣加大了混淆處理的力度目前商業上比較成功的混淆工具包括JProof公司的stBarrier系列Eastridge公司的JShrink和的SourceGuard等主要的混淆技術按照混淆目標可以進行如下分類它們分別為符號混淆(Lexical Obfuscation)數據混淆(Data Obfuscation)控制混淆(Control Obfuscation)預防性混淆(Prevent Transformation)
  
  符號混淆
  
  在Class中存在許多與程序執行本身無關的信息例如方法名稱變量名稱這些符號的名稱往往帶有一定的含義例如某個方法名為getKeyLength()那麼這個方法很可能就是用來返回Key的長度符號混淆就是將這些信息打亂把這些信息變成無任何意義的表示例如將所有的變量從vairant_開始編號對於所有的方法從method_開始編號這將對反編譯帶來一定的困難對於私有函數局部變量通常可以改變它們的符號而不影響程序的運行但是對於一些接口名稱公有函數成員變量如果有其它外部模塊需要引用這些符號我們往往需要保留這些名稱否則外部模塊找不到這些名稱的方法和變量因此多數的混淆工具對於符號混淆都提供了豐富的選項讓用戶選擇是否如何進行符號混淆
  
  數據混淆
   
  圖 改變數據訪問
  
  數據混淆是對程序使用的數據進行混淆混淆的方法也有多種主要可以分為改變數據存儲及編碼(Store and Encode Transform)改變數據訪問(Access Transform)
  
  改變數據存儲和編碼可以打亂程序使用的數據存儲方式例如將一個有個成員的數組拆開為個變量並且打亂這些變量的名字將一個兩維數組轉化為一個一維數組等對於一些復雜的數據結構我們將打亂它的數據結構例如用多個類代替一個復雜的類等
  
  另外一種方式是改變數據訪問例如訪問數組的下標時我們可以進行一定的計算就是一個例子
  
  在實踐混淆處理中這兩種方法通常是綜合使用的在打亂數據存儲的同時也打亂數據訪問的方式經過對數據混淆程序的語義變得復雜了這樣增大了反編譯的難度
  
  控制混淆
  
  控制混淆就是對程序的控制流進行混淆使得程序的控制流更加難以反編譯通常控制流的改變需要增加一些額外的計算和控制流因此在性能上會給程序帶來一定的負面影響有時需要在程序的性能和混淆程度之間進行權衡控制混淆的技術最為復雜技巧也最多這些技術可以分為如下幾類
  
  增加混淆控制 通過增加額外的復雜的控制流可以將程序原來的語義隱藏起來例如對於按次序執行的兩個語句AB我們可以增加一個控制條件以決定B的執行通過這種方式加大反匯編的難度但是所有的干擾控制都不應該影響B的執行就給出三種方式為這個例子增加混淆控制
   
  圖 增加混淆控制的三種方式
  
  控制流重組 重組控制流也是重要的混淆方法例如程序調用一個方法在混淆後可以將該方法代碼嵌入到調用程序當中反過來
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19576.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.