吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4665|回复: 12
收起左侧

[原创] 160个Crackme之019学习笔记

[复制链接]
海天一色001 发表于 2019-4-22 09:15
打开019程序,与018一样的作者,只是要输入用户名和注册码后进行检测:
001.png     002.png
直接点击“Check it”按钮,程序弹出提示,要求用户名长度要5个以上;
用户名随意输入“11111”,注册码输入“22222”再点击,弹出错误提示:
003.png
仍然先查壳,C++ 6.0编写,无壳:
004.png
第一步、爆破程序:
用OD加载程序,用“中文搜索引擎”的智能搜索功能,找到了如下字符串:
005.png
这次有两个地方要爆破,一个是用户名输入时的限制,一个是爆破注册码:
很容易知道00401582处是用户名长度限制,00401669处是注册成功的提示,那么先双击00401582地址,回到CPU窗口:
随意看了一下代码,很容易就找到了关键跳等信息:
00401579处地址跳过了用户名长度的限制,jge直接改成jmp:
[Asm] 纯文本查看 复制代码
00401572  |.  8945 E4       mov [local.7],eax
00401575  |.  837D E4 05    cmp [local.7],0x5
00401579  |.  7D 43         jge short Brad_Sob.004015BE
0040157B  |.  6A 40         push 0x40
0040157D  |.  68 20404000   push Brad_Sob.00404020                   ;  CrackMe
00401582  |.  68 28404000   push Brad_Sob.00404028                   ;  User Name must have at least 5 characters.
............
004015BE  |>  C745 E0 00000>mov [local.8],0x0

007.png
006.png
先保存成可执行文件Brad Soblesky.2-user.nop.exe,试运行一下,不管输不输入,输入什么都不再限制了;
再向下找到00401669处,注册成功的提示,向上查看,到00401642处,命令是jnz Brad_Sob.00401747,跳过成功,走向失败,将这一句nop掉:
[Asm] 纯文本查看 复制代码
00401640          |.  85C0                     test eax,eax                                           ;  Brad_Sob.00403430
00401642              0F85 FF000000            jnz Brad_Sob.00401747                                  ;  跳过成功,走向失败


将所有修改保存为可执行文件Brad Soblesky.2-user-Serial.nop.exe,运行Brad Soblesky.2-user-Serial.nop.exe,直接点击“Check“按钮,弹出成功,说明用户名长度限制与注册码都爆破了。

第二步、追注册码:
接下来找注册码,可以先向上翻到“Check”按钮事件的代码段首004014DF处下断,这次我是直接在004015BE处(过了用户名长度限制)下断:
Ctrl+F2键返回程序开始(将刚才修改的两个爆破处还原),
F9运行程序,
输入用户名“52pojie”,注册码“123450”,点击“Check”按钮,程序中断于004015BE处:
查看了一下寄存器窗口,看到EBP-18存入假码,EBP-14存入用户名;
008.png
F8单步向下,从004015BE到0040161A之间是生成注册码的代码段,头疼的是一大堆的逻辑与运算、有符号数乘法、异或运算,心里就发怵。
[Asm] 纯文本查看 复制代码
004015BE    |> \C745 E0 >mov [local.8],0x0                         ;  此时eax=用户名长度,[local.8]首次为0,以后每次+1
004015C5    |.  EB 09    jmp short Brad_Sob.004015D0
004015C7    |>  8B55 E0  /mov edx,[local.8]                        ;  edx=[local.8];循环开始,edx开始取值?
004015CA    |.  83C2 01  |add edx,0x1                              ;  edx=edx+1
004015CD    |.  8955 E0  |mov [local.8],edx                        ;  [local.8]=edx
004015D0    |>  8B45 E0   mov eax,[local.8]                        ;  eax=[local.8];第一次从上面跳过来,第二次从循环中来
004015D3    |.  3B45 E4  |cmp eax,[local.7]                        ;  eax与长度比较:[local.7]=len(user)
004015D6    |.  7D 42    |jge short Brad_Sob.0040161A              ;  eax>=len(user)时跳,即循环了用户名长度次数后跳
004015D8    |.  8B4D E0  |mov ecx,[local.8]
004015DB    |.  51       |push ecx
004015DC    |.  8D4D EC  |lea ecx,[local.5]                        ;  ecx=用户名 [local.5]=[ebp-0x14]=user
004015DF    |.  E8 1C030>|call <Brad_Sob.ASC(Strings(n))>          ;  al=asc(user(n))
004015E4    |.  0FBED0   |movsx edx,al                             ;  edx=al=ASC(user(n));n为每次循环的当次序数
004015E7    |.  8B45 F0  |mov eax,[local.4]                        ;  [local.4]=[ebp-10],第一次循环前值为0x81276345,固定值
004015EA    |.  03C2     |add eax,edx                              ;  eax=eax+edx(16进制)
004015EC    |.  8945 F0  |mov [local.4],eax                        ;  [local.4]=[local.4]+hex(asc(user(n)))
004015EF    |.  8B4D E0  |mov ecx,[local.8]                        ;  ecx=[local.8]([ebp-20]),ecx(当前循环次数(从0开始))=n
004015F2    |.  C1E1 08  |shl ecx,0x8                              ;  ecx左移8位:ecx=ecx*(2^8)(10进制的算法)
004015F5    |.  8B55 F0  |mov edx,[local.4]
004015F8    |.  33D1     |xor edx,ecx                              ;  按位'异或'运算,结果送至edx中
004015FA    |.  8955 F0  |mov [local.4],edx                        ;   [local.4] = [local.4] xor [local.8]
004015FD    |.  8B45 E0  |mov eax,[local.8]
00401600    |.  83C0 01  |add eax,0x1                              ;  循环次数+1:n=n+1
00401603    |.  8B4D E4  |mov ecx,[local.7]                        ;  [local.7]=len(user)
00401606    |.  0FAF4D E>|imul ecx,[local.8]                       ;  ecx=[local.7]*[local.8]=len(user)*(n+1)
0040160A    |.  F7D1     |not ecx                                  ;  对ecx按位求反运算(即0变1,1变0),结果返回ecx?
0040160C    |.  0FAFC1   |imul eax,ecx                             ;  eax=eax*ecx=(n+1)*(not ecx)????
0040160F    |.  8B55 F0  |mov edx,[local.4]
00401612    |.  0FAFD0   |imul edx,eax                             ;  edx=edx*eax=[local.4]*{(n+1)*[not 【len(user)】*n])????
00401615    |.  8955 F0  |mov [local.4],edx                        ;  [ebp-0x10]存入以上结果(即注册码)
00401618    |.^ EB AD    \jmp short Brad_Sob.004015C7
0040161A    |>  8B45 F0  mov eax,[local.4]                         ;  循环运算后得到注册码

