準備的工具:
.NET Reactor破解他,當然要先安裝先下載地址:
.NET Generic Unpacker和SNSRemover,用來脫掉Reactor本身的殼和去去掉強名稱
Reflector,這個不用說了吧…
十六進制編輯器,主要有查找、替換和保存功能就OK了。
我們安裝完Reactor,發現他不是.NET程序,直接用Reflector不能反編譯他,這時候我們就要用.NET Generic Unpacker,將Reactor的殼脫掉如圖1。
(圖1 對Reactor進行脫殼)
每次脫出來的數量都不壹定相同的。好了,我們用Reflector打開他看看,如圖2
(圖2 用Reflector對Reactor進行反編譯)
這時候,我們發現混淆後的類名竟然是亂碼,這個沒所謂,ilasm是支持亂碼的,是不是我們也可以用ildasm進行反編譯,然後修改他的代碼,然後用ilasm將他重新編譯呢?理論上是可以,但實際上由於反編譯出來的資源文件的文件名是亂碼,ilasm沒辦法找到那些文件,編譯會失敗。那怎麽辦,那就直接修改原程序的了。
首先用SNSRemover去掉他的強名稱先。
(圖3 用SNSRemover去掉Reactor的強名稱)
現在妳是不是有這個疑問,本來脫出來的程序就已經不能運行的了,現在去掉了強名稱後,反而運行起來會提示出錯。不用怕,試壹下用原版的Reactor對現在去掉強名稱後的Reactor進行壹次加密。將加密出來的程序放在Reactor目錄下運行。
(圖4 重新加密後運行時發生的錯誤)
哈哈,看到是什麽錯誤沒有?現在這個已經不是驗證強名稱錯誤了,是壹個運算錯誤,是某數除於0時時發生的錯誤。再看看他發生錯誤是在那裏,我們通過Reflector來找出–v. –c..cctor()這個方法,由於Reactor他本身是經過混淆的,已經不能用C#來反編譯,新版也做出了新的混淆,就算去掉了
L_0000: br L_0007
L_0005: pop
L_0006: ldc.i4.0
這三段代碼,也不能用C#來反編譯,我們只能用IL了。
(圖5 用Reflector找出發生異常的方法)
熟悉IL的就會知道,除的命令是div,那我們就在這裏裏面搜索div,發現這段代碼:
L_004f: ldc.i4 0x10
L_0054: stloc.s num
L_0056: ldloc num
L_005a: ldloc num
L_005e: sub
L_005f: conv.u1
L_0060: stloc.s num
L_0062: ldloc num
L_0066: ldloc num
L_006a: div
L_006b: conv.u1
L_006c: stloc.s num
看到這裏應該知道了吧,將他換成C#的代碼應該是
num = 0x10;
num = num - num;
num = num / num;
知道錯誤的原因了,那我們將這個div改掉就行了,但有壹個問題,為什麽原版的程序就不會發生這個問題?原因很簡單,妳搜索壹下GetPublicKeyToken(),妳就會發現上面那段代碼是他驗證強名稱失敗時才會執行的,因為我們去掉了強名稱,所以肯定會執行那段代碼的。
我們知道了出錯的原因了,但我們怎樣改呢?方法很簡單,因為Reflector他有提示該代碼對應的十六進制,
(圖6 找出該代碼對應的十六進制)
這時候我們是不是該想壹下,其他的方法裏是不是也同樣也有這樣的驗證。好,我們隨便找幾個方法,發現有些方法是有,有些是沒有。但有些的IL代碼不壹樣,有點區別如:
L_003b: ldc.i4 0x24
L_0040: stloc.s num
L_0042: ldloc.s num
L_0044: ldloc.s num
L_0046: sub
L_0047: conv.u1
L_0048: stloc.s num
L_004a: ldloc.s num
L_004c: ldloc.s num
L_004e: div
L_004f: conv.u1
L_0050: stloc.s num
但運行出來的效果是壹樣的,只不過是他對應的十六進制不壹樣而已
(圖7 ldloc.s對應的十六進制)
好了,如果我們壹個個方法都要去看,那花的時間太多了,不如我們先處理掉壹部分先,如果再發現那裏的錯誤,我們就去那裏找出來。
我們很容易通過Reflector可以知道這兩段代碼對應的十六進制應該是
FE0C0000FE0C000059D21300FE0C0000FE0C00005BD213和1100110059D21300110011005BD213
從Reflector那裏我們可以知道,sub對應是59,div對應是5B,那我們將5B換成59那程序就不會發生異常了,用十六進制編輯器,替換FE0C0000FE0C000059D21300FE0C0000FE0C00005BD213為FE0C0000FE0C000059D21300FE0C0000FE0C000059D213,替換1100110059D21300110011005BD213為1100110059D213001100110059D213
(圖8 替換代碼)
現在我們又用原版的Reactor重新加密壹次我們剛處理完的文件。發現現在可以正常運行了。
我們已經可以正常運行我們脫殼後的程序了,現在開始我們就要將他變成正式版。
用Reflector打開我們剛處理完的文件,使用Reflector自帶的功能,跳到程序的入口點
(圖9 找到入口點)
分析壹下程序的,不難的可以找到
L_0662: call bool –v.–c::‘2()
這段代碼就是驗證的代碼了,但如果在這裏直接修改,難度會相當大,不如我們修改‘2()的返回值,只要他永遠返回true,那就達到我們的目的了。
(圖10 來到‘2())
我們不難的找到了L_0000: br L_0007對應的地址是0x17cd28,將原來的3802改成172A
(圖10 修改3802為172A)
保存後,我們在次用原版的Reactor對剛處理完的程序進行加密,將加密後的程序放在Reactor目錄下運行。看看,現在是FULL VERSION了,但我們現在測試壹下他,會發現出現這樣的異常
(圖11 修改完,運行出現的異常)
看壹下他的異常,還是System.DivideByZeroException,也就是說還有壹部分的強名稱驗證的代碼還沒有修改,只要重復上面的操作,找出他的十六進制,將5B換成59就行了。
該版本我已經發布了他的破解版,3.3.8.0也已經發布了,3.3.8.0的破解會比這個更難,有興趣的朋友可以來研究壹下,可以拿3.3.8.9版來試壹下,這個跟3.3.8.0是壹樣的破解。..