1. 程式人生 > >簡單算法分析2 ------適合新手學習算法分析

簡單算法分析2 ------適合新手學習算法分析

user 核心 creat 3.3 username and volatile 不遠 初始化

自從發表了第一篇算法分析文章起,自己打心底上就喜歡上算法分析了,O(_)O哈哈~

好了,今天繼續分享一個簡單的算法分析文章,雖然也是參考別人的文章,但是只學理論不去實踐的話,永遠都開不到東西,所以我選擇了自己動手跟著別人的分析文章走,然後再結合自己的思路來進行分析,寫註冊機。

本文參考文章:http://blog.sina.com.cn/u/2295763487

【軟件名稱】: SecureExplore 3.3
【下載地址】: http://www.onlinedown.net/soft/14419.htm

打開軟件,輸入以下內容點擊註冊後信息框提示信息

所以我們直接下信息框斷點或者是搜索字符串進行快速定位關鍵破解地方。

100031A0 6A FF push -0x1 ; 註冊按鈕

100031A2 68 517D0110 push LicenseD.10017D51

100031A7 64:A1 00000000 mov eax,dword ptr fs:[0]

100031AD 50 push eax

100031AE 64:8925 0000000>mov dword ptr fs:[0],esp

100031B5 81EC 28010000 sub esp,0x128

100031BB A1 B8E50110 mov eax,dword ptr ds:[0x1001E5B8]

100031C0 53 push ebx

100031C1 55 push ebp

100031C2 56 push esi ; LicenseD.10019498

100031C3 57 push edi

100031C4 8BE9 mov ebp,ecx

100031C6 894424 10 mov dword ptr ss:[esp+0x10],eax

100031CA 33F6 xor esi,esi ; LicenseD.10019498

100031CC 894424 18 mov dword ptr ss:[esp+0x18],eax

100031D0 89B424 40010000 mov dword ptr ss:[esp+0x140],esi ; LicenseD.10019498

100031D7 894424 14 mov dword ptr ss:[esp+0x14],eax

100031DB 8D9D 94020000 lea ebx,dword ptr ss:[ebp+0x294]

100031E1 8D4424 38 lea eax,dword ptr ss:[esp+0x38]

100031E5 68 80000000 push 0x80

100031EA 50 push eax

100031EB 8BCB mov ecx,ebx

100031ED C68424 48010000>mov byte ptr ss:[esp+0x148],0x2

100031F5 E8 90140100 call LicenseD.1001468A

100031FA 8D9424 B8000000 lea edx,dword ptr ss:[esp+0xB8] ; 獲取用戶名的長度

10003201 68 80000000 push 0x80

10003206 8D8D 58020000 lea ecx,dword ptr ss:[ebp+0x258]

1000320C 52 push edx

1000320D E8 78140100 call LicenseD.1001468A ; 獲取key的長度、

10003212 8D4424 38 lea eax,dword ptr ss:[esp+0x38] ; 用戶名

10003216 8BCD mov ecx,ebp

10003218 50 push eax

10003219 E8 E2FEFFFF call LicenseD.10003100

1000321E 8D8C24 B8000000 lea ecx,dword ptr ss:[esp+0xB8] ; key

10003225 51 push ecx

10003226 8BCD mov ecx,ebp

10003228 E8 D3FEFFFF call LicenseD.10003100

1000322D 8D5424 38 lea edx,dword ptr ss:[esp+0x38] ; uername

10003231 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]

10003235 52 push edx

10003236 E8 50E70000 call LicenseD.1001198B

1000323B 8D8424 B8000000 lea eax,dword ptr ss:[esp+0xB8] ; key

10003242 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]

10003246 50 push eax

我們來到這裏 這段地方就是註冊按鈕事件

1000324C 8B45 74 mov eax,dword ptr ss:[ebp+0x74] ; SE unique Seed 0x0031

1000324F 8B4D 70 mov ecx,dword ptr ss:[ebp+0x70] ; GlobeSoft

10003252 8B5424 10 mov edx,dword ptr ss:[esp+0x10] ; username

10003256 50 push eax

10003257 51 push ecx

