160个CrackMe之123
来源:互联网 发布:二维动漫制作软件 编辑:程序博客网 时间:2024/06/05 21:02
我并不是大神,所以哪里写的不对,还请各位大佬们指出来。
0x0 分析算法
OD载入,搜索字符串,发现关键函数0x004013C0,给这个函数下断点,然后随便输入一串注册码,程序成功断下。
首先,程序将字符串”ABCDEFGHIJKLMNOPQRSTUVWXYZ”拷贝到一个新的地址处
00401421 B9 06000000 mov ecx, 0x600401426 BE 4C304000 mov esi, 0040304C ; ABCDEFGHIJKLMNOPQRSTUVWXYZ0040142B 8D7C24 24 lea edi, dword ptr [esp+0x24]0040142F 8D4424 14 lea eax, dword ptr [esp+0x14]00401433 F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]00401435 66:A5 movs word ptr es:[edi], word ptr [esi]
然后取出Code和Serial
00401437 50 push eax00401438 68 EA030000 push 0x3EA0040143D 8BCD mov ecx, ebp0040143F C64424 50 04 mov byte ptr [esp+0x50], 0x400401444 A4 movs byte ptr es:[edi], byte ptr [esi]00401445 E8 0A030000 call <jmp.&MFC42.#3097> ; 取出Code0040144A 8D4C24 10 lea ecx, dword ptr [esp+0x10]0040144E 51 push ecx0040144F 68 E9030000 push 0x3E900401454 8BCD mov ecx, ebp00401456 E8 F9020000 call <jmp.&MFC42.#3097> ; 取出Serial
然后用sscanf函数将Serial转换成整数
0040145B 8B4424 10 mov eax, dword ptr [esp+0x10]0040145F 8D5424 18 lea edx, dword ptr [esp+0x18]00401463 52 push edx ; Serial的整数形式00401464 68 48304000 push 00403048 ; %d00401469 50 push eax ; Serial0040146A FF15 84214000 call dword ptr [<&MSVCRT.sscanf>] ; msvcrt.sscanf
然后程序用srand函数设置一个随机数种子,种子值就是Serial的整数形式。
00401470 8B4C24 24 mov ecx, dword ptr [esp+0x24] ; Serial的整数形式00401474 51 push ecx ; Serial的整数形式00401475 FF15 B0214000 call dword ptr [<&MSVCRT.srand>] ; msvcrt.srand
然后调用rand函数,将rand函数返回的随机数除以0x1A,用余数取出”ABCDEFGHIJKLMNOPQRSTUVWXYZ”中的一个字符,一共进行12次。
0040147B 8B3D B8214000 mov edi, dword ptr [<&MSVCRT.rand>] ; msvcrt.rand00401481 83C4 10 add esp, 0x1000401484 BE 0C000000 mov esi, 0xC00401489 FFD7 call edi0040148B 99 cdq0040148C B9 1A000000 mov ecx, 0x1A00401491 F7F9 idiv ecx00401493 8D4C24 0C lea ecx, dword ptr [esp+0xC]00401497 8A5414 24 mov dl, byte ptr [esp+edx+0x24]0040149B 52 push edx0040149C E8 AD020000 call <jmp.&MFC42.#940> ; 转换成字符串004014A1 4E dec esi004014A2 ^ 75 E5 jnz short 00401489
其中,Code所对应的每个余数如下:
int DATA[] = {0x13,0x12,0x12,0x5,0x13,0xC,0x4,0x19,0x3,0xF,0xA,0x12};
最后将转换成的字符串和Code比较,如果相等就成功,否则失败。
004014A4 8B4424 14 mov eax, dword ptr [esp+0x14]004014A8 8B4C24 0C mov ecx, dword ptr [esp+0xC]004014AC 50 push eax ; Code004014AD 51 push ecx004014AE FF15 BC214000 call dword ptr [<&MSVCRT._mbscmp>] ; msvcrt._mbscmp004014B4 83C4 08 add esp, 0x8004014B7 85C0 test eax, eax004014B9 75 12 jnz short 004014CD ; 失败则转移
0x1 计算注册码
首先看一下srand函数是如何实现的:
函数取出保存随机数种子的地址,然后将参数1(即种子值)保存进去。
7404CAB0 > 8BFF mov edi, edi7404CAB2 55 push ebp7404CAB3 8BEC mov ebp, esp7404CAB5 E8 AAA20000 call 74056D647404CABA 8B4D 08 mov ecx, dword ptr [ebp+0x8] ; 取出种子值7404CABD 8948 14 mov dword ptr [eax+0x14], ecx ; 保存种子值7404CAC0 5D pop ebp7404CAC1 C3 retn
然后再看一下rand函数是如何实现的:
函数首先取出保存随机数种子的地址,然后取出种子值,进行如下运算:
Seed = Seed * 0x343FD + 0x269EC3
其中,Seed就是取出的种子值。
最后程序将Seed进行如下运算,返回结果,这个结果就是随机数。
Seed >> 0x10 & 0x7FFF
在程序中的代码如下:
7404CA80 > E8 DFA20000 call 74056D647404CA85 6948 14 FD43030>imul ecx, dword ptr [eax+0x14], 0x343FD7404CA8C 81C1 C39E2600 add ecx, 0x269EC37404CA92 8948 14 mov dword ptr [eax+0x14], ecx7404CA95 C1E9 10 shr ecx, 0x107404CA98 81E1 FF7F0000 and ecx, 0x7FFF7404CA9E 8BC1 mov eax, ecx7404CAA0 C3 retn
因为程序中有进行模运算(即取余数),因此无法逆向,考虑枚举。
枚举代码如下:
运行结果如图所示:
放到CM中测试一下,可以通过。
全文完。
- 160个CrackMe之123
- 160个CrackMe之001
- 160个crackme之003
- 160个crackme之004
- 160个crackme之008
- 160个crackme之009
- 160个crackme之010
- 160个crackme之011
- 160个CrackMe之11
- 160个CrackMe之91
- 160个CrackMe之51
- 160个CrackMe之41
- 160个CrackMe之34
- 160个破解练习之CrackMe 006
- 160个破解练习之CrackMe 007
- 160个破解练习之CrackMe 008
- 160个CrackMe-第九个
- [反汇编练习] 160个CrackMe之001
- 如何准备校招技术面试
- C++名字隐藏
- HTML canvas 制作星星背景加流星特效
- 清北学堂-D1-T1-alien
- ucos-iii学习之内存对象
- 160个CrackMe之123
- linux shell 脚本/命令 超时 结束
- Eclipse设置类或方法的注释模板
- 我的第一篇博客
- 【每周论文】Paragon: QoS-Aware Scheduling for Heterogeneous Datacenters
- 关于java中快速排序和冒泡排序的小结
- 换一个角度来看Hadoop集群
- Thinkphp封装P方法。实现分页效果
- C++17 std::in_place_type, std::in_place_index_t, std::in_place_type_t 这些的用法