起因 最近在對接一個第三方平臺。該平臺只提供了Java版本的SDK,C#版本的還處於敬請期待狀態。由於C#可以復用絕大部分代碼,便考慮找一個Java到C#的轉換器,在試用了幾個軟體之後,發現還是Java to C# Converter(下文簡稱Converter)好用一點。然而基本版功能受限(文件夾 ...
起因
最近在對接一個第三方平臺。該平臺只提供了Java版本的SDK,C#版本的還處於敬請期待狀態。由於C#可以復用絕大部分代碼,便考慮找一個Java到C#的轉換器,在試用了幾個軟體之後,發現還是Java to C# Converter(下文簡稱Converter)好用一點。然而基本版功能受限(文件夾不能超過1000行代碼,代碼片段不能超過100行),高級版的則要$169。
在經歷過自己寫小程式轉換Java、手寫代碼、利用Converter分批次轉換、查找替換等方式完成C#版本之後。終於按捺不住心中的好奇心,研究了下軟體的破解。
希望
首先看看這個軟體是不是C#寫的,將文件拖入ILSpy,一看之下,果然有驚喜。
嗯,驚喜就是雖然該軟體是利用C#+WinForm寫成的,但是很明顯的經過了混淆。嚇得我趕忙利用ILSpy的Save Code功能將其保存為工程文件。看能不能重新編譯成可執行程式。
失望
首先試試雙擊工程文件,VS沒反應。換用dotPeek依然如此。
然後新建工程,將項目添加到工程中,一大堆錯誤,無外乎是變數名不正確。換用dotPeek依然如此。如果時間充足的話,可以細心研讀代碼,修複錯誤,重新編譯。一來錯誤太多、二來我也不想花太多時間在讀代碼上面、三來我的目的不在這上面。於是果斷放棄該方式。
新希望
思路
我們知道,C#程式是編譯成IL的,恰好我知道Reflexil可以直接編輯IL。上Reflexil官網一看,現在也支持ILSpy(以前我以為只支持Reflector),那就直接在ILSpy中改寫IL。
查找編輯位置
要編輯IL的話,關鍵是要找對地方。軟體未註冊的話,好多時候都會彈出一個對話框,Converter也與此類似。
直接在VS中查找相應的字元串,如最開始的The Free Edtion of。經過簡單分析後不難看出_g22.cs正是我們要找的地方。
internal static bool _g41(List<string> Copyright_Tangible_Software_Solutions_p0) { if (_g22._g24 == _g3.FreeEdition) { if (_g22._m21 != 100) { Copyright_Tangible_Software_Solutions_g810._g844(Copyright_Tangible_Software_Solutions_g810._g843); return false; } if (Copyright_Tangible_Software_Solutions_p0 == null) { return true; } int num = 0; for (int i = 0; i < Copyright_Tangible_Software_Solutions_p0.Count; i++) { if (Copyright_Tangible_Software_Solutions_p0[i].Trim().Length > 0 && !Copyright_Tangible_Software_Solutions_p0[i].TrimStart(new char[0])._g1079("//")) { num++; if (num > _g22._m21) { new _g376(string.Concat(new string[] { "The Free Edition of ", Application.ProductName, " doesn't allow conversion of snippets with more than ", _g22._m21.ToString(), " lines at a time." })); return false; } } } } return true; }
下麵還有兩個函數,_g42和_g43形式與此類似,_g42應該是文件夾的許可,_g43不知道是做什麼的。從函數的代碼上看,感覺直接將返回值改成true就好了。不管那麼多,先來試試改寫_g41。
準備工作
在網站上下了reflexil.for.ILSpy.2.0.AIO(我愣了下才反應過來AIO是All In One的意思),解壓後將裡面的DLL複製到ILSpy目錄下。打開ILSpy(如果ILSpy複製前是打開,則需重啟),在View中點擊Reflexil v2.0,然後在ILSpy中打開Converter的可執行文件,找到_g22類中的_g41函數。如下圖所示:
Instructions標簽頁就是進行IL編輯操作的地方。雖然在Reflexil中可以直接編輯源碼:在Instructions標簽頁的表格中選擇Replace all with code,在彈出的視窗中編輯源碼。但是在Converter中預設的代碼方法體無任何內容,而且Complie也會訪問錯誤(雖然並沒有錯誤)。於是果斷放棄這種方式。
編輯IL
編輯IL還有一個問題就是我們要將IL改變成什麼樣。在本例中就是return true對應的IL是什麼 。這個問題說難也難,說簡單也簡單。只要我們在VS中編寫一段同樣的代碼,生成後在ILSpy中以IL方式查看即可。
C#形式的代碼
IL形式的代碼
接下來就是將Instructions標簽頁表格中的IL改為與上圖的IL一樣。整個過程很簡單,刪除、添加、修改,只要保持指令與目標一致。值得一提的是,總共6條指令(nop將就留下吧),只有第4條有操作數,可將其最後添加。因為是跳轉語句,需要在Operand type中選擇Instruction reference,然後在Operand選擇要跳轉的指令位置。
大功告成
在ILSpy中Converter可執行文件上單擊右鍵,在彈出的右鍵菜單中選擇Save As,保存好文件(可以對Converter原文件作好備份後直接覆蓋)。驗證後發現針對代碼片段的限制確實失效了。
如果對_g42和_g43也如法炮製,就會發現針對文件夾的限制也會失效。
結語
我是抱著研究學習的態度來嘗試破解的,破解之後也沒有作其他用途。本著跟大家溝通交流的初衷將這個過程寫下來,請各位多多賜教,同時,也希望大家多支持正版。
然而我辛辛苦苦作出的C#版本最終一點用都沒派上,這真是一個溫暖人心的結局。