SRS Audio Sandbox破解紀實


  最近挺忙的,本來需要各種為前路做准備,無奈自己天生屬於低血壓型的人,偏偏就是提不起勁兒來干正事兒,卻把大好的一天光陰全交代到SRS的分析工作上了。雖然說這多少算不務正業,不過由於本人有着嚴重的軟件新版本強迫症,故這算是給自己的一個開脫理由吧。

  這款軟件的破解工作展開比較容易,沒有加殼,直接上工具分析之。首先請出OllyDBG來,通過查找字符串引用和查找API MessageBox引用的老法子,很容易就定位了大概的關鍵代碼位置。

  找到關鍵位置后,順手又記錄了一下函數調用棧,然后打開了神器IDA。用IDA載入后,跳轉到之前找到的關鍵代碼RVA處,着手分析。說起來,我自己喜歡將動態和靜態調試方法結合起來用,不如果不願意太費神分析匯編代碼,有時候直接看運行時結果便是最直觀和省時的。載入后發覺之前判斷的關鍵點實際上是CWinApp::ShowAppMessageBox函數,繼續沿着剛才記錄的函數運行時調用棧往上找,依次順藤摸瓜:AfxMessageBox--->Sub44D240,這才到了SRS程序的代碼領空,於是正是着手分析。(IDA這個靜態分析功能實在是強大,它可以根據二進制代碼特征判斷出其是否是庫函數代碼。這大大節省了我的時間,應為對這類代碼我只需要看SDK文檔就行了,而不需要去分析其實際的代碼行為)

  進一步根據線索判斷(Sub44D240里包含了SendMessage、AfxMessageBox、GetWindowText等函數,足以說明該函數的關鍵作用),我鎖定在了Sub44D240函數的Sub4430F0調用上,繼續追蹤到Sub442FF0上,繼而是Sub44B9E0過程,最終到了Sub44BC30過程上。在該過程中,我同時追蹤到了用戶輸入的ProductID以及Serial Number等信息,這進一步是我確認了我的判斷。

  該過程具體代碼如下:

