防止反編譯的代碼
我們都知道JAVA是一種解析型語言,這就決定JAVA文件編譯後不是機器碼,而是一個位元組碼文件,也就是CLASS文件。而這樣的文件是存在規律的,經過反編譯工具是可以還原回來的。例如Decafe、FrontEnd,YingJAD和Jode等等軟體。下面是《Nokia中Short數組轉換演算法》
類中Main函數的ByteCode:0 ldc #162 invokestatic #185 astore_16 return其源代碼是:short [] pixels = parseImage("/ef1s.png");
我們通過反編譯工具是可以還原出以上源代碼的。而通過簡單的分析,我們也能自己寫出源代碼的。
第一行:ldc #16
ldc為虛擬機的指令,作用是:壓入常量池的項,形式如下ldc index這個index就是上面的16,也就是在常量池中的有效索引,當我們去看常量池的時候,我們就會找到index為16的值為String_info,裡面存了/ef1s.png.
所以這行的意思就是把/ef1s.pn作為一個String存在常量池中,其有效索引為16。
第二行:2 invokestatic #18
invokestatic為虛擬機指令,作用是:調用類(static)方法,形式如下
invokestatic indexbyte1 indexbyte2
其中indexbyte1和indexbyte2必須是在常量池中的有效索引,而是指向的類型必須有Methodref標記,對類名,方法名和方法的描述符的引用。
所以當我們看常量池中索引為18的地方,我們就會得到以下信息:
Class Name : cp_info#1
Name Type : cp_info#19
1 和19都是常量池中的有效索引,值就是右邊<中的值,再往下跟蹤我就不多說了,有興趣的朋友可以去JAVA虛擬機規范。
這里我簡單介紹一下parseImage(Ljava/lang/String;)[S 的意思。
這就是parseImage這個函數的運行,我們反過來看看parseImage的原型就明白了
short [] parseImage(String)
那麼Ljava/lang/String;就是說需要傳入一個String對象,而為什麼前面要有一個L呢,這是JAVA虛擬機用來表示這是一個Object。如果是基本類型,這里就不需要有L了。然後返回為short的一維數組,也就是對應的[S。是不是很有意思,S對應著Short類型,而「[」對應一維數組,那有些朋友要問了,兩維呢,那就「[[」,呵呵,是不是很有意思。
好了,調用了函數,返回的值要保存下來吧。那麼就是第三行要做的事情了。
2. C#怎樣防止反編譯
我使用的方法是利用加殼工具:virboxProtectorStandalone。直接進行加殼。高級混淆、虛擬化代碼、智能壓縮等加密策略。如果要授權控制,可使用許可版本的virboxProtector。
未經加殼保護的 ILspy 反編譯效果如下:
public int add(int a, int b){
return a + b;}public int div(int a, int b){
return a / b;}public int mul(int a, int b){
return a * b;}public int sub(int a, int b){
return a - b;}
解決方案:
深思自主研發了為 C# .net 語言做保護的外殼(Virbox Protector)。將C# .net 編譯成的執行程序(.exe),動態庫(.dll)直接拖入加殼工具即可完成保護操作,十分方便。並且在效果上已經完全看不到源碼中的邏輯。
加密後的效果
public int add(int a, int b){
return (int)dm.dynamic_method((object)this, System.Reflection.MethodBase.GetCurrentMethod(), 16416u, 21, 16384u, 32u, 31516u, 5).Invoke(this, new object[]
{
this,
a,
b
});}
public int div(int a, int b){
return (int)dm.dynamic_method((object)this, System.Reflection.MethodBase.GetCurrentMethod(), 16956u, 21, 16924u, 32u, 31516u, 2).Invoke(this, new object[]
{
this,
a,
b
});}
public int mul(int a, int b){
return (int)dm.dynamic_method((object)this, System.Reflection.MethodBase.GetCurrentMethod(), 16776u, 21, 16744u, 32u, 31516u, 3).Invoke(this, new object[]
{
this,
a,
b
});}
public int sub(int a, int b){
return (int)dm.dynamic_method((object)this, System.Reflection.MethodBase.GetCurrentMethod(), 16596u, 21, 16564u, 32u, 31516u, 4).Invoke(this, new object[]
{
this,
a,
b
});}
架構支持
IIS 服務架構的後台邏輯 DLL 文件
windows PC 應用程序 EXE 文件
windows PC 應用程序動態庫 DLL 文件
UG等第三方繪圖工具使用的 DLL 文件
Unity3d 編譯使用的 DLL 文件
3. 如何防止Unity3D代碼被反編譯
根本的解決辦法是:先對DLL加密,然後在Unity的源碼中載入程序DLL之前進行解密。
這就需要通過逆向工程獲得相應的Unity源碼或者是直接向Unity購買Source Code License。
4. 如何防止你的 jar 被反編譯
Java世界的防護盾:如何抵擋反編譯的侵襲
作為一門廣泛應用的語言,Java的解釋特性使其易受反編譯威脅。然而,通過巧妙的策略和工具,我們可以有效提高代碼的安全性。以下是幾種防範措施,它們各有其適用場景和潛在挑戰:
- 伺服器端隔離:將Java程序部署在伺服器端,限制直接訪問,如通過API介面,降低被破解的可能性。
- Class文件加密:通過自定義ClassLoader實現解密,保護核心代碼免受未經授權的訪問。但是,這需要在運行時進行解密,增加了復雜性和潛在的性能損失。
- 本地化代碼轉換:犧牲一定的跨平台性,將代碼轉換為本地機器代碼,降低反編譯的難度,但可能影響代碼的移植性。
- 代碼混淆藝術:包括符號混淆、數據混淆、控制混淆和預防性混淆,它們是基本保護手段。符號混淆混淆方法和變數名,數據混淆則處理數據的存儲和訪問方式,控制混淆擾亂程序邏輯,預防性混淆則針對特定反編譯器進行針對性設計。
- 符號混淆:通過工具如1stBarrier、JShrink和SourceGuard,將代碼中的標識符改頭換面,使反編譯者難以識別其原始含義,同時保留必要部分以保持功能。
- 數據混淆:增加數據處理的復雜性,如使用非標准編碼,使得反編譯後的代碼難以解讀數據結構。
- 控制混淆:混淆控制流,如引入額外計算,提升反編譯的難度,但可能影響程序性能。
- 預防性混淆:針對特定工具的策略,利用其破解過程中的弱點,提升防護層次。
讓我們以SCJP模擬考試軟體為例,它巧妙地運用了這些技術。核心題庫類被分解為獨立模塊,部分採用C++開發,如題庫訪問模塊,專門處理Windows下的安全介面。關鍵步驟如下:
- 介面初始化:生成隨機SessionKey,確保合法用戶通過認證並加密數據,如圖8所示。
- 數據訪問介面:經過認證後,對題庫進行加密訪問。只有特定模塊才能解密,甚至可以採用雙向認證以增強安全性。
盡管這些方法增加了代碼的復雜性和保護性,但沒有絕對的安全。隨著技術的進步,反編譯技術也在不斷演進,因此持續更新和優化混淆策略至關重要。記住,防護是一場馬拉松,而非短跑。
5. 怎麼防止Java開發出來的程序被別人反編譯
防止Java開發出來的程序被別人反編譯有很多種方法,下面給你介紹幾種:
1、隔離Java程序
最簡單的方法就是讓用戶不能夠訪問到Java Class程序,這種方法是最根本的方法,具體實現有多種方式。例如,開發人員可以將關鍵的Java Class放在伺服器端,客戶端通過訪問伺服器的相關介面來獲得服務,而不是直接訪問Class文件。這樣黑客就沒有辦法反編譯Class文件。目前,通過介面提供服務的標准和協議也越來越多,例如 HTTP、Web Service、RPC等。但是有很多應用都不適合這種保護方式,例如對於單機運行的程序就無法隔離Java程序。
2、對Class文件進行加密
為了防止Class文件被直接反編譯,許多開發人員將一些關鍵的Class文件進行加密,例如對注冊碼、序列號管理相關的類等。在使用這些被加密的類之前,程序首先需要對這些類進行解密,而後再將這些類裝載到JVM當中。這些類的解密可以由硬體完成,也可以使用軟體完成。
3、轉換成本地代碼
將程序轉換成本地代碼也是一種防止反編譯的有效方法。因為本地代碼往往難以被反編譯。開發人員可以選擇將整個應用程序轉換成本地代碼,也可以選擇關鍵模塊轉換。如果僅僅轉換關鍵部分模塊,Java程序在使用這些模塊時,需要使用JNI技術進行調用。
4、代碼混淆
代碼混淆是對Class文件進行重新組織和處理,使得處理後的代碼與處理前代碼完成相同的功能(語義)。但是混淆後的代碼很難被反編譯,即反編譯後得出的代碼是非常難懂、晦澀的,因此反編譯人員很難得出程序的真正語義。從理論上來說,黑客如果有足夠的時間,被混淆的代碼仍然可能被破解,甚至目前有些人正在研製反混淆的工具。但是從實際情況來看,由於混淆技術的多元化發展,混淆理論的成熟,經過混淆的Java代碼還是能夠很好地防止反編譯。
不同保護技術比較希望能給大家帶來參考: