简单算法分析2 ------适合新手学习算法分析
2021-07-04 23:04
所以我们直接下信息框断点或者是搜索字符串进行快速定位关键破解地方。
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
我们怎么知道它是获取数据的第几位,其实我们可以在标记为红色的地址上数据窗口中跟随就能看的一目了然。