首页
社区
课程
招聘
[原创]刚写的一个crackme. 新手可以试试(求一个邀请码)
发表于: 2010-3-21 13:44 5975

[原创]刚写的一个crackme. 新手可以试试(求一个邀请码)

2010-3-21 13:44
5975
比较简单的一个crackme.新手可以试试.附件已上传.网盘地址还是留着.临时用户可以用这个链接下载.



网盘链接:
http://www.rayfile.com/files/6a13b47a-34ac-11df-ae9b-0015c55db73d/

引用上iEXE 同学的解法, 还差一小步就完成了完美的算法破解.

用 OD 载入
跟踪到验证部分:

引用:
00401480   .  81EC C8000000 SUB ESP,0C8                            ;  分配局部变量
00401486   .  8D4424 64     LEA EAX,DWORD PTR SS:[ESP+64]          ;  取SN缓冲区(局部变量)地址
0040148A   .  56            PUSH ESI                               ;  保存寄存器
0040148B   .  57            PUSH EDI                               ;  。。。
0040148C   .  6A 64         PUSH 64                                ;  缓冲区长度
0040148E   .  50            PUSH EAX                               ;  。。。
0040148F   .  8BF1          MOV ESI,ECX
00401491   .  68 EA030000   PUSH 3EA
00401496   .  E8 E3020000   CALL <JMP.&MFC42.#3098_?GetDlgItemText>;  获取SN至局部变量
0040149B   .  8D4C24 08     LEA ECX,DWORD PTR SS:[ESP+8]           ;  用户名的缓冲区(局部变量)地址
0040149F   .  6A 64         PUSH 64
004014A1   .  51            PUSH ECX
004014A2   .  68 E9030000   PUSH 3E9
004014A7   .  8BCE          MOV ECX,ESI
004014A9   .  E8 D0020000   CALL <JMP.&MFC42.#3098_?GetDlgItemText>;  获取用户名
004014AE   .  8D7C24 6C     LEA EDI,DWORD PTR SS:[ESP+6C]
004014B2   .  83C9 FF       OR ECX,FFFFFFFF                        ;  下面计算用户名字串长度
004014B5   .  33C0          XOR EAX,EAX
004014B7   .  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]
004014B9   .  F7D1          NOT ECX
004014BB   .  49            DEC ECX
004014BC   .  83F9 06       CMP ECX,6                              ;  用户名长度 > 6 跳到 继续验证
004014BF   .  73 23         JNB SHORT crackme1.004014E4            ;  不小于则跳过头部验证
004014C1   .  807C24 6C 61  CMP BYTE PTR SS:[ESP+6C],61            ;  头部验证;第一个字符是‘a’?
004014C6   .  74 1C         JE SHORT crackme1.004014E4             ;  是则跳到继续处理
004014C8   .  6A 00         PUSH 0
004014CA   .  68 7C304000   PUSH crackme1.0040307C                 ;  wrong name
004014CF   .  68 64304000   PUSH crackme1.00403064                 ;  wrong name, try again
004014D4   .  8BCE          MOV ECX,ESI
004014D6   .  E8 9D020000   CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
004014DB   .  5F            POP EDI
004014DC   .  5E            POP ESI
004014DD   .  81C4 C8000000 ADD ESP,0C8
004014E3   .  C3            RETN
004014E4   >  8B3D AC214000 MOV EDI,DWORD PTR DS:[<&MSVCRT.atoi>]  ;  继续验证;验证SN
004014EA   .  8D5424 08     LEA EDX,DWORD PTR SS:[ESP+8]           ;  取序列号至 EDX(atoi() 实参)
004014EE   .  52            PUSH EDX                               ; /s
004014EF   .  FFD7          CALL EDI                               ; \atoi
004014F1   .  83C4 04       ADD ESP,4                              ;  平衡堆栈
004014F4   .  85C0          TEST EAX,EAX                           ;  判断 atoi(假码) 的返回值
004014F6   .  74 4A         JE SHORT crackme1.00401542             ;  为 0 则 跳到 “wrong serial number...”
004014F8   .  8D4424 08     LEA EAX,DWORD PTR SS:[ESP+8]           ;  取假码
004014FC   .  50            PUSH EAX                               ;  又执行了一遍 atoi()
004014FD   .  FFD7          CALL EDI
004014FF   .  8BD0          MOV EDX,EAX                            ;  保存返回值 至 EDX
00401501   .  8D7C24 0C     LEA EDI,DWORD PTR SS:[ESP+C]           ;  假码地址入 EDI
00401505   .  83C9 FF       OR ECX,FFFFFFFF                        ;  计算长度
00401508   .  33C0          XOR EAX,EAX
0040150A   .  83C4 04       ADD ESP,4
0040150D   .  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]
0040150F   .  F7D1          NOT ECX
00401511   .  49            DEC ECX
00401512   .  83F9 0A       CMP ECX,0A                             ;  序列号长度 与 10 比较
00401515   .  75 2B         JNZ SHORT crackme1.00401542            ;  不等则跳 “wrong serial number...”
00401517   .  81E2 07000080 AND EDX,80000007                       ;  转换之后的数值 & 80000007
0040151D   .  79 05         JNS SHORT crackme1.00401524            ;  非负转移;否则跳到“wrong serial...”
0040151F   .  4A            DEC EDX                                ;  -1
00401520   .  83CA F8       OR EDX,FFFFFFF8                        ;  高29位置位
00401523   .  42            INC EDX                                ;  +1
00401524   >  75 1C         JNZ SHORT crackme1.00401542            ;  不为 0
00401526   .  6A 00         PUSH 0
00401528   .  68 5C304000   PUSH crackme1.0040305C                 ;  correct
0040152D   .  68 50304000   PUSH crackme1.00403050                 ;  correct ^_^
00401532   .  8BCE          MOV ECX,ESI
00401534   .  E8 3F020000   CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
00401539   .  5F            POP EDI
0040153A   .  5E            POP ESI
0040153B   .  81C4 C8000000 ADD ESP,0C8
00401541   .  C3            RETN
00401542   >  6A 00         PUSH 0
00401544   .  68 40304000   PUSH crackme1.00403040                 ;  wrong serial
00401549   .  68 20304000   PUSH crackme1.00403020                 ;  wrong serial number, try again
0040154E   .  8BCE          MOV ECX,ESI
00401550   .  E8 23020000   CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
00401555   .  5F            POP EDI
00401556   .  5E            POP ESI
00401557   .  81C4 C8000000 ADD ESP,0C8
0040155D   .  C3            RETN

综上分析,我写了个注册机:

引用:
// CrackMe1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "stdlib.h"
using namespace std;
//
//该函数验证输入的SN是否合法
//返回 TRUE:合法
int __fastcall CheckSN(char *sn)
{
  long t;
  t = atoi(sn);
  __asm
  {
    mov edx,t
    and edx,0x80000007
    jns err
    dec edx
    or edx,0xfffffff8
    inc edx
    jnz err
  }

  return TRUE;
err:
  return FALSE;
}
//
//Main
int _tmain(int argc, _TCHAR* argv[])
{
  char sn[11]={0};
  long h = -9, l = 0;

  cout<<"If the lenght of your name greater then 5 and less then 64,please make it by youself."<<endl;
  cout<<"Otherwise please use 'a' in head of the string."<<endl;
  //穷举法,似乎效率不高
  cout<<"The possible serial number:\n";
  //生成假SN
  while(TRUE)
  {
    l ++;
    if (l == 0x7FFFFFFF)
    {
      cout<<sn<<endl;
      system("pause");
      h ++;
      l = 0;
      if (h == 0x100)
        break;
    }
    wsprintf(sn,"%02d%08ld",h,l);
    if (CheckSN(sn))
    {
      cout<<sn<<endl;
      system("pause");
    }
  }

  return 0;
}

//以上代码在vcpp9.0中调试通过

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (18)
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
帮你顶一下
2010-3-21 14:03
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这是看雪的限制是为了论坛的优化
2010-3-21 17:40
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
偶简单分析了一下
用 OD 载入
跟踪到验证部分:
00401480 . 81EC C8000000 SUB ESP,0C8 ; 分配局部变量
00401486 . 8D4424 64 LEA EAX,DWORD PTR SS:[ESP+64] ; 取SN缓冲区(局部变量)地址
0040148A . 56 PUSH ESI ; 保存寄存器
0040148B . 57 PUSH EDI ; 。。。
0040148C . 6A 64 PUSH 64 ; 缓冲区长度
0040148E . 50 PUSH EAX ; 。。。
0040148F . 8BF1 MOV ESI,ECX
00401491 . 68 EA030000 PUSH 3EA
00401496 . E8 E3020000 CALL <JMP.&MFC42.#3098_?GetDlgItemText>; 获取SN至局部变量
0040149B . 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8] ; 用户名的缓冲区(局部变量)地址
0040149F . 6A 64 PUSH 64
004014A1 . 51 PUSH ECX
004014A2 . 68 E9030000 PUSH 3E9
004014A7 . 8BCE MOV ECX,ESI
004014A9 . E8 D0020000 CALL <JMP.&MFC42.#3098_?GetDlgItemText>; 获取用户名
004014AE . 8D7C24 6C LEA EDI,DWORD PTR SS:[ESP+6C]
004014B2 . 83C9 FF OR ECX,FFFFFFFF ; 下面计算用户名字串长度
004014B5 . 33C0 XOR EAX,EAX
004014B7 . F2:AE REPNE SCAS BYTE PTR ES:[EDI]
004014B9 . F7D1 NOT ECX
004014BB . 49 DEC ECX
004014BC . 83F9 06 CMP ECX,6 ; 用户名长度 > 6 跳到 继续验证
004014BF . 73 23 JNB SHORT crackme1.004014E4 ; 不小于则跳过头部验证
004014C1 . 807C24 6C 61 CMP BYTE PTR SS:[ESP+6C],61 ; 头部验证;第一个字符是‘a’?
004014C6 . 74 1C JE SHORT crackme1.004014E4 ; 是则跳到继续处理
004014C8 . 6A 00 PUSH 0
004014CA . 68 7C304000 PUSH crackme1.0040307C ; wrong name
004014CF . 68 64304000 PUSH crackme1.00403064 ; wrong name, try again
004014D4 . 8BCE MOV ECX,ESI
004014D6 . E8 9D020000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
004014DB . 5F POP EDI
004014DC . 5E POP ESI
004014DD . 81C4 C8000000 ADD ESP,0C8
004014E3 . C3 RETN
004014E4 > 8B3D AC214000 MOV EDI,DWORD PTR DS:[<&MSVCRT.atoi>] ; 继续验证;验证SN
004014EA . 8D5424 08 LEA EDX,DWORD PTR SS:[ESP+8] ; 取序列号至 EDX(atoi() 实参)
004014EE . 52 PUSH EDX ; /s
004014EF . FFD7 CALL EDI ; \atoi
004014F1 . 83C4 04 ADD ESP,4 ; 平衡堆栈
004014F4 . 85C0 TEST EAX,EAX ; 判断 atoi(假码) 的返回值
004014F6 . 74 4A JE SHORT crackme1.00401542 ; 为 0 则 跳到 “wrong serial number...”
004014F8 . 8D4424 08 LEA EAX,DWORD PTR SS:[ESP+8] ; 取假码
004014FC . 50 PUSH EAX ; 又执行了一遍 atoi()
004014FD . FFD7 CALL EDI
004014FF . 8BD0 MOV EDX,EAX ; 保存返回值 至 EDX
00401501 . 8D7C24 0C LEA EDI,DWORD PTR SS:[ESP+C] ; 假码地址入 EDI
00401505 . 83C9 FF OR ECX,FFFFFFFF ; 计算长度
00401508 . 33C0 XOR EAX,EAX
0040150A . 83C4 04 ADD ESP,4
0040150D . F2:AE REPNE SCAS BYTE PTR ES:[EDI]
0040150F . F7D1 NOT ECX
00401511 . 49 DEC ECX
00401512 . 83F9 0A CMP ECX,0A ; 序列号长度 与 10 比较
00401515 . 75 2B JNZ SHORT crackme1.00401542 ; 不等则跳 “wrong serial number...”
00401517 . 81E2 07000080 AND EDX,80000007 ; 转换之后的数值 & 80000007
0040151D . 79 05 JNS SHORT crackme1.00401524 ; 非负转移;否则跳到“wrong serial...”
0040151F . 4A DEC EDX ; -1
00401520 . 83CA F8 OR EDX,FFFFFFF8 ; 高29位置位
00401523 . 42 INC EDX ; +1
00401524 > 75 1C JNZ SHORT crackme1.00401542 ; 不为 0
00401526 . 6A 00 PUSH 0
00401528 . 68 5C304000 PUSH crackme1.0040305C ; correct
0040152D . 68 50304000 PUSH crackme1.00403050 ; correct ^_^
00401532 . 8BCE MOV ECX,ESI
00401534 . E8 3F020000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
00401539 . 5F POP EDI
0040153A . 5E POP ESI
0040153B . 81C4 C8000000 ADD ESP,0C8
00401541 . C3 RETN
00401542 > 6A 00 PUSH 0
00401544 . 68 40304000 PUSH crackme1.00403040 ; wrong serial
00401549 . 68 20304000 PUSH crackme1.00403020 ; wrong serial number, try again
0040154E . 8BCE MOV ECX,ESI
00401550 . E8 23020000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CW>
00401555 . 5F POP EDI
00401556 . 5E POP ESI
00401557 . 81C4 C8000000 ADD ESP,0C8
0040155D . C3 RETN



综上分析,我写了个注册机:
// CrackMe1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "stdlib.h"
using namespace std;
//
//该函数验证输入的SN是否合法
//返回 TRUE:合法
int __fastcall CheckSN(char *sn)
{
long t;
t = atoi(sn);
__asm
{
mov edx,t
and edx,0x80000007
jns err
dec edx
or edx,0xfffffff8
inc edx
jnz err
}

return TRUE;
err:
return FALSE;
}
//
//Main
int _tmain(int argc, _TCHAR* argv[])
{
char sn[11]={0};
long h = -9, l = 0;

cout<<"If the lenght of your name greater then 5 and less then 64,please make it by youself."<<endl;
cout<<"Otherwise please use 'a' in head of the string."<<endl;
//穷举法,似乎效率不高
cout<<"The possible serial number:\n";
//生成假SN
while(TRUE)
{
l ++;
if (l == 0x7FFFFFFF)
{
cout<<sn<<endl;
system("pause");
h ++;
l = 0;
if (h == 0x100)
break;
}
wsprintf(sn,"%02d%08ld",h,l);
if (CheckSN(sn))
{
cout<<sn<<endl;
system("pause");
}
}

return 0;
}

//以上代码在vcpp9.0中调试通过

还望高手多多指点
2010-3-21 19:39
0
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
楼上的90%都答对了..就差一个算法没解出来.可以再仔细看看代码.应该比较简单可以看出来.
2010-3-21 23:24
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
写的不错  我就不下了  哈哈
2010-3-22 00:22
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
可惜要钱啊,我就不下了
2010-3-22 08:54
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
俺是懒人、把源码发给我啊
2010-3-22 09:40
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
不知道这个是不是巧合?

不过我懒人一个,习惯暴力破解~
提供一个附件外链
附件外链地址
crack目录
上传的附件:
2010-3-22 12:58
0
雪    币: 236
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
我已经没钱下载了。
2010-3-22 13:37
0
雪    币: 75
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
啊哦
序列号是 8 的 倍数就可以了啊
2010-3-22 16:45
0
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
fdddddddddddddddddddd
2010-3-24 18:55
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
14
name:a
serial:2147483656

name根本没有参与到计算,不知道这个name有什么用
2010-3-25 00:31
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
15
name必须长于6位,或者首字母为a也可以

name和serial是没关系的

serial为1000000000到4294967288之间任意一个能被8整除的数
下面是生成serial的算法

#include "stdafx.h"
int main(int argc, char* argv[])
{
unsigned long p=1000000000;
while(p<=4294967288)
{
printf("%lu\n",p);
p+=8;
}
return 0;
}

谢谢gbbs的提醒,后来想想只需要保证serial的二进制最低3位为0就好
所以从1000000000开始
比4294967288大也是可以的,不过overflow了,没必要

刚才发现0000000008开始也可以
2010-3-25 00:51
0
雪    币: 15
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
都是强人阿,~~`
2010-3-25 07:32
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
为啥要从2147483656开始?1000000000开始不也是可以的吗
貌似只要是十位数是8的整数倍就可以的
2010-3-25 11:09
0
雪    币: 435
活跃值: (1282)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
18
哦对,大意了
谢谢更正
2010-3-25 11:52
0
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
呵呵,这个号啊,我下一个试试啊
2010-3-25 22:12
0
雪    币: 208
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
学习中
2010-3-25 22:22
0
游客
登录 | 注册 方可回帖
返回
//