Sub44BC30代碼
  1  .text:0044BC30
  2  .text:0044BC30 ; =============== S U B R O U T I N E =======================================
  3  .text:0044BC30
  4  .text:0044BC30 ; Attributes: bp-based frame
  5  .text:0044BC30
  6  .text:0044BC30 check_PID_SN    proc near               ; CODE XREF: realCheckSN+182p
  7  .text:0044BC30
  8  .text:0044BC30 productId_segs_temp= dword ptr -14h
  9  .text:0044BC30 new_ProdectID   = dword ptr -10h
 10  .text:0044BC30 sn_lowerDWord   = dword ptr -4
 11  .text:0044BC30 SN              = dword ptr  8
 12  .text:0044BC30
 13  .text:0044BC30                 push    ebp
 14  .text:0044BC31                 mov     ebp, esp
 15  .text:0044BC33                 and     esp, 0FFFFFFF8h
 16  .text:0044BC36                 sub     esp, 14h
 17  .text:0044BC39                 push    ebx
 18  .text:0044BC3A                 push    esi
 19  .text:0044BC3B                 push    edi
 20  .text:0044BC3C                 push    14h             ; unsigned int
 21  .text:0044BC3E                 mov     ebx, eax        ; ebx指向ProductID首位置
 22  .text:0044BC40                 call    j_??2@YAPAXI@Z  ; operator new(uint)
 23  .text:0044BC45                 mov     esi, eax
 24  .text:0044BC47                 lea     eax, [esi+6]
 25  .text:0044BC4A                 push    eax
 26  .text:0044BC4B                 mov     eax, [ebp+SN]
 27  .text:0044BC4E                 lea     ecx, [esi+4]
 28  .text:0044BC51                 push    ecx
 29  .text:0044BC52                 lea     edx, [esi+2]
 30  .text:0044BC55                 push    edx
 31  .text:0044BC56                 push    esi             ; 新申請的14h的空間
 32  .text:0044BC57                 push    offset a4x4x4x4x ; "%4x-%4x-%4x-%4x"
 33  .text:0044BC5C                 push    eax             ; SN首地址
 34  .text:0044BC5D                 call    String2Integer  ; 將字符串SN轉換為數組,比如
 35  .text:0044BC5D                                         ; “E6E9-24CB-2968-09BC”變為
 36  .text:0044BC5D                                         ; E9 E6 ...
 37  .text:0044BC62                 mov     ecx, [esi+4]    ; ECX為后半部分SN
 38  .text:0044BC65                 mov     edi, [esi]      ; EDI為前半部分SN
 39  .text:0044BC67                 push    esi             ; void *
 40  .text:0044BC68                 mov     [esp+40h+sn_lowerDWord], ecx
 41  .text:0044BC6C                 call    j__free
 42  .text:0044BC71                 lea     edx, [esp+40h+productId_segs_temp]
 43  .text:0044BC75                 push    edx
 44  .text:0044BC76                 push    offset a4x      ; "%4x"
 45  .text:0044BC7B                 push    ebx
 46  .text:0044BC7C                 call    String2Integer  ; 將ProductID第一段轉換為Word
 47  .text:0044BC81                 mov     esi, [esp+4Ch+productId_segs_temp] ; esi儲存productId_1
 48  .text:0044BC85                 lea     eax, [esp+4Ch+productId_segs_temp]
 49  .text:0044BC89                 push    eax
 50  .text:0044BC8A                 lea     ecx, [ebx+0Ah]
 51  .text:0044BC8D                 push    offset asc_48C804 ; "%x"
 52  .text:0044BC92                 push    ecx
 53  .text:0044BC93                 call    String2Integer
 54  .text:0044BC98                 mov     edx, [esp+58h+productId_segs_temp] ; EDX儲存ProductId_2
 55  .text:0044BC9C                 add     esp, 38h
 56  .text:0044BC9F                 xor     eax, eax
 57  .text:0044BCA1                 push    eax
 58  .text:0044BCA2                 push    esi
 59  .text:0044BCA3                 push    eax
 60  .text:0044BCA4                 push    edx
 61  .text:0044BCA5                 call    __allmul
 62  .text:0044BCAA                 mov     esi, eax        ; product_1*product_2乘積的低word放入esi
 63  .text:0044BCAC                 lea     eax, [esp+20h+productId_segs_temp]
 64  .text:0044BCB0                 push    eax
 65  .text:0044BCB1                 lea     ecx, [ebx+14h]
 66  .text:0044BCB4                 push    offset asc_48C804 ; "%x"
 67  .text:0044BCB9                 push    ecx
 68  .text:0044BCBA                 mov     [esp+2Ch+new_ProdectID+4], edx
 69  .text:0044BCBE                 call    String2Integer
 70  .text:0044BCC3                 mov     edx, [esp+2Ch+new_ProdectID+4]
 71  .text:0044BCC7                 mov     eax, [esp+2Ch+productId_segs_temp] ; eax保存productId_3
 72  .text:0044BCCB                 add     esp, 0Ch
 73  .text:0044BCCE                 push    edx
 74  .text:0044BCCF                 push    esi
 75  .text:0044BCD0                 push    0
 76  .text:0044BCD2                 push    eax
 77  .text:0044BCD3                 call    __allmul
 78  .text:0044BCD8                 lea     ecx, [esp+20h+productId_segs_temp]
 79  .text:0044BCDC                 push    ecx
 80  .text:0044BCDD                 push    offset asc_48C804 ; "%x"
 81  .text:0044BCE2                 add     ebx, 1Eh
 82  .text:0044BCE5                 push    ebx
 83  .text:0044BCE6                 mov     esi, eax
 84  .text:0044BCE8                 mov     [esp+2Ch+new_ProdectID+4], edx
 85  .text:0044BCEC                 call    String2Integer
 86  .text:0044BCF1                 mov     edx, [esp+2Ch+new_ProdectID+4]
 87  .text:0044BCF5                 mov     eax, [esp+2Ch+productId_segs_temp]
 88  .text:0044BCF9                 add     esp, 0Ch
 89  .text:0044BCFC                 push    edx
 90  .text:0044BCFD                 push    esi
 91  .text:0044BCFE                 push    0
 92  .text:0044BD00                 push    eax
 93  .text:0044BD01                 call    __allmul        ; 結果edx高位,eax低位
 94  .text:0044BD06                 mov     esi, edx
 95  .text:0044BD08                 shr     esi, 10h
 96  .text:0044BD0B                 mov     [esp+20h+new_ProdectID], eax
 97  .text:0044BD0F                 mov     [esp+20h+new_ProdectID+4], edx
 98  .text:0044BD13                 xor     ebx, ebx
 99  .text:0044BD15                 mov     cl, 10h
