这是一个crackme破解练习
算法简单 适合初学!
附件:Splish.rar
呵呵 我也是初学者 也是从爆破刚刚走出来(也许还没有^_^,但我想走出来)!
----------------------------------------------------------------------
我非常讨厌这些密密麻麻的汇编代码就象魔鬼字符 一点意思都没有! 我看破解文章时也是检 中文多的看 !没办法 太菜了
----------------------------------------------------------------------
非常感谢看雪里的同仁们为了照顾我们这些菜鸟 不顾辛劳 写的一篇篇好文并整理收集! 可想而知你们不顾辛劳 不计报酬 花费了多少时间!
----------------------------------------------------------------------
特别是看雪学院里的同仁们,本站作为中国破解界最早 最有威望 最有技术含量对中国破解影响最深的破解交流平台 在经历了几年的风风雨雨 付出了大量的心血 由于破解技术的特殊性 总有一些人不厌其烦的攻击 遭受各方面的压力也越来越大 着实让人担心!前几天买了看雪学院的加密与解密第二版看的爽透了!
----------------------------------------------------------------------
^_^值此新春佳节到来之际 真诚祝愿看雪学院越来越好 祝愿看雪学院里的同仁们新年快乐 心想事成!
以此文感谢那么多破文的作者! 没有你们也没有我的这篇文章!
----------------------------------------------------------------------
一个破解练习 比较早了 可能也有人写过 ! 不过肯定没我细吧! 建议如果初学一定要看懂算法!如果有错误一定要指出!
断点下在 GetWindowTextA ( bp GetWindowTextA ) 建议初学者在跟踪算法时 把自己输入的用户名的ASC先看一下有一个印象
还需要知道 你注册码和用户名输入了多少位(ASC码)
----------------------------------------------------------------------
004015E4 /$ 55 PUSH EBP
004015E5 |. 8BEC MOV EBP,ESP
004015E7 |. 6A 20 PUSH 20 ; /Count = 20 (32.)
004015E9 |. 68 42324000 PUSH Splish.00403242 ; |Buffer = Splish.00403242
004015EE |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; |hWnd
004015F1 |. E8 34010000 CALL <JMP.&USER32.GetWindowTextA> ; \GetWindowTextA
004015F6 |. 85C0 TEST EAX,EAX
004015F8 |. 0F84 95000000 JE Splish.00401693 ; 测试是否输入了用户名
004015FE |. A3 67344000 MOV DWORD PTR DS:[403467],EAX
00401603 |. 6A 0B PUSH 0B ; /Count = B (11.)
00401605 |. 68 36324000 PUSH Splish.00403236 ; |Buffer = Splish.00403236
0040160A |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
0040160D |. E8 18010000 CALL <JMP.&USER32.GetWindowTextA> ; \GetWindowTextA
00401612 |. 85C0 TEST EAX,EAX
00401614 |. 74 68 JE SHORT Splish.0040167E ; 测试是否输入了注册码
00401616 |. A3 63344000 MOV DWORD PTR DS:[403463],EAX ; eax为用户名位数送内存403463处 下面循环用
0040161B |. 33C9 XOR ECX,ECX ; ecx 清零下面要用
0040161D |. 33DB XOR EBX,EBX ; 同上
0040161F |. 33D2 XOR EDX,EDX ; 同上
00401621 |. 8D35 36324000 LEA ESI,DWORD PTR DS:[403236] ; 把内存地址为403236里的值送入esi 可以在命令行输入d 403236查看
00401627 |. 8D3D 58324000 LEA EDI,DWORD PTR DS:[403258] ; 同上
0040162D |. B9 0A000000 MOV ECX,0A ; 把0A 送ecx
00401632 |> 0FBE041E /MOVSX EAX,BYTE PTR DS:[ESI+EBX] ; 循环入口 依次取用户名ASC码
00401636 |. 99 |CDQ ; 字符扩展
00401637 |. F7F9 |IDIV ECX ; 取用户名ASC码除以0A余数送EDX(ecx为常数0A)
00401639 |. 33D3 |XOR EDX,EBX ; 当前计算位数与(ASC码除以0A的余数EDX)异或
0040163B |. 83C2 02 |ADD EDX,2 ; 当前计算位数与(ASC码除以0A的余数EDX)异或+2
0040163E |. 80FA 0A |CMP DL,0A ; 当前计算位数与(ASC码除以0A的余数EDX)异或+2与0a比较
00401641 |. 7C 03 |JL SHORT Splish.00401646 ; 这里插一句 本例中所有除运算 商,作者没用!
00401643 |. 80EA 0A |SUB DL,0A ; 当前计算位数与(ASC码除以0A的余数EDX)异或+2与0a比较大于0a就-0A
00401646 |> 88141F |MOV BYTE PTR DS:[EDI+EBX],DL ; 当前计算位数与(ASC码除以0A的余数EDX)异或+2与0a比较大于就-0A 把值送入edi+ebx
00401649 |. 43 |INC EBX ; 取下一位!
0040164A |. 3B1D 63344000 |CMP EBX,DWORD PTR DS:[403463] ; 比较取完没
00401650 |.^ 75 E0 \JNZ SHORT Splish.00401632 ; 没取完向上继续 循环出口
00401652 |. 33C9 XOR ECX,ECX ; ecx 清零下面用
00401654 |. 33DB XOR EBX,EBX ; 同上 清零
00401656 |. 33D2 XOR EDX,EDX ; 同上 清零
00401658 |. 8D35 42324000 LEA ESI,DWORD PTR DS:[403242] ; 参照上面 类似指令!
0040165E |. 8D3D 4D324000 LEA EDI,DWORD PTR DS:[40324D] ; 参照上面 类似指令!
00401664 |. B9 0A000000 MOV ECX,0A ; 把0A 送ecx
00401669 |> 0FBE041E /MOVSX EAX,BYTE PTR DS:[ESI+EBX] ; 循环入口 取当前注册码ASC码
0040166D |. 99 |CDQ ; 字符扩展
0040166E |. F7F9 |IDIV ECX ; 你应该知道这是除法运算了吧! 罗嗦一句 eax/ecx商eax 余edx
00401670 |. 88141F |MOV BYTE PTR DS:[EDI+EBX],DL ; 循环内容 当前注册码ASC码除0A的余数给EDX+EBX 循环结果 也放EDX+EBX这里了! 在下面比较时一个一个取出来比较
00401673 |. 43 |INC EBX ; ebx加一
00401674 |. 3B1D 67344000 |CMP EBX,DWORD PTR DS:[403467] ; 比较是否取完
0040167A |.^ 75 ED \JNZ SHORT Splish.00401669 ; 循环出口 结束时 就不往上条跳了
0040167C |. EB 2A JMP SHORT Splish.004016A8
0040167E |> 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401680 |. 68 0A304000 PUSH Splish.0040300A ; |Title = "Splish, Splash"
00401685 |. 68 A0304000 PUSH Splish.004030A0 ; |Text = "Please enter your name."
0040168A |. 6A 00 PUSH 0 ; |hOwner = NULL
0040168C |. E8 B7000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401691 |. EB 62 JMP SHORT Splish.004016F5
00401693 |> 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00401695 |. 68 0A304000 PUSH Splish.0040300A ; |Title = "Splish, Splash"
0040169A |. 68 B8304000 PUSH Splish.004030B8 ; |Text = "Please enter your serial number."
0040169F |. 6A 00 PUSH 0 ; |hOwner = NULL
004016A1 |. E8 A2000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004016A6 |. EB 4D JMP SHORT Splish.004016F5
004016A8 |> 8D35 4D324000 LEA ESI,DWORD PTR DS:[40324D] ; 把内存地址为40324d里的值送入esi 可以在命令行输入d 40324d查看
004016AE |. 8D3D 58324000 LEA EDI,DWORD PTR DS:[403258] ; 同上
004016B4 |. 33DB XOR EBX,EBX ; EBX 清零
004016B6 |> 3B1D 63344000 /CMP EBX,DWORD PTR DS:[403463] ; 此为以上计算出的两码依次比较--循环开始处 从以上循环可知此验证为f(用户名)=f(注册码)
004016BC |. 74 0F |JE SHORT Splish.004016CD ; 全部正确就跳转 爆破点
004016BE |. 0FBE041F |MOVSX EAX,BYTE PTR DS:[EDI+EBX] ; edi+ebx是由上面循环用户名所得值 传一个字节给eax
004016C2 |. 0FBE0C1E |MOVSX ECX,BYTE PTR DS:[ESI+EBX] ; esi+ebx是由上面循环注册码所得 传一个字节给ecx
004016C6 |. 3BC1 |CMP EAX,ECX ; 比较
004016C8 |. 75 18 |JNZ SHORT Splish.004016E2 ; 错误就跳
004016CA |. 43 |INC EBX ; 把ebx加1
004016CB |.^ EB E9 \JMP SHORT Splish.004016B6 ; 继续循环
004016CD |> \6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004016CF |. 68 0A304000 PUSH Splish.0040300A ; |Title = "Splish, Splash"
004016D4 |. 68 42304000 PUSH Splish.00403042 ; |Text = "Good job, now keygen it."
004016D9 |. 6A 00 PUSH 0 ; |hOwner = NULL
004016DB |. E8 68000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004016E0 |. EB 13 JMP SHORT Splish.004016F5
004016E2 |> 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004016E4 |. 68 0A304000 PUSH Splish.0040300A ; |Title = "Splish, Splash"
004016E9 |. 68 67304000 PUSH Splish.00403067 ; |Text = "Sorry, please try again."
004016EE |. 6A 00 PUSH 0 ; |hOwner = NULL
004016F0 |. E8 53000000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004016F5 |> C9 LEAVE
004016F6 \. C2 0800 RETN 8
004016BC |. 74 0F |JE SHORT Splish.004016CD ; 全部正确就跳转 爆破点
改为
004016BC /EB 0F JMP SHORT Splish.004016CD ; 全部正确就跳转 爆破点
算法总结:
-----------------------------------------------------------------------------------
程序开始:
注册名循环开始 取完没?
[(当前计算位数)与(当前用户名ASC码除以0A的余数EDX)异或]+2与0a比较大于就-0A
下一位
继续循环
注册码循环开始 取完没?
当前注册码ASC码除0A的余数
下一位
继续循环
以上两数相等吗? 相等-》"Good job, now keygen it." 不相等->"Sorry, please try again."
程序结束!
f(用户名)=f(注册码)
|
|