运行到004015F2处,命令是shl ecx,0x8,意思是ecx里的数逻辑左移8位?ecx=0,执行命令后,寄存器窗口中ECX 为0不变,下面的标志位中P、A、Z均变成了1,S变成了0;
Shl命令给我难住了,不知道该如何进行下去。再向下看,Not命令后的乘法又不会了!什么意思嘛!从网上疯狂地搜索,搞明白了shl和not这两个命令,基本上ecx=shl ecx,0x8是说ecx中的10进制数值*2的N次方再存入ecx中,Not命令后的结果是10进制数4294967296减去寄存器中的10进制值:
再向下基本上算法出来了:
Result = 0x81276345
For n=0 to len(user)-1
Result = Result + Hex(asc(user(n)    ’
Result = Result xor (n shl,0x8)
Result = (n+1) * (not len(user) * n) * Result
Next n
循环7次后,得到注册码,继续向下,对得到的数值进行格式化,是无符号数格式:
[Asm] 纯文本查看 复制代码
0040161D    |.  50       push eax
0040161E    |.  68 54404>push Brad_Sob.00404054                    ;  %lu  无符号数格式
00401623    |.  8D4D DC  lea ecx,[local.9]                         ;  [local.9]=[ebp-24]:存入计算出的注册码
00401626    |.  51       push ecx
00401627    |.  E8 52070>call <jmp.&MFC42.#CString::Format_2818>   ;  可能是字符串格式函数,ecx=真码
0040162C    |.  83C4 0C  add esp,0xC
0040162F    |.  8D4D DC  lea ecx,[local.9]
00401632    |.  E8 79020>call Brad_Sob.004018B0                    ;  eax=真码,经格式化转变后得到

到0040162C处运行后寄存器窗口中数值如下,感觉“3186769159”这一串数字就是注册码了:试着往程序019中输入,成功了,说明感觉是正确的。
010.png
继续到0040163B处,调用检测代码段进行计算:
[Asm] 纯文本查看 复制代码
00401637    |.  50       push eax
00401638    |.  8D4D E8  lea ecx,[local.6]                         ;  [local.6]=[ebp-18]:存入的假码
0040163B    |.  E8 80020>call <Brad_Sob.IsTrue(Sn)>                ;  应该是检测注册码真假,存入eax中
00401640    |.  85C0     test eax,eax
00401642        0F85 FF0>jnz Brad_Sob.00401747                     ;  跳过成功,走向失败

到这里,信心满满啊,这个程序也不复杂嘛!开始编写注册机,由于自己不会C语言,仍用VB进行,就在这一步卡了一个多星期!!!
注册算法正确,可是第一次循环过程中,Result+asc(user(n)就开始出错,开始了漫漫的调试修改之路。程序一运行,就是提示6号数值溢出错误,于是将Result定义为双精度型,继续运行,仍然超出了范围!从网上搜索了大量的资料,基本上都是C++及其他语言的,极少有VB的!自己按说明将大数定义为字符,反反复复地修改,几乎要崩溃了!后来,后来,借网上几个大数运算的函数套了进去,然后运行,仍是错误重重,不是首位多了空格,就是结果少了1位,等等。
现在的注册机虽然写出来了,但肯定也会有数据溢出的问题存在,只是精力不足,只能留待以后学习完善,更盼望大神指导!

附件,含CM原程序、爆破后的程序及019注册机。百度链接是:http://pan.baidu.com/s/1skMkJY9密码: 86pm,160个CM、我已练习过的前19个crackme程序(不含012)都在里面。

免费评分

参与人数 4威望 +1 吾爱币 +10 热心值 +4 收起 理由
Hmily + 1 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
1.008 + 1 + 1 我很赞同!
zys_ + 1 + 1 用心讨论,共获提升!
WYWZ + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 海天一色001 发表于 2019-4-22 15:19
鬼手56 发表于 2019-4-22 09:42
这个程序用IDA的话注册机算法直接就能抠出来

感谢你的指导!
不过我现在正处于初学阶段,语言只学了点VB,连C都不会;反编译工具很多,现在也只是会用了有限的几个,IDA打开过,基本不懂!
其实更重要的,是基础太差,汇编指令都需要在用到时猛查,数据的存储更是迷糊,这次大数计算时才算是深入学习了一下原码、反码和补码,真的感觉学习的任务很重,盼望大神给我多指点啊!
小城微风 发表于 2019-4-22 09:39
鬼手56 发表于 2019-4-22 09:42
这个程序用IDA的话注册机算法直接就能抠出来

免费评分

参与人数 1热心值 +1 收起 理由
KaQqi + 1 666

查看全部评分

newchange452pj 发表于 2019-4-22 10:10
谢谢分享
shelly1314 发表于 2019-4-22 12:39
感谢楼主分享
lshfyq 发表于 2019-4-22 13:47

谢谢大佬的分享
rickw 发表于 2019-4-22 14:18
19/160,进步呀。
networkbox 发表于 2019-4-22 17:07
同新手,一起学习,共同进步
li4ming 发表于 2019-4-22 20:18
共同进步、加油
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 03:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表