10003258 8D4C24 20 lea ecx,dword ptr ss:[esp+0x20]

1000325C 51 push ecx

1000325D 52 push edx

1000325E 897424 2C mov dword ptr ss:[esp+0x2C],esi

10003262 E8 89ECFFFF call LicenseD.10001EF0 ; 關鍵算法Call

10003267 83C4 10 add esp,0x10

1000326A 25 FF000000 and eax,0xFF

1000326F 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]

10003273 8BF8 mov edi,eax

10003275 68 FCE30110 push LicenseD.1001E3FC ; -MNM5

1000327A E8 22CA0000 call LicenseD.1000FCA1 ; 檢測用戶名裏是否包含 "-MNM5"

1000327F 83F8 FF cmp eax,-0x1 ; 返回用戶名- -MNM5的長度 長度7

10003282 74 07 je short LicenseD.1000328B

10003284 BE 01000000 mov esi,0x1

10003289 EB 29 jmp short LicenseD.100032B4

1000328B 807C24 3E 2D cmp byte ptr ss:[esp+0x3E],0x2D

10003290 75 22 jnz short LicenseD.100032B4

10003292 8D85 F8000000 lea eax,dword ptr ss:[ebp+0xF8]

10003298 6A 02 push 0x2

1000329A 8D4C24 3C lea ecx,dword ptr ss:[esp+0x3C]

1000329E 50 push eax

1000329F 51 push ecx

100032A0 E8 FB190000 call LicenseD.10004CA0

100032A5 83C4 0C add esp,0xC

100032A8 85C0 test eax,eax

100032AA 75 08 jnz short LicenseD.100032B4

100032AC C74424 1C 01000>mov dword ptr ss:[esp+0x1C],0x1

100032B4 85FF test edi,edi

100032B6 0F84 3F020000 je LicenseD.100034FB ; 檢測是否註冊成功

100032BC 8B5424 1C mov edx,dword ptr ss:[esp+0x1C]

100032C0 0BD6 or edx,esi

我們先單步調試下看看程序流程,通過看錯誤提示來進行定位關鍵算法call

我們可以看到標記為紅色的判斷跳轉,這個跳轉是跳到提示錯誤信息的地方,所以我們看到這跳轉就大概知道算法call就在這個跳轉的不遠處。

100034FB 6A 40 push 0x40

100034FD 68 78E20110 push LicenseD.1001E278 ; Unsuccessful Registration!

10003502 68 54E20110 push LicenseD.1001E254 ; Not a valid License\nand/or Key!\n

10003507 8BCD mov ecx,ebp

10003509 E8 F1FF0000 call LicenseD.100134FF

1000350E 8D4C24 14 lea ecx,dword ptr ss:[esp+0x14]

10003512 C68424 40010000>mov byte ptr ss:[esp+0x140],0x1

1000351A E8 15E40000 call LicenseD.10011934

1000351F 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]

10003523 C68424 40010000>mov byte ptr ss:[esp+0x140],0x0

1000352B E8 04E40000 call LicenseD.10011934

10003530 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]

10003534 C78424 40010000>mov dword ptr ss:[esp+0x140],-0x1

1000353F E8 F0E30000 call LicenseD.10011934

10003544 8B8C24 38010000 mov ecx,dword ptr ss:[esp+0x138]

1000354B 5F pop edi ; 0012E890

1000354C 5E pop esi ; 0012E890

1000354D 5D pop ebp ; 0012E890

1000354E 5B pop ebx ; 0012E890

1000354F 64:890D 0000000>mov dword ptr fs:[0],ecx

10003556 81C4 34010000 add esp,0x134

1000355C C3 retn

然後經過幾次調試,我們不難發現,10003262 這個地址為關鍵算法Call。

我們F7進call看看

10001EF0 8B4424 10 mov eax,dword ptr ss:[esp+0x10] ; SE unique Seed 0x0031

10001EF4 8B4C24 0C mov ecx,dword ptr ss:[esp+0xC] ; GlobeSoft

10001EF8 8B5424 04 mov edx,dword ptr ss:[esp+0x4] ; 用戶名

10001EFC 83EC 44 sub esp,0x44

