首页
社区
课程
招聘
[原创]新手再来CrackMe 爆破+注册机
发表于: 2014-5-4 17:20 9206

[原创]新手再来CrackMe 爆破+注册机

2014-5-4 17:20
9206

/*
 *   CrackMe 下载链接 : http://bbs.pediy.com/upload/files/1084801702.zip
 *   源码类型 :  VC6 project files
 *   使用工具 :  Ollydbg
 *   作者: 木瓜枫叶(block)
 */

 小弟新手,逆向接触的晚,目前正是学习阶段,为了提高,正准备将论坛上的一些CrackMe 都翻出来,然后写一下注册机。
还是先从爆破开始,然后再说一下算法的逆向
开始:
一、爆破
爆破比较简单,直接一下搞定。

定位方法,随便输入UserName和key ,会提示fail,右键查找参考字串。
定位到提示部分,一目了然。
直接 00401069 EAX置0 就爆了。

Code:
00401069   .  85C0          TEST EAX,EAX                             ;  爆破点 EAX置0就OK
0040106B   .  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
0040106D   .  68 80504000   PUSH ncrackme.00405080                   ; |ncrackme
00401072   .  75 1B         JNZ SHORT ncrackme.0040108F              ; |
00401074   .  A1 B8564000   MOV EAX,DWORD PTR DS:[4056B8]            ; |
00401079   .  68 64504000   PUSH ncrackme.00405064                   ; |Registration successful.
0040107E   .  50            PUSH EAX                                 ; |hOwner => 000901F2 ('Newbie smallsize crackme - 

v1',class='myWindowClass')
0040107F   .  FF15 C0404000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
00401085   .  E8 A6020000   CALL ncrackme.00401330
0040108A   .  33C0          XOR EAX,EAX
0040108C   .  C2 1000       RETN 10
0040108F   >  8B0D B8564000 MOV ECX,DWORD PTR DS:[4056B8]            ; |
00401095   .  68 50504000   PUSH ncrackme.00405050                   ; |Registration fail.
0040109A   .  51            PUSH ECX                                 ; |hOwner => 000901F2 ('Newbie smallsize crackme - 

v1',class='myWindowClass')
0040109B   .  FF15 C0404000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA
004010A1   .  33C0          XOR EAX,EAX
004010A3   .  C2 1000       RETN 10

二、算法逆向

步骤
第一步:先根据用户名的前两个字节,相除取得余数,然后与第三个字节相乘后再加1.
作为第一个运算的基数,将基数放入全局变量。
第二步:根据上面计算得出的值,在运算15次。运算代码如下,
0040134A  /$  A1 AC504000   MOV EAX,DWORD PTR DS:[4050AC]
0040134F  |.  69C0 FD430300 IMUL EAX,EAX,343FD
00401355  |.  05 C39E2600   ADD EAX,269EC3
0040135A  |.  A3 AC504000   MOV DWORD PTR DS:[4050AC],EAX
0040135F  |.  C1F8 10       SAR EAX,10
00401362  |.  25 FF7F0000   AND EAX,7FFF
00401367  \.  C3            RETN

将结果再次放入全局变量。

上面再次作为第三次也就是真正计算key 运算的基数。

第三步: 循环UserName 每个字符,然后计算一下运算的次数。循环运算。
然后 与ECX (0x1a) 相除取得余数。就是key 的字符。
具体分析如下,

算法分析

00401230  /$  8B0D BC564000 MOV ECX,DWORD PTR DS:[4056BC]                        ;  控件句柄
00401236  |.  83EC 30       SUB ESP,30
00401239  |.  8D4424 00     LEA EAX,DWORD PTR SS:[ESP]
0040123D  |.  53            PUSH EBX                                             ;  取用户名文本框
0040123E  |.  56            PUSH ESI
0040123F  |.  8B35 94404000 MOV ESI,DWORD PTR DS:[<&USER32.GetDlgItemTextA>]     ;  USER32.GetDlgItemTextA
00401245  |.  6A 10         PUSH 10                                              ; /Count = 10 (16.)
00401247  |.  50            PUSH EAX                                             ; |Buffer
00401248  |.  68 E8030000   PUSH 3E8                                             ; |ControlID = 3E8 (1000.)
0040124D  |.  51            PUSH ECX                                             ; |hWnd => 000701F4 

(class='#32770',parent=000901F2)
0040124E  |.  33DB          XOR EBX,EBX                                          ; |
00401250  |.  FFD6          CALL ESI                                             ; \GetDlgItemTextA
00401252  |.  83F8 03       CMP EAX,3                                            ;  比较用户名长度是否小于3
00401255  |.  73 0B         JNB SHORT ncrackme.00401262
00401257  |.  5E            POP ESI
00401258  |.  B8 01000000   MOV EAX,1
0040125D  |.  5B            POP EBX
0040125E  |.  83C4 30       ADD ESP,30
00401261  |.  C3            RETN
00401262  |>  A1 BC564000   MOV EAX,DWORD PTR DS:[4056BC]                        ;  控件句柄
00401267  |.  8D5424 28     LEA EDX,DWORD PTR SS:[ESP+28]
0040126B  |.  6A 10         PUSH 10
0040126D  |.  52            PUSH EDX
0040126E  |.  68 E9030000   PUSH 3E9
00401273  |.  50            PUSH EAX
00401274  |.  FFD6          CALL ESI                                             ;  key
00401276  |.  0FBE4424 08   MOVSX EAX,BYTE PTR SS:[ESP+8]            ;  获取用户名第一个字符
0040127B  |.  0FBE4C24 09   MOVSX ECX,BYTE PTR SS:[ESP+9]            ;  获取用户名第二个字符
00401280  |.  99            CDQ                                      ;  相除运算
00401281  |.  F7F9          IDIV ECX                                 ;  EAX%ECX 将结果放入到EDX中
00401283  |.  8BCA          MOV ECX,EDX                              ;  将结果赋值给ECX
00401285  |.  83C8 FF       OR EAX,FFFFFFFF                          ;  EAX=-1
00401288  |.  0FBE5424 0A   MOVSX EDX,BYTE PTR SS:[ESP+A]            ;  获取用户名第三个字符
0040128D  |.  0FAFCA        IMUL ECX,EDX                             ;  将上次取得余数与第三个字符相乘 结果放入到ECX
00401290  |.  41            INC ECX                                  ;  ECX++
00401291  |.  33D2          XOR EDX,EDX                              ;  EDX=0
00401293  |.  F7F1          DIV ECX                                  ;  EAX%ECX将商放入到EAX
00401295  |.  50            PUSH EAX                                 ;  EAX 是运算key 第一步基数
00401296  |.  E8 A5000000   CALL ncrackme.00401340                   ;  将eax 放入全局变量保存
0040129B  |.  83C4 04       ADD ESP,4
0040129E  |.  33F6          XOR ESI,ESI                              ;  esi=0
004012A0  |>  E8 A5000000   /CALL ncrackme.0040134A                  ;  此循环运算15次,具体运算在 0040134A 内部
/*
  0040134A 内部CODE:
  0040134A  /$  A1 AC504000   MOV EAX,DWORD PTR DS:[4050AC]
  0040134F  |.  69C0 FD430300 IMUL EAX,EAX,343FD
  00401355  |.  05 C39E2600   ADD EAX,269EC3
  0040135A  |.  A3 AC504000   MOV DWORD PTR DS:[4050AC],EAX
  0040135F  |.  C1F8 10       SAR EAX,10
  00401362  |.  25 FF7F0000   AND EAX,7FFF
  00401367  \.  C3            RETN
*/

004012A5  |.  99            |CDQ
004012A6  |.  B9 1A000000   |MOV ECX,1A
004012AB  |.  F7F9          |IDIV ECX
004012AD  |.  80C2 41       |ADD DL,41
004012B0  |.  885434 18     |MOV BYTE PTR SS:[ESP+ESI+18],DL         ;  计算得到key 计算所需要的的字符串
004012B4  |.  46            |INC ESI
004012B5  |.  83FE 0F       |CMP ESI,0F                              ;  判断循环条件退出条件
004012B8  |.^ 72 E6         \JB SHORT ncrackme.004012A0
004012BA  |.  57            PUSH EDI                                 ;  最后将结果放入到全局变量
004012BB  |.  8D7C24 0C     LEA EDI,DWORD PTR SS:[ESP+C]
004012BF  |.  83C9 FF       OR ECX,FFFFFFFF
004012C2  |.  33C0          XOR EAX,EAX
004012C4  |.  33F6          XOR ESI,ESI
004012C6  |.  F2:AE         REPNE SCAS BYTE PTR ES:[EDI]             ;  计算用户名的长度
004012C8  |.  F7D1          NOT ECX
004012CA  |.  49            DEC ECX                                  ;  真正计算key 的运算
004012CB  |.  74 59         JE SHORT ncrackme.00401326
004012CD  |>  8A4434 0C     /MOV AL,BYTE PTR SS:[ESP+ESI+C]          ;  取出每一个字符
004012D1  |.  C0F8 05       |SAR AL,5                                ;  右移 5 位
004012D4  |.  0FBEC0        |MOVSX EAX,AL
004012D7  |.  8D1480        |LEA EDX,DWORD PTR DS:[EAX+EAX*4]
004012DA  |.  8D04D0        |LEA EAX,DWORD PTR DS:[EAX+EDX*8]
004012DD  |.  8D0440        |LEA EAX,DWORD PTR DS:[EAX+EAX*2]        ;  这四步是计算当前个字符串所要循环运算的次数
004012E0  |.  85C0          |TEST EAX,EAX
004012E2  |.  7E 0A         |JLE SHORT ncrackme.004012EE
004012E4  |.  8BF8          |MOV EDI,EAX                             ;  将次数存放到EDI,作为循环退出的条件
004012E6  |>  E8 5F000000   |/CALL ncrackme.0040134A                 ;  根据上面计算的结果的值。循环对应的次数运算
004012EB  |.  4F            ||DEC EDI
004012EC  |.^ 75 F8         |\JNZ SHORT ncrackme.004012E6
004012EE  |>  E8 57000000   |CALL ncrackme.0040134A                  ;  退出后在运算一次
004012F3  |.  99            |CDQ
004012F4  |.  B9 1A000000   |MOV ECX,1A                              ;  从这开始就是计算每个key字符的地方
004012F9  |.  8D7C24 0C     |LEA EDI,DWORD PTR SS:[ESP+C]
004012FD  |.  F7F9          |IDIV ECX                                ;  计算DL 要根据上面计算所得的EAX和ECX
004012FF  |.  0FBE4C34 2C   |MOVSX ECX,BYTE PTR SS:[ESP+ESI+2C]
00401304  |.  80C2 41       |ADD DL,41                               ;  DL + 0x41 目前就是key 的字符了
00401307  |.  0FBEC2        |MOVSX EAX,DL
0040130A  |.  2BC1          |SUB EAX,ECX
0040130C  |.  885434 1C     |MOV BYTE PTR SS:[ESP+ESI+1C],DL
00401310  |.  99            |CDQ
00401311  |.  33C2          |XOR EAX,EDX
00401313  |.  83C9 FF       |OR ECX,FFFFFFFF
00401316  |.  2BC2          |SUB EAX,EDX
00401318  |.  03D8          |ADD EBX,EAX
0040131A  |.  33C0          |XOR EAX,EAX
0040131C  |.  46            |INC ESI
0040131D  |.  F2:AE         |REPNE SCAS BYTE PTR ES:[EDI]            ;  计算用户名长度
0040131F  |.  F7D1          |NOT ECX
00401321  |.  49            |DEC ECX
00401322  |.  3BF1          |CMP ESI,ECX                             ;  循环退出的条件,根据用户名长度来计算
00401324  |.^ 72 A7         \JB SHORT ncrackme.004012CD
计算出来的:
asdfg23-YNMKBOX
asdfg-YNMKB

注册机代码:

int DefValue=0;
int _tmain(int argc, _TCHAR* argv[])
{
  char keyStr[6]={0};//这个长度根据用户名来,我这里写死了,注意修改
  char *UserName="asdfg";
  //1.先通过用户名算出运算基数
  int _EAX=0;
  int _ECX=0;
  int _EDX=0;
  _EAX=(int)(UserName[0]);
  _ECX=(int)(UserName[1]);
  _EDX=_EAX%_ECX;
  _ECX=_EDX;
  _EAX=-1;
  _EDX=(int)(UserName[2]);
  _ECX=_EDX*_ECX;
  _ECX++;
  _asm MOV EAX,-1;
  _asm MOV ECX,_ECX;
  _asm XOR EDX,EDX;
  _asm DIV ECX;
  _asm MOV _EAX,EAX;
  printf("_EAX=%x\r\n",_EAX);
  //将结果放入全局变量
  DefValue=_EAX;
  //2.开始循环计算15次
  int _ESI=0;
  do
  {
    _EAX=DefValue;
    _asm MOV EAX,_EAX;
    _asm IMUL EAX,EAX,0x343FD;
    _asm ADD EAX,0x269EC3;
    _asm MOV DefValue,EAX
    _asm SAR EAX,0x10
    _asm AND EAX,0x7FFF
    _ESI++;
  }while(_ESI<15);
  printf("DefValue=%x\r\n",DefValue);
  //3.开始真正的key运算
  int UserLength=strlen(UserName);
  int _EDI=0;
  for(int i=0;i<UserLength;i++)
  {
    int _DL=0;
    int _AL=(int)(UserName[i]);
    _asm XOR EAX,EAX;
    _asm MOV EAX,_AL;
    _asm SAR AL,5;
    _asm MOVSX EAX,AL;
    _asm LEA EDX,DWORD PTR DS:[EAX+EAX*4]
    _asm LEA EAX,DWORD PTR DS:[EAX+EDX*8]
    _asm LEA EAX,DWORD PTR DS:[EAX+EAX*2]
    _asm MOV _EDI,EAX;
    
    if(_EDI>0)
    {
      do
      {
        _EAX=DefValue;
        _asm MOV EAX,_EAX;
        _asm IMUL EAX,EAX,0x343FD;
        _asm ADD EAX,0x269EC3;
        _asm MOV DefValue,EAX
        _asm SAR EAX,0x10
        _asm AND EAX,0x7FFF
        _EDI--;
      }while(_EDI>0);
    }
    //这里还要来一次运算
    _EAX=DefValue;
    _asm MOV EAX,_EAX;
    _asm IMUL EAX,EAX,0x343FD;
    _asm ADD EAX,0x269EC3;
    _asm MOV DefValue,EAX;
    _asm SAR EAX,0x10;
    _asm AND EAX,0x7FFF;
    _asm MOV ECX,0x1A;
    _asm XOR EDX,EDX;
    _asm IDIV ECX;
    _asm ADD DL,0x41;
    _asm MOV _DL,EDX;
    keyStr[i]=_DL;
  }
  printf("keyStr=%s\r\n",keyStr);
  getchar();
  return 0;
}

代码写的不是很好,大家凑活看。


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 4
支持
分享
最新回复 (8)
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
支持,加油...
2014-5-4 17:22
0
雪    币: 459
活跃值: (398)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
谢谢 安于此生 大大
2014-5-4 17:28
0
雪    币: 341
活跃值: (143)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
4
也谢谢我撒
2014-5-4 19:39
0
雪    币: 459
活跃值: (398)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
必须
2014-5-4 19:53
0
雪    币: 2903
活跃值: (2839)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
将 jnz改为je也可以的,然后顺便输入就行了。

上传的附件:
2014-9-5 11:26
0
雪    币: 459
活跃值: (398)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
7
[QUOTE=xiwushgya;1314483]将 jnz改为je也可以的,然后顺便输入就行了。

[/QUOTE]

一、爆破
爆破比较简单,直接一下搞定。

定位方法,随便输入UserName和key ,会提示fail,右键查找参考字串。
定位到提示部分,一目了然。
直接 00401069 EAX置0 就爆了。
怎么弄法,太多了
2014-9-5 11:50
0
雪    币: 43
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
[QUOTE=xiwushgya;1314483]将 jnz改为je也可以的,然后顺便输入就行了。

[/QUOTE]

我觉得楼主主要是强调注册机的写法,其实学习破解,最高的追求是写注册机
而爆破是低级武功
2014-9-8 22:50
0
雪    币: 12
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
呵呵 这个彩蛋?
2014-9-11 23:19
0
游客
登录 | 注册 方可回帖
返回
//