100  .text:0044BD17                 call    __allshr        ; {edx,eax}==new_prodectID >> 10h
101  .text:0044BD1C                 mov     ecx, [esp+20h+new_ProdectID+4]
102  .text:0044BD20                 xor     edx, edx
103  .text:0044BD22                 push    1
104  .text:0044BD24                 and     eax, 0FFFF0000h
105  .text:0044BD29                 push    edx
106  .text:0044BD2A                 add     esi, eax
107  .text:0044BD2C                 adc     ebx, edx
108  .text:0044BD2E                 mov     edx, [esp+28h+new_ProdectID]
109  .text:0044BD32                 push    ecx
110  .text:0044BD33                 push    edx
111  .text:0044BD34                 call    __allmul        ; eax=0, edx為new_productID的低位
112  .text:0044BD39                 push    0
113  .text:0044BD3B                 add     esi, eax
114  .text:0044BD3D                 push    8475h
115  .text:0044BD42                 adc     ebx, edx
116  .text:0044BD44                 push    ebx
117  .text:0044BD45                 push    esi
118  .text:0044BD46                 call    __alldiv        ; {edx,eax} == {edx,esi} / 0x8475
119  .text:0044BD4B                 push    0
120  .text:0044BD4D                 push    0AE6000h
121  .text:0044BD52                 push    edx
122  .text:0044BD53                 push    eax
123  .text:0044BD54                 call    __allmul
124  .text:0044BD59                 add     eax, 91F2884Dh
125  .text:0044BD5E                 adc     edx, 2DCh
126  .text:0044BD64                 mov     cl, 0Ah
127  .text:0044BD66                 call    __allshr
128  .text:0044BD6B                 push    0
129  .text:0044BD6D                 push    2046h
130  .text:0044BD72                 push    edx
131  .text:0044BD73                 push    eax
132  .text:0044BD74                 call    __allmul
133  .text:0044BD79                 mov     ecx, 0FFFFFFFEh
134  .text:0044BD7E                 sub     ecx, eax
135  .text:0044BD80                 mov     eax, 0FFFFFFFFh
136  .text:0044BD85                 sbb     eax, edx
137  .text:0044BD87                 mov     edx, [esp+20h+sn_lowerDWord]
138  .text:0044BD8B                 shld    edx, edi, 1
139  .text:0044BD8F                 add     edi, edi
140  .text:0044BD91                 cmp     edi, ecx
141  .text:0044BD93                 jnz     short loc_44BDA5
142  .text:0044BD95                 cmp     edx, eax
143  .text:0044BD97                 jnz     short loc_44BDA5
144  .text:0044BD99                 mov     eax, 1
145  .text:0044BD9E                 pop     edi
146  .text:0044BD9F                 pop     esi
147  .text:0044BDA0                 pop     ebx
148  .text:0044BDA1                 mov     esp, ebp
149  .text:0044BDA3                 pop     ebp
150  .text:0044BDA4                 retn
151  .text:0044BDA5 ; ---------------------------------------------------------------------------
152  .text:0044BDA5
153  .text:0044BDA5 loc_44BDA5:                             ; CODE XREF: check_PID_SN+163j
154  .text:0044BDA5                                         ; check_PID_SN+167j
155  .text:0044BDA5                 pop     edi
156  .text:0044BDA6                 pop     esi
157  .text:0044BDA7                 xor     eax, eax
158  .text:0044BDA9                 pop     ebx
159  .text:0044BDAA                 mov     esp, ebp
160  .text:0044BDAC                 pop     ebp
161  .text:0044BDAD                 retn
162  .text:0044BDAD check_PID_SN    endp

 

基本思路

  通過分析,我了解到,其算法大概思路如下:首先,注冊流程有效輸入為Serial Number和Product ID,Registration No實際上沒有參與注冊的驗證計算過程。SRS通過系統各種信息生成Product ID,然后用戶需要提供與Product ID匹配的Serial Number方能注冊。當然,Serial Number是需要你拿美刀換的。

  簡而言之,SRS將Product ID作fp變換,得到一個64bit長的整數,並將用戶輸入的序列號做fs變換同樣得到一個64bit長整數。為了使注冊成功,需要滿足:

fp(gen()) = fs(SerialNumber) 成立      (1)

  這其中,gen()的算法我們不需要管,因為其結果在界面Product ID框中已經顯示了。我們需要找到fp和fs的實現算法,並順利推出fs-1的實現。從而:

 SerialNumber = fs-1( fp(ProductID) )   (2)

Product ID變換算法描述

  我們首先描述fp的實現。fp基本上是由我不知道原理的各種數值變換組成,為了精確表述,我直接用C語言描述:

Product ID變換函數描述
 1 __int64 getProductID(char* id){
 2     __int64 temp = 1;
 3     DWORD elem;
 4 
 5     for(int i = 0; i < 4; i++){
 6         sscanf(id + (i * 5), "%x", &elem);
 7         temp *= elem;
 8     }
 9 
10     //高地位變換
11     DWORD lowerDWord = temp; 
12     DWORD upperDWord = temp >> 0x20;
13     WORD lower = upperDWord;
14     WORD upper = upperDWord >> 0x10;
15     upperDWord = lower;
16     upperDWord <<= 0x10;
17     upperDWord |= upper;
18     
19     temp = lowerDWord;
20     temp <<= 0x20;
21     temp |= upperDWord;
22     
23 
24     temp /= 0x8475;
25     temp *= 0xAE6000;
26     temp += 0x2DC91F2884D;
27     temp >>= 0xA;
28     temp *= 0x2046;
29     temp = 0xfffffffffffffffe - temp;
30 
31     return temp;
32 }

 

Serial Number變換算法描述  

  接下來描述fs函數的實現。我們稱變換后的Product ID為TransPID,並且LowerDW和HighDW表示一個64bit整數的低雙字和高雙字,shld表示對應匯編指令的函數,TransSerialNumberHighDW和TransSerialNumberLowDW分別表示變換后的序列號高雙字和低雙字。則有:

  TransSerialNumberHighDW(SerialNumber) = shld(UpperDW(SerialNumber), LowerDW(SerialNumber), 1);   (3)

  TransSerialNumberLowDW(SerialNumber) = LowerDW(SerialNumber) + LowerDW(SerialNumber);      (4)

  fs(SerialNumber) =   TransSerialNumberHighDW<< 32 | TransSerialNumberLowDW;            (5)

 

Serial Number逆向變換算法描述

  了解了fs的實現,我們接下來需要着手研究實現fs-1的思路。由於fs高雙字和低雙字分別由不同的方式變換的(3)、(4),所以我們需要分別求出SerialNumber的高低雙字。得到Serial Number的低雙字很簡單,由(4)可知,我們只要將LowerDW(fp(ProductID))除以2就行。但需注意的是,整個雙字值域中,LowerDW(fp(ProductID)) / 2 + (2<<31)同樣能滿足條件(由於溢出導致的相等),這點很重要!

  再來考慮高位的算法。我們需要把HighDW(fp(ProductID))往右移一位,這是左邊補入的一位可以任意。這時需要注意,考慮到shld性質,有以下兩種情況:

①如果HighDW(fp(ProductID))最低位是1則需要LowerDW(SerialNumber)的最高位為1

②如果HighDW(fp(ProductID))最低位是0則需要LowerDW(SerialNumber)的最高位為0

  考慮到LowerDW(fp(ProductID)) / 2和LowerDW(fp(ProductID)) / 2 + (2<<31)均可滿足條件,若是情況①則選取后者,因為此時可保證LowerDW(SerialNumber)的最高位為1。同理,若是情況②則需選擇前者。

  該算法的C語言描述如下:

SerialNumber逆變換算法
 1 void getSerialNumber(__int64 productId, char* buffer){
 2     DWORD upper = productId >> 0x20;
 3     DWORD lower = productId;
 4     assert((lower & 1) == 0); //lower = snLower + snLower因此lower必須為偶數
 5 
 6 
 7 
 8     DWORD snUpper = upper >> 1;
 9 
10     DWORD snLower =0;
11     if((upper & 1) == 1){
12         snLower = lower / 2;
13         snLower += (1<<31);
14     }else{
15         snLower = lower / 2;
16     }
17 
18     DWORDLONG sn = snUpper;
19     sn <<= 0x20;
20     sn |= snLower;
21 
22     WORD *p = (WORD*)&sn;
23     sprintf(buffer, "%04x-%04x-%04x-%04x", p[0], p[1], p[2], p[3]);
24 }

 

小結

  IDA很強大,Crack很費時間,收獲的免費SRS使用權和投入的大量時間不成正比。結論:以后還是盡量少搞Crack吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM