Sandboxie 註冊演演算法分析
【文章作者】: uuk
【軟體名稱】: Sandboxie 3.49.06
【下載地址】: http://www.sandboxie.com/index.php
【加殼方式】: 無
【保護方式】: 序號
【編寫語言】: Microsoft Visual C++ 7.0
【使用工具】: PEID,IDA Pro with Hex-Rays plugin,Syser
【操作平臺】: XP SP3,
【軟體介紹】: Sandboxie 允許你在沙盤環境中運行流覽器或其他程式,因此運行所產生的變化可以隨後刪除。可用來消除上網、運行程式的痕跡,也可用來還原我的最愛、主頁、註冊表等。即 使在沙盤進程中下載的檔,也會隨著沙盤的清空而刪除。此軟體在系統託盤中運行,如果想啟動一個沙盤進程,請通過託盤圖示(而不要用原方式)啟動流覽器或 相應程式。
【作者聲明】: 菜鳥學習演算法,失誤之處敬請諸位大俠賜教!
Sandboxie自3.48版本開始採用新的啟動方式——聯網啟動,但也為不能上網的電腦提供了離線啟動方式。能離線啟動說明註冊的驗證是在本地進行的,方便我們進行演演算法分析。官方離線啟動網址:http://www.sandboxie.com/index.php?OfflineActivation。在之前我已經通過官方的離線啟動網頁得到一個離線啟動碼Key(RF0UD7XH6KREU2TX……E4YJ1PT8RW8PO)。
通過跟蹤啟動過程,啟動管理程式License.exe調用SbieDll.dll的SbieApi_ActivateLicense,SbieApi_ActivateLicense通過IRP_MJ_DEVICE_CONTROL與驅動SbieDrv.sys通信,最終驗證過程在驅動SbieDrv.sys裡。通過IoControlCode定位到函數sub_20744(重命名為ActivateLicense),查看ActivateLicense的交叉引用,發現在驅動載入過程中也被調用了,因此可以確認驗證過程就是sub_20744。ActivateLicense反彙編代碼如下:
.text:00020744 push ebp
.text:00020745 mov ebp, esp
.text:00020747 sub esp, 28h
.text:0002074A push esi
.text:0002074B push 24h ; 36 = 24h
.text:0002074D push [ebp+pKey] ; ActivationKey(UNICODE)
.text:00020750 xor esi, esi
.text:00020752 push pPagedPool_tzuk ; PagedPool("tzuk")
.text:00020758 mov [ebp+var_18], esi
.text:0002075B mov [ebp+var_14], esi
.text:0002075E call sub_1C1C8 ; mpz_set_str (mpz_t rop, char *str, int base)
.text:0002075E ; return eax = rop
仔細分析sub_1C1C8,會發現它是將字串Key當作36進制數,轉換成16進制的大數(有點像GMP庫裡的mpz_set_str(Key, ActivationKey, 36))。由於是大數操作,所以sub_1C1C8裡有大量的記憶體操作,剛開始分析時就讓我暈頭轉向,同時又是大數運算,比較複雜。我花了不少時間才搞明白它在做什麼,也知道程式中是如何存儲大數的。大數結構如下所示:
struct BigNum{unsigned int size; unsigned int num[size];}
大數在記憶體中按從低到高的位址存儲從低到高的數。知道了大數的結構,以及記憶體申請和釋放操作,後面的分析就會輕鬆許多。
.text:00020763 cmp eax, esi ; 大數 Key = eax
.text:00020765 mov [ebp+pKey], eax
.text:00020768 jnz short loc_2077E
.text:0002077E ; ---------------------------------------------------------------------------
.text:0002077E
.text:0002077E loc_2077E: ; CODE XREF: ActivateLicense+24 j
.text:0002077E push ebx
.text:0002077F push edi
.text:00020780 push offset MOD
.text:00020785 push offset EXP
.text:0002078A push eax
.text:0002078B push pPagedPool_tzuk
.text:00020791 call sub_1C09E ; mpz_powm (mpz_t rop, mpz_t base, mpz_t exp, mpz_t mod)
.text:00020791 ; return eax = rop
大致分析sub_1C09E,排除記憶體操作後,發現裡面有一些除法運算,初步確定是在做大數除法,但是在自己用大數計算器驗證時發現結果總是不對,於是以為在sub_1C09E裡有其他小動作。花了好幾個晚上,仔仔細細的研究了裡面不確定的CALL,以及運算過程,最後確定sub_1C09E裡面做的就是大數除法和求模運算。既然是除法,那為什麼測試時結果不對呢?我又去分析了下測試過程,發現我寫的一個字串反轉程式少做一次對換,導致中間的兩個字元沒被反轉(大數在記憶體裡是從小到大存儲,而計算器中是從大到小,所以要反轉)。這樣浪費了幾天時間,但也讓我明白了大數除法的演算法。確定了sub_1C09E裡面的大數運算過程,寫出數學表達示,化簡後發現是類似mpz_powm(Reg, Key, EXP, MOD)的函數。在sub_1C09E之後,註冊資訊就以明碼放在記憶體中,後面就是一些資料的校驗了。想要寫出註冊機就得能反求Reg = Key^EXP mod MOD,我求不出來,於是到論壇上求助http://bbs.pediy.com/showthread.php?t=123926,lingyu大俠告知這是RSA2048加密演算法,在這要感謝大俠們的指點!
下麵是資料校驗過程:
.text:00020796 mov ebx, eax ; ebx = Reg = eax
.text:00020798 mov eax, [ebx]
.text:0002079A cmp eax, 4 ; Reg 長度size大於4
.text:0002079D push 12h
.text:0002079F pop esi
.text:000207A0 jbe loc_20A39
.text:000207A6 mov cl, [ebx+4]
.text:000207A9 and cl, 0Fh
.text:000207AC cmp cl, 1 ; Reg 最低位為1
.text:000207AF push 13h
.text:000207B1 pop esi
.text:000207B2 jnz loc_20A39
.text:000207B8 push 14h
.text:000207BA pop esi
.text:000207BB lea eax, ds:0FFFFFFF4h[eax*4] ; size*4-0Ch
.text:000207C2 push eax
.text:000207C3 lea edi, [ebx+10h]
.text:000207C6 push edi
.text:000207C7 call sub_1B4B8 ; CheckSum 資料校驗
sub_1B4B8是對註冊資訊Reg進行校驗,返回兩個校驗值,裡面有兩個CALL(sub_1B392、sub_1B418),看Hex-Rays plugin生成的C代碼,很容易就能自己寫出個checksum生成函數,代碼在附件裡有。也不知道是有現成的函數,還是作者杜撰的。
.text:000207CC cmp eax, [ebx+8] ; 比較校驗值1與[ebx+8]
.text:000207CF jnz loc_20A39
.text:000207D5 cmp edx, [ebx+0Ch] ; 比較校驗值2與[ebx+0Ch]
.text:000207D8 jnz loc_20A39
.text:000207DE cmp dword ptr [edi], 80000001h ; [ebx+10h]
.text:000207E4 push 21h
.text:000207E6 pop esi
.text:000207E7 jnz loc_20A39
.text:000207ED cmp dword ptr [ebx+14h], 1 ; [ebx+14h] == 1
.text:000207F1 push 22h
.text:000207F3 pop esi
.text:000207F4 jnz loc_20A39
再後面還有到期時間與當前系統時間的比較,軟體版本的比較,系統碼的比較,在IDA裡很容易就能看得懂,這裡就不詳細說明瞭。註冊資訊的結構如下所示:
關於註冊機:RSA2048是很難反求的,只能通過替換公開金鑰的方法進行破解(看雪論壇精華裡看到的)。由於是替換驅動SbieDrv.sys裡的公開金鑰,替換後還得修正檔的CheckSum,不然驅動不能載入。附件裡是我寫的一個簡單的Patch和Keygen。
同時有個疑問:SbieDrv.sys打過補丁後,其數位簽章就變成無效了,既然RSA可以通過替換公開金鑰進行攻擊,那檔的數位簽章可不可以偽造?