keygenning4newbies keygenme #3 註冊演算法,雖然說是初學者的crackme,可是 (9千字)

看雪資料發表於2001-08-18

keygenning4newbies keygenme #3 註冊演算法,雖然說是初學者的crackme,可是
也不簡單喲~~~


我輸入的名字是:TAE!
        註冊碼:78787878
下面是檢查註冊碼個數的地方,和普通的檢測方法不一樣,瞧瞧:

:004011F5 6BC003                  imul eax, 00000003              ;eax是假註冊碼的個數
:004011F8 C1E002                  shl eax, 02                    ;右移兩位
:004011FB 05CD000000              add eax, 000000CD              ;加上0xCD
:00401200 8945FC                  mov dword ptr [ebp-04], eax    ;儲存
:00401203 817DFCA5010000          cmp dword ptr [ebp-04], 000001A5;和0x1A5比較
:0040120A 0F85BC000000            jne 004012CC                    ;不同就跳走了
:00401210 33C0                    xor eax, eax                    ;清零
:00401212 8A4594                  mov al, byte ptr [ebp-6C]      ;依次取註冊碼字元
:00401215 84C0                    test al, al                    ;是最後一個字元嗎?
:00401217 7413                    je 0040122C                    ;是就跳走了!準備計算
:00401219 8D4D94                  lea ecx, dword ptr [ebp-6C]    ;指向註冊碼

根據上面的演算法,可以得到這樣一個方程式:
(個數*3*2^2)+0xCD=0x1A5      (注:"2^2"指的是2的平方!)
既然知道了這個,求“個數”應該就非常簡單了吧?用Windows的計算器簡單的算一下,
0x1A5-0xCD=0xD8,用0xD8/2^2=0x36,最後用0x36/3=0x12,換算成10進位制,那麼就是18,
所以,根據上面的演算法可以知道註冊碼必須是18個字元!那麼輸入787878787878787878

繼續跟蹤來到下面,這裡是檢查註冊碼中是否有小於0的Ascii碼的字元。有的話程式就
判斷註冊碼是錯的!

:0040121C 3C30                    cmp al, 30                      ;小於零嗎?
:0040121E 0F82C6000000            jb 004012EA                    ;小於就跳走了!完蛋!
:00401224 8A4101                  mov al, byte ptr [ecx+01]      ;否則就將下一個字元給al
:00401227 41                      inc ecx                        ;指向下一個字元
:00401228 84C0                    test al, al                    ;是空嗎
:0040122A 75F0                    jne 0040121C                    ;沒有結束就跳,形成迴圈

出了上面那個迴圈,我們便來到了下面:

:0040122C E8CFFDFFFF              call 00401000                    ;這裡面會將eax,ebx,ecx,edx清零
:00401231 8D852CFFFFFF            lea eax, dword ptr [ebp+FFFFFF2C];指向使用者名稱
:00401237 50                      push eax                        ;將使用者名稱壓入堆疊
:00401238 E843FEFFFF              call 00401080                    ;裡面會對使用者名稱進行操作

給初學者介紹一點經驗,如果你發現程式先將使用者名稱壓入堆疊,後面緊跟著一個Call,那
你就得非常注意了,除了計算個數,那麼很可能就是計算註冊碼了!所以我們一定得進去
看看到底發生了什麼!

:00401080 55                      push ebp
:00401081 8BEC                    mov ebp, esp
:00401083 51                      push ecx
:00401084 53                      push ebx
:00401085 56                      push esi
:00401086 57                      push edi

* Possible StringData Ref from Data Obj ->"eheh"        //注意這個喲
                                  |
:00401087 6880504000              push 00405080
:0040108C 6A00                    push 00000000
:0040108E E8ADFFFFFF              call 00401040      ;將上面的字元Ascii反相放入eax
:00401093 83C408                  add esp, 00000008
:00401096 8BD8                    mov ebx, eax        ;再放到ebx中去
:00401098 E863FFFFFF              call 00401000

* Possible StringData Ref from Data Obj ->" is a whore." //什麼?妓女??
                                  |
:0040109D BF70504000              mov edi, 00405070
:004010A2 83C9FF                  or ecx, FFFFFFFF
:004010A5 33C0                    xor eax, eax
:004010A7 F2                      repnz

.......

:004010CC 8B4508                  mov eax, dword ptr [ebp+08]
:004010CF 50                      push eax                  ;到了這裡,使用者名稱就和"is a whore"給串連了!
:004010D0 56                      push esi                  ;媽的,竟然說我們是妓女!
:004010D1 E86AFFFFFF              call 00401040              ;每次取串連後的四個字元
:004010D6 8B8E30504000            mov ecx, dword ptr [esi+00405030] ;將"12"放入ecx
:004010DC 83C408                  add esp, 00000008         
:004010DF 33CF                    xor ecx, edi              ;異或結果放入ecx
:004010E1 03C1                    add eax, ecx              ;用四個字元的十六進位制加上ecx
:004010E3 8945FC                  mov dword ptr [ebp-04], eax;儲存
:004010E6 C145FC07                rol dword ptr [ebp-04], 07 ;帶進位的左移七位
:004010EA 8B45FC                  mov eax, dword ptr [ebp-04];結果放入eax
:004010ED 83C604                  add esi, 00000004     
:004010F0 33D8                    xor ebx, eax              ;異或(ebx是"eheh"的十六進位制)
:004010F2 47                      inc edi                   
:004010F3 83FE40                  cmp esi, 00000040          ;哇!做六十四次!!
:004010F6 7CD4                    jl 004010CC                ;跳轉形成迴圈!
:004010F8 5F                      pop edi
:004010F9 8BC3                    mov eax, ebx
:004010FB 5E                      pop esi
:004010FC 5B                      pop ebx
:004010FD 8BE5                    mov esp, ebp
:004010FF 5D                      pop ebp
:00401100 C3                      ret

上面算出一個結果在eax和ebx中
好啦,終於可以回去了!

:0040123D 8945FC                  mov dword ptr [ebp-04], eax ;儲存
:00401240 E8BBFDFFFF              call 00401000              ;這裡面會將eax,ebx,ecx,edx清零
:00401245 8D8D2CFFFFFF            lea ecx, dword ptr [ebp+FFFFFF2C];"TAE! is a whore"字串
:0040124B 56                      push esi
:0040124C 51                      push ecx
:0040124D E8BEFDFFFF              call 00401010             
:00401252 83C40C                  add esp, 0000000C
:00401255 33C9                    xor ecx, ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401284(C)
|
:00401257 8B45FC                  mov eax, dword ptr [ebp-04] ;記得這個嗎?就是上面計算出的值啦!
:0040125A 33D2                    xor edx, edx                ;清零
:0040125C BE1A000000              mov esi, 0000001A          ;0x1A放入esi
:00401261 F7F6                    div esi                    ;用上面的值除以0x1A
:00401263 8A941510FFFFFF          mov dl, byte ptr [ebp+edx-000000F0] ;查一張由26個大寫字母組成的表
:0040126A 88540DC8                mov byte ptr [ebp+ecx-38], dl      ;儲存
:0040126E 8B45FC                  mov eax, dword ptr [ebp-04]        ;取值放入eax
:00401271 C1E003                  shl eax, 03                        ;將它乘以8
:00401274 BA45230100              mov edx, 00012345                  ;0x12345放入edx
:00401279 F7E8                    imul eax                            ;乘以eax   
:0040127B 03C2                    add eax, edx                        ;和0x12345相加
:0040127D 8945FC                  mov dword ptr [ebp-04], eax        ;又儲存嘍!
:00401280 41                      inc ecx                            ;計數器
:00401281 83F912                  cmp ecx, 00000012                  ;結束了嗎?
:00401284 72D1                    jb 00401257                        ;沒有就跳轉
:00401286 E875FDFFFF              call 00401000                     
:0040128B 33C0                    xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012A2(C)
|
:0040128D 8A4C0594                mov cl, byte ptr [ebp+eax-6C]      ;輸入的註冊碼
:00401291 8A5405C8                mov dl, byte ptr [ebp+eax-38]      ;查表得到的字母
:00401295 80E930                  sub cl, 30                        ;Ascii減0x30
:00401298 32D1                    xor dl, cl                        ;和查表後的字母異或
:0040129A 885405C8                mov byte ptr [ebp+eax-38], dl      ;儲存
:0040129E 40                      inc eax                            ;計數器
:0040129F 83F812                  cmp eax, 00000012                  ;結束了?
:004012A2 72E9                    jb 0040128D                        ;未結束就跳!
:004012A4 E857FDFFFF              call 00401000
:004012A9 8D55C8                  lea edx, dword ptr [ebp-38]
:004012AC 52                      push edx
:004012AD E85EFEFFFF              call 00401110                      ;這裡面是最後的運算!
:004012B2 E849FDFFFF              call 00401000
:004012B7 8D45C8                  lea eax, dword ptr [ebp-38]

進入call 00401110

:00401110 8B4C2404                mov ecx, dword ptr [esp+04]
:00401114 33C0                    xor eax, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401122(C)
|
:00401116 8A1408                  mov dl, byte ptr [eax+ecx]        ;上面結果的一個數
:00401119 32D0                    xor dl,al                          ;和位數異或(從零開始)
:0040111B 881408                  mov byte ptr [eax+ecx], dl        ;儲存!
:0040111E 40                      inc eax
:0040111F 83F812                  cmp eax, 00000012                  ;又是這麼多的迴圈
:00401122 72F2                    jb 00401116                        ;迴圈 
:00401124 C3                      ret

回去嘍!
下面就是最後的比較了!呼,好累!


* Possible StringData Ref from Data Obj ->"KEYGENNING4NEWBIES"
                                  |
:004012BA 6814514000              push 00405114                    ;這個是"KEYGENNING4NEWBIES"
:004012BF 50                      push eax                          ;這個是最後運算出的結果
:004012C0 E86BFEFFFF              call 00401130                    ;比較是否相同
:004012C5 83C40C                  add esp, 0000000C
:004012C8 85C0                    test eax, eax
:004012CA 753C                    jne 00401308

所以我們們的註冊碼經過運算後一定要和"KEYGENNING4NEWBIES"這個字串相同,
好了,演算法已經清楚了,誰來寫個序號產生器?偽裝者大俠?這個夠級別吧?試試呀!也好讓我們這些
嚮往搞序號產生器的朋友學習學習;)

相關文章