10001EFF 50 push eax

10001F00 51 push ecx

10001F01 8D4424 28 lea eax,dword ptr ss:[esp+0x28]

10001F05 52 push edx

10001F06 50 push eax

10001F07 E8 54000000 call LicenseD.10001F60 ; 核心算法 計算出md5

上面貼出的代碼,標記為紅色的為關鍵

我們進入10001F07 E8 54000000 call LicenseD.10001F60 ; 核心算法 計算出md5 這個地址看看

10001FEA 8D4424 20 lea eax,dword ptr ss:[esp+0x20]

10001FEE 83E1 03 and ecx,0x3

10001FF1 50 push eax

10001FF2 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[>

10001FF4 E8 D7F2FFFF call LicenseD.100012D0 ; 初始化MD5

10001FF9 8D7C24 7C lea edi,dword ptr ss:[esp+0x7C] ; GlobeSoftSE unique Seed 0x0031Sendige

10001FFD 83C9 FF or ecx,-0x1

10002000 33C0 xor eax,eax

10002002 8D5424 24 lea edx,dword ptr ss:[esp+0x24]

10002006 F2:AE repne scas byte ptr es:[edi]

來到10001FF9 這個地址,我們看到[esp+0x7C]的數據是 GlobeSoftSE unique Seed 0x0031Sendige

所以可以看出,前面壓入的這兩個字符串 GlobeSoftSE unique Seed 0x0031 和我們輸入的用戶名進行合並

我在這裏設str=GlobeSoftSE unique Seed 0x0031

設 user_str=str+用戶名=GlobeSoftSE unique Seed 0x0031Sendige

1000200C 8D8C24 80000000 lea ecx,dword ptr ss:[esp+0x80] ; GlobeSoftSE unique Seed 0x0031Sendige

10002013 51 push ecx 壓入user_str進行md5加密

10002014 52 push edx

10002015 E8 E6F2FFFF call LicenseD.10001300 ; MD5加密

1000201A 8D4424 30 lea eax,dword ptr ss:[esp+0x30]

1000201E 8D4C24 1C lea ecx,dword ptr ss:[esp+0x1C]

10002022 50 push eax

10002023 51 push ecx

10002024 E8 87F3FFFF call LicenseD.100013B0 ; MD5加密

10002029 8B9C24 94020000 mov ebx,dword ptr ss:[esp+0x294]

10002030 83C4 18 add esp,0x18

10002033 33F6 xor esi,esi

10002035 8BFB mov edi,ebx

10002037 33D2 xor edx,edx

10002039 8A5434 0C mov dl,byte ptr ss:[esp+esi+0xC] ; DL逐位指向 MD5加密後的結果

1000203D 52 push edx

1000203E 68 2CE10110 push LicenseD.1001E12C ; %02x

10002043 57 push edi

10002044 E8 31280000 call LicenseD.1000487A ; 把內存中的MD5結果格式化為 小寫字符串

10002049 83C4 0C add esp,0xC ; ebx=8f7ac38427990c023c056f39886bde08(user_str MD5後的結果)

1000204C 46 inc esi

1000204D 83C7 02 add edi,0x2

10002050 83FE 10 cmp esi,0x10

10002053 ^ 7C E2 jl short LicenseD.10002037

10002055 5F pop edi ; 0012DC24

10002056 C643 20 00 mov byte ptr ds:[ebx+0x20],0x0

1000205A 5E pop esi ; 0012DC24

1000205B 5B pop ebx ; 0012DC24

1000205C 81C4 6C020000 add esp,0x26C

10002062 C3 retn

這段代碼其實就是將user_str MD5加密 我在這裏設user_str md5 =str_md5

然後我們單步出來後來到這裏

10001F0C 0FBE4C24 4E movsx ecx,byte ptr ss:[esp+0x4E] ; md5數據的第31位

10001F11 0FBE5424 38 movsx edx,byte ptr ss:[esp+0x38] ; md5數據的第第9位

10001F16 0FBE4424 36 movsx eax,byte ptr ss:[esp+0x36] ; md5數據的第第7位

10001F1B 83C4 10 add esp,0x10

10001F1E 51 push ecx

10001F1F 52 push edx

10001F20 0FBE4C24 2B movsx ecx,byte ptr ss:[esp+0x2B] ; md5數據的第第4位

10001F25 0FBE5424 28 movsx edx,byte ptr ss:[esp+0x28] ; md5數據的第第1位

10001F2A 50 push eax

10001F2B 51 push ecx

10001F2C 52 push edx

10001F2D 8D4424 14 lea eax,dword ptr ss:[esp+0x14]

10001F31 68 20E10110 push LicenseD.1001E120 ; %x%x%x-%x%x

10001F36 50 push eax

10001F37 E8 3E290000 call LicenseD.1000487A ; 轉換為真碼

10001F3C 8B4C24 68 mov ecx,dword ptr ss:[esp+0x68] ; 393665-6136

10001F40 8D5424 1C lea edx,dword ptr ss:[esp+0x1C]

10001F44 52 push edx

10001F45 8B01 mov eax,dword ptr ds:[ecx]

10001F47 50 push eax

10001F48 E8 7E280000 call LicenseD.100047CB

10001F4D 85C0 test eax,eax

10001F4F 0F94C0 sete al

10001F52 83C4 68 add esp,0x68

10001F55 C3 retn

我們可以看到分別取md5數據的第1、4、7、9、31共五位 字符的ASCII碼並轉換成十六進制的字符串

分別記為 str_md5_1 str_md5_4 str_md5_7 str_md5_9 str_md5_31

我們怎麽知道它是獲取數據的第幾位,其實我們可以在標記為紅色的地址上數據窗口中跟隨就能看的一目了然。

如上圖,直接定位到哪個數據,接著就自己去數吧。其他我就不再闡述了。

接著我們進入10001F37 這個地址看看

1000487A 55 push ebp

1000487B 8BEC mov ebp,esp

1000487D 83EC 20 sub esp,0x20

10004880 8B45 08 mov eax,dword ptr ss:[ebp+0x8]

10004883 56 push esi

10004884 8945 E8 mov dword ptr ss:[ebp-0x18],eax

10004887 8945 E0 mov dword ptr ss:[ebp-0x20],eax

1000488A 8D45 10 lea eax,dword ptr ss:[ebp+0x10]

1000488D C745 EC 4200000>mov dword ptr ss:[ebp-0x14],0x42

10004894 50 push eax

10004895 8D45 E0 lea eax,dword ptr ss:[ebp-0x20]

10004898 FF75 0C push dword ptr ss:[ebp+0xC] ; %x%x%x-%x%x

1000489B C745 E4 FFFFFF7>mov dword ptr ss:[ebp-0x1C],0x7FFFFFFF

100048A2 50 push eax

100048A3 E8 B4350000 call LicenseD.10007E5C

100048A8 83C4 0C add esp,0xC 可以在堆棧看到真正的註冊碼

100048AB FF4D E4 dec dword ptr ss:[ebp-0x1C] ; LicenseD.100011DF

100048AE 8BF0 mov esi,eax

100048B0 78 08 js short LicenseD.100048BA

100048B2 8B45 E0 mov eax,dword ptr ss:[ebp-0x20] ; SecExplo.0043654C

100048B5 8020 00 and byte ptr ds:[eax],0x0

100048B8 EB 0D jmp short LicenseD.100048C7

100048BA 8D45 E0 lea eax,dword ptr ss:[ebp-0x20]

100048BD 50 push eax

100048BE 6A 00 push 0x0

100048C0 E8 7F340000 call LicenseD.10007D44

100048C5 59 pop ecx ; LicenseD.10001F3C

100048C6 59 pop ecx ; LicenseD.10001F3C

100048C7 8BC6 mov eax,esi

100048C9 5E pop esi ; LicenseD.10001F3C

100048CA C9 leave

100048CB C3 retn

其實這裏是連接str_md5_1 str_md5_4 str_md5_7 str_md5_9 str_md5_31 這些數據,然後作為最後的註冊碼

10004898 FF75 0C push dword ptr ss:[ebp+0xC] ; %x%x%x-%x%x 這裏可以看出註冊碼格式

所以得出註冊碼:386138-3230

但是,註冊碼雖然出來了,拿這個得出的註冊碼註冊的話還是一樣提示錯誤,為什麽呢?我們繼續跟下去。

10003267 83C4 10 add esp,0x10

1000326A 25 FF000000 and eax,0xFF

1000326F 8D4C24 10 lea ecx,dword ptr ss:[esp+0x10]

10003273 8BF8 mov edi,eax

10003275 68 FCE30110 push LicenseD.1001E3FC ; -MNM5

1000327A E8 22CA0000 call LicenseD.1000FCA1 ; 檢測用戶名裏是否包含 "-MNM5"

1000327F 83F8 FF cmp eax,-0x1 ; 返回用戶名- -MNM5的長度 長度7

10003282 74 07 je short LicenseD.1000328B

10003284 BE 01000000 mov esi,0x1

10003289 EB 29 jmp short LicenseD.100032B4

1000328B 807C24 3E 2D cmp byte ptr ss:[esp+0x3E],0x2D

10003290 75 22 jnz short LicenseD.100032B4

來到這段代碼,可以看到檢測用戶名是否包含-MNM5這個字符串,如果沒有,就算正確的註冊碼也會註冊失敗。

我們進入1000327A 這個地址的call看看

1000FCA1 6A 00 push 0x0

1000FCA3 FF7424 08 push dword ptr ss:[esp+0x8]

1000FCA7 E8 03000000 call LicenseD.1000FCAF

1000FCAC C2 0400 retn 0x4

1000FCAF 56 push esi

1000FCB0 8BF1 mov esi,ecx

1000FCB2 8B4C24 0C mov ecx,dword ptr ss:[esp+0xC] ; LicenseD.1000327F

1000FCB6 8B06 mov eax,dword ptr ds:[esi] ; 用戶名

1000FCB8 3B48 F8 cmp ecx,dword ptr ds:[eax-0x8] ; 檢測用戶名的長度是否為0

1000FCBB 7F 12 jg short LicenseD.1000FCCF

1000FCBD FF7424 08 push dword ptr ss:[esp+0x8] ; -MNM5

1000FCC1 03C1 add eax,ecx

1000FCC3 50 push eax

1000FCC4 E8 8C62FFFF call LicenseD.10005F55 ; 進行對比

1000FCC9 59 pop ecx ; LicenseD.1000FCAC

1000FCCA 85C0 test eax,eax

1000FCCC 59 pop ecx ; LicenseD.1000FCAC

1000FCCD 75 05 jnz short LicenseD.1000FCD4

1000FCCF 83C8 FF or eax,-0x1

1000FCD2 EB 02 jmp short LicenseD.1000FCD6

1000FCD4 2B06 sub eax,dword ptr ds:[esi]

1000FCD6 5E pop esi ; LicenseD.1000FCAC

1000FCD7 C2 0800 retn 0x8

繼續進入1000FCC4 這個call看看

10005F55 55 push ebp

10005F56 8BEC mov ebp,esp

10005F58 53 push ebx

10005F59 33DB xor ebx,ebx

10005F5B 391D 9C4F0210 cmp dword ptr ds:[0x10024F9C],ebx

10005F61 56 push esi

10005F62 57 push edi

10005F63 75 0F jnz short LicenseD.10005F74

10005F65 FF75 0C push dword ptr ss:[ebp+0xC]

10005F68 FF75 08 push dword ptr ss:[ebp+0x8]

10005F6B E8 B0EEFFFF call LicenseD.10004E20

10005F70 59 pop ecx ; LicenseD.1000FCC9

10005F71 59 pop ecx ; LicenseD.1000FCC9

10005F72 EB 52 jmp short LicenseD.10005FC6

10005F74 FF75 0C push dword ptr ss:[ebp+0xC] ; -MNM5

10005F77 8B75 08 mov esi,dword ptr ss:[ebp+0x8]

10005F7A E8 C1000000 call LicenseD.10006040

10005F7F 8BFE mov edi,esi

10005F81 56 push esi

10005F82 2BF8 sub edi,eax

10005F84 E8 B7000000 call LicenseD.10006040

10005F89 59 pop ecx ; LicenseD.1000FCC9

10005F8A 03F8 add edi,eax

10005F8C 59 pop ecx ; LicenseD.1000FCC9

10005F8D 381E cmp byte ptr ds:[esi],bl

10005F8F 74 33 je short LicenseD.10005FC4

10005F91 3BF7 cmp esi,edi

10005F93 77 2F ja short LicenseD.10005FC4

10005F95 381E cmp byte ptr ds:[esi],bl

10005F97 8B45 0C mov eax,dword ptr ss:[ebp+0xC]

10005F9A 74 15 je short LicenseD.10005FB1

10005F9C 8BD6 mov edx,esi

10005F9E 2BD0 sub edx,eax

10005FA0 8A08 mov cl,byte ptr ds:[eax]

10005FA2 3ACB cmp cl,bl

10005FA4 74 0B je short LicenseD.10005FB1

10005FA6 380C02 cmp byte ptr ds:[edx+eax],cl

10005FA9 75 06 jnz short LicenseD.10005FB1

10005FAB 40 inc eax

10005FAC 381C02 cmp byte ptr ds:[edx+eax],bl

10005FAF ^ 75 EF jnz short LicenseD.10005FA0

10005FB1 3818 cmp byte ptr ds:[eax],bl

10005FB3 74 0B je short LicenseD.10005FC0

10005FB5 56 push esi

10005FB6 E8 44FCFFFF call LicenseD.10005BFF

10005FBB 59 pop ecx ; LicenseD.1000FCC9

10005FBC 8BF0 mov esi,eax

10005FBE ^ EB CD jmp short LicenseD.10005F8D

10005FC0 8BC6 mov eax,esi

10005FC2 EB 02 jmp short LicenseD.10005FC6

10005FC4 33C0 xor eax,eax

10005FC6 5F pop edi ; LicenseD.1000FCC9

10005FC7 5E pop esi ; LicenseD.1000FCC9

10005FC8 5B pop ebx ; LicenseD.1000FCC9

10005FC9 5D pop ebp ; LicenseD.1000FCC9

10005FCA C3 retn

這段代碼是一個標準的文本對比,如果對這個結構不熟悉的,可以自己在易語言寫個文本對比看看,和這個基本差不多。

10003481 8B5424 10 mov edx,dword ptr ss:[esp+0x10]

10003485 8D4C24 18 lea ecx,dword ptr ss:[esp+0x18]

10003489 50 push eax

1000348A 51 push ecx

1000348B 52 push edx

1000348C E8 CFE9FFFF call LicenseD.10001E60 ; 寫註冊信息到註冊表

10003491 83C4 0C add esp,0xC

10003494 8DB5 1C020000 lea esi,dword ptr ss:[ebp+0x21C]

1000349A 8BCE mov ecx,esi

1000349C 68 44E20110 push LicenseD.1001E244 ; OK

100034A1 E8 BD110100 call LicenseD.10014663

100034A6 6A 00 push 0x0

100034A8 8BCB mov ecx,ebx

0012DE14 10003A9A /CALL 到 RegCreateKeyExA 來自 LicenseD.10003A94

0012DE18 80000002 |hKey = HKEY_LOCAL_MACHINE

0012DE1C 00585ED0 |Subkey = "SOFTWARE\GlobeSoft\SecureExplore"

0012DE20 00000000 |Reserved = 0x0

0012DE24 10021A34 |Class = ""

0012DE28 00000000 |Options = REG_OPTION_NON_VOLATILE

0012DE2C 000F003F |Access = KEY_ALL_ACCESS

0012DE30 00000000 |pSecurity = NULL

0012DE34 0012DE44 |pHandle = 0012DE44

0012DE38 0012DE40 \pDisposition = 0012DE40

所以可以知道軟件是寫註冊表進行註冊的,Subkey = "SOFTWARE\GlobeSoft\SecureExplore"。刪除這裏面的鍵值就可以繼續玩了。

附上自己寫的易語言代碼,寫的很拙。。。。

高清文檔下載地址:http://www.vdisk.cn/down/index/19539036

簡單算法分析2 ------適合新手學習算法分析