首页
社区
课程
招聘
[原创]WAKU的第二个破文----Rith's CrackMe #1(非常简单)
2006-3-23 21:13 8419

[原创]WAKU的第二个破文----Rith's CrackMe #1(非常简单)

2006-3-23 21:13
8419
【文章标题】: WAKU的第二个破文----Rith's CrackMe #1(非常简单)
【文章作者】: WAKU
【作者邮箱】: wakuwakuwawaku@163.com
【作者主页】: www.rzz.cn
【下载地址】: 见附件
【使用工具】: PEID OD
--------------------------------------------------------------------------------
【详细过程】
      最近学习脱壳没什么进展,怕自己失去信心在<<加密与解密第二版>>中找了个CrackMe玩玩.
      用PEID查了一个,无壳,用VC6编写.
      用OD载入运行一下,是NAME/SERIAL型验证方式.乱输了一对,点Check It!.哦耶!没反应-_-!那我也看看有什么字符串,用
  "超级字串参考+"看了下,发现了congratulations!well done cracker!嘿嘿,出错不提示成功有提示也行~双击来到代码段,
  往上下都翻一翻,在一大段NOP指令和一个REN指令之间,就应该是验证注册码的函数代码了,WAKU把这段代码一段段粘上来,并
  加上详细注释:  (为了简洁, 注释中的>不是大于的意思,是把什么放到什么的意思)
  
  00401580   .  6A FF         PUSH -1
  00401582   .  68 B81B4000   PUSH Rith_Cra.00401BB8                   ;  SE 处理程序安装
  00401587   .  64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
  0040158D   .  50            PUSH EAX
  0040158E   .  64:8925 00000>MOV DWORD PTR FS:[0],ESP
  00401595   .  83EC 0C       SUB ESP,0C
  00401598   .  53            PUSH EBX
  00401599   .  55            PUSH EBP
  0040159A   .  56            PUSH ESI
  0040159B   .  8BF1          MOV ESI,ECX
  0040159D   .  57            PUSH EDI
  0040159E   .  68 48304000   PUSH Rith_Cra.00403048                   ;  31415926535897932384 这个字符串很可疑,好像是圆周率呢...
  004015A3   .  8D4C24 14     LEA ECX,DWORD PTR SS:[ESP+14]
  004015A7   .  897424 1C     MOV DWORD PTR SS:[ESP+1C],ESI
  004015AB   .  E8 FA020000   CALL <JMP.&MFC42.#537_??0CString@@QAE@PB>
  004015B0   .  6A 01         PUSH 1
  004015B2   .  8BCE          MOV ECX,ESI
  004015B4   .  C74424 28 000>MOV DWORD PTR SS:[ESP+28],0
  004015BC   .  E8 E3020000   CALL <JMP.&MFC42.#6334_?UpdateData@CWnd@>
  004015C1   .  8B7E 60       MOV EDI,DWORD PTR DS:[ESI+60]            ;  用户名 > EDI
  004015C4   .  8B5F F8       MOV EBX,DWORD PTR DS:[EDI-8]             ;  用户名长度 > EBX
  004015C7   .  83FB 05       CMP EBX,5
  004015CA   .  7C 7E         JL SHORT Rith_Cra.0040164A               ;  长度小于5就OVER
  004015CC   .  8B46 64       MOV EAX,DWORD PTR DS:[ESI+64]            ;  注册码 > EAX
  004015CF   .  894424 14     MOV DWORD PTR SS:[ESP+14],EAX
  004015D3   .  3958 F8       CMP DWORD PTR DS:[EAX-8],EBX             ;  注册码长度如果不和用户名长度相等,也OVER
  004015D6   .  75 72         JNZ SHORT Rith_Cra.0040164A
  004015D8   .  83FB 14       CMP EBX,14                               ;  注册码长度大于0x14也不行,事真多
  004015DB   .  7F 6D         JG SHORT Rith_Cra.0040164A
  004015DD   .  33C9          XOR ECX,ECX                              ;  ECX归0,为下面的循环做准备
  004015DF   .  85DB          TEST EBX,EBX
  004015E1   .  7E 54         JLE SHORT Rith_Cra.00401637              ;  如果注册码全验证成功则弹出正确提示
  004015E3   .  8B7424 10     MOV ESI,DWORD PTR SS:[ESP+10]            ;  把圆周率从栈中取出 > ESI(看执行结果才知道...)
  
      有人问了,你咋知道哪处内存放的就是用户名哪处内存就是注册码呢?嗯,光看代码俺也不知道,那你不会用F8走一次啊?OD
  提示信息那么丰富你不用干啥啊?
      还有个事,看着有类似CALL <JMP.&MFC42.#537_??0CString@@QAE@PB>这样的CALL没?这样的是调用MFC的函数,你别傻乎乎
  的跟进去了啊!
      嗯,恢复温柔语气.上面的代码呢基本就是判断用户名和注册的合法性,旁边的注释也是我调试好多次才写出来的.
      好,看下面的循环段码
  
  004015E7   > /8A040F        MOV AL,BYTE PTR DS:[EDI+ECX]             ;  依次取用户名的每位 > AL
  004015EA   . |0FBE2C31      MOVSX EBP,BYTE PTR DS:[ECX+ESI]          ;  取圆周率每一位 > EBP
  004015EE   . |0FBEC0        MOVSX EAX,AL                             ;  把AL扩展放到EAX中,看寄存器变化其实就是留下低字节,剩下的清0
  004015F1   . |99            CDQ                                      ;  CDQ?是什么意思?  查一下,原来是把EAX中的字的符号扩展到EDX中去
  004015F2   . |F7FD          IDIV EBP                                 ;  除法,EAX/EBP 商回送AX,余数回送DX
  004015F4   . |8BC2          MOV EAX,EDX                              ;  看来商没啥用,人家要的是余数
  004015F6   . |D1E0          SHL EAX,1                                ;  左移一位,相当于乘2
  
      如果你和俺一样对汇编指令不熟悉,身旁一定要有汇编指令参考之类的资料,遇到陌生的查一下.
      上面的指令就是把用户名第n位和圆周率字符串第n位求余,再乘2
  
  004015F8   .  83F8 7B       CMP EAX,7B
  004015FB   .  7E 03         JLE SHORT Rith_Cra.00401600
  004015FD   .  83E8 1A       SUB EAX,1A                               ;  如果大于z的ASCII码,减去1Ah,即26使其为小写字母
  00401600   >  83F8 41       CMP EAX,41                               ;  41是大写字母A
  00401603   .  7D 09         JGE SHORT Rith_Cra.0040160E
  00401605   .  BA 82000000   MOV EDX,82
  0040160A   .  2BD0          SUB EDX,EAX
  0040160C   .  8BC2          MOV EAX,EDX                              ;  如小于41则用82减,结果肯定是大于等于41,即为大写字母
  0040160E   >  83F8 5B       CMP EAX,5B                               ;  5B是[符号,在Z之后
  00401611   .  7E 12         JLE SHORT Rith_Cra.00401625              ;  和00401603一起判断是否为大写字母
  00401613   .  83F8 61       CMP EAX,61
  00401616   .  7D 0D         JGE SHORT Rith_Cra.00401625              ;  如果大于等于a则不用处理
  00401618   .  99            CDQ                                      ;  如果在Z和a之间,那么下面的处理让它成为数字!
  00401619   .  BD 0A000000   MOV EBP,0A
  0040161E   .  F7FD          IDIV EBP                                 ;  EAX除以10,余数放到DX中
  00401620   .  83C2 30       ADD EDX,30                               ;  加上30h,变成数字的ASCII值
  00401623   .  8BC2          MOV EAX,EDX                              ;  放回EAX中
  00401625   >  8B5424 14     MOV EDX,DWORD PTR SS:[ESP+14]            ;  注册码取出 > EDX
  00401629   .  38040A        CMP BYTE PTR DS:[EDX+ECX],AL             ;  把AL依次和注册码比,有一位不等就OVER  可知把用户名按照上面过程计算就

可得注册码
  0040162C   .  75 1C         JNZ SHORT Rith_Cra.0040164A              ;  有一位不等则死掉
  0040162E   .  41            INC ECX                                  ;  计算下一位
  0040162F   .  3BCB          CMP ECX,EBX
  00401631   .^ 7C B4         JL SHORT Rith_Cra.004015E7               ;  循环,直到ECX等于注册码的长度
  
      这段指令比较麻烦,来回跳转.你一定要查询每个16进制数所代表的字符(一般都是紧挨着A,Z,a,z),猜测作者的意图就是
  保证用户名每一次运算后得到的是常规字符(大小写字符,数字等).要多跟踪几次,输入不同的用户名测试流程,耐心一点肯定
  会弄明白这段代码的.
  
      总结一下,验证过程非常简单,只经过了一次计算就得出了注册码:
      1.取用户名每位和圆周率每位求余,然后乘2,设算出的字符ASCII值为c
      2.如果C > 'z',就减去0x1A(这么一减一般就是小写字母了)
      3.如果C < 'A',就用0x82减(这么一减一定就是大写字母了)
      4.如果c > 'A' 并且 c < 'a',就和10求余,然后加上0x30,成为数字
      5.循环步骤1到4,直到用户名都算完,得出的就是注册码了.
  
  下面给出C语言的注册机算法:
  
  #include <stdio.h>
  #include <string.h>
  
  int main()
  {
          char* PI = "31415926535897932384";
          char szUserName[80];
          int nLen;
          int i;
          char c;
  
          do
          {
                  printf("请输入用户名:");
                  scanf("%s", szUserName);
                  nLen = strlen(szUserName);
                  if (nLen >= 5 && nLen <= 0x14) break;
          } while(true);
  
          printf("注册码:");
          for (i = 0; i < nLen; i++)
          {
                  c = szUserName[i] % PI[i];
                  c <<= 1;
                  if (c > 'z') c -= 0x1a;
                  if (c < 'A') c = 0x82 - c;
                  if (c > 'A' && c < 'a') c = c % 0xA + 0x30;
                  printf("%c", c);
          }
          printf("\n");
  }
  
  完
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                   WAKU   2006年03月23日 21:01:26

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

上传的附件:
收藏
点赞7
打赏
分享
最新回复 (13)
雪    币: 191
活跃值: (335)
能力值: ( LV9,RANK:450 )
在线值:
发帖
回帖
粉丝
RegKiller 10 2006-3-23 23:24
2
0
int main()
{
reutrn 0;
}

void main()
{}
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
WAKU 7 2006-3-24 08:18
3
0
呵呵,我用的VC8,确实能编译通过
雪    币: 270
活跃值: (176)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
ikki 9 2006-3-24 08:33
4
0
最初由 WAKU 发布
呵呵,我用的VC8,确实能编译通过

vc8还没见过呢,长见识了
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
foxbase 2006-3-24 12:03
5
0
学习中。。。不过文章写得思路不是很清楚
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
WAKU 7 2006-3-24 12:25
6
0
嗯...可能是我分段不太恰当.注释大概看看就行,看明白注册机算法就成了

破文写好了是门艺术啊.
雪    币: 2256
活跃值: (941)
能力值: (RANK:2210 )
在线值:
发帖
回帖
粉丝
逍遥风 55 2006-3-24 17:13
7
0
呵呵 ~比我分析的详细.学习了
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
redhatzj 2006-6-4 22:03
8
0
来学习学习,,,,
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
无所谓了 2006-6-5 16:02
9
0
学习一下~~~
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hjm 2006-6-5 16:10
10
0
分析的详细.学习了
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxhu 2006-6-6 20:51
11
0
呵呵,算法分析不错,初学者可以看看
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhiqiang 2006-6-6 21:10
12
0
好啊 本人正想学习呢
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ziyoung 2006-6-8 12:15
13
0
多提供素材哦
雪    币: 207
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
流水无心 2006-6-9 17:53
14
0
谢谢,我也好久没有来看了,反正先看看吧,谢谢提供
游客
登录 | 注册 方可回帖
返回