Crackme#1

【文章标题】: PEDIY CRACKME#1
【文章作者】: gchao
【作者邮箱】: bysdy915@tom.com
【软件名称】: Bigman's Crackme6
【软件大小】: 7k
【下载地址】: 自己搜索下载
【加壳方式】: Aspack
【编写语言】: vc++
【使用工具】: od,peid,Aspackdie1.41
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!



【详细过程】
    打开软件输入NAME和SERIAL发现没有任何提示。
    用PEID查看发现加了壳,用ASPACKDIE脱掉,得到CRACKME6_U
    因为没有提示对话框,于是在获得输入时下断点。
    用OD载入,运行CRACKME,输入NAME和SERIAL,在COMMAND中输入BPX GetDlgItemTextA,点击CHECK,被断在00401539处。
  00401539  |.  E8 FA010000   call        ; /GetDlgItemTextA    ;压F8跳过CALL,
  0040153E  |.  89C3          mov     ebx, eax
  00401540  |.  09DB          or      ebx, ebx
  00401542  |.  75 04         jnz     short 00401548;判断NAME是否为空,不为空则往下跳,否者EAX清零返回
  00401544  |.  31C0          xor     eax, eax
  00401546  |.  EB 50         jmp     short 00401598
  00401548  |>  BF BC020000   mov     edi, 2BC
  0040154D  |.  BE 30000000   mov     esi, 30
  00401552  |.  B8 48000000   mov     eax, 48
  00401557  |.  99            cdq
  00401558  |.  F7FB          idiv    ebx
  0040155A  |.  29C6          sub     esi, eax
  0040155C  |.  8D34B6        lea     esi, dword ptr [esi+esi*4]
  0040155F  |.  29F7          sub     edi, esi
  00401561  |.  6BFF 6B       imul    edi, edi, 6B
  00401564  |.  81EF 6CCF0000 sub     edi, 0CF6C
  0040156A  |.  81FF 00230000 cmp     edi, 2300
  00401570  |.  7F 08         jg      short 0040157A
  00401572  |.  81FF 90010000 cmp     edi, 190
  00401578  |.  7D 04         jge     short 0040157E
  0040157A  |>  31C0          xor     eax, eax
  0040157C  |.  EB 1A         jmp     short 00401598;以上判断name的位数是否在3——9位之间,否则跳向出错
 
  0040157E  |> /8D85 00FFFFFF lea     eax, dword ptr [ebp-100]
  00401584  |.  50            push    eax
  00401585  |.  53            push    ebx
  00401586  |.  FF75 08       push    dword ptr [ebp+8]
  00401589  |.  E8 77FDFFFF   call    00401305;关键CALL F7跟入因为在后面就是判断和RETN了
  跟进后经过一些读写操作后就到这
  00401397 >|.  C745 FC 00000>mov     dword ptr [ebp-4], 0             ;  获得注册码
  0040139E  |.  68 00010000   push    100                              ; /Count = 100 (256.)
  004013A3  |.  8D85 E1FCFFFF lea     eax, dword ptr [ebp-31F]         ; |
  004013A9  |.  50            push    eax                              ; |Buffer
  004013AA  |.  6A 66         push    66                               ; |ControlID = 66 (102.)
  004013AC  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  004013AF  |.  E8 84030000   call        ; /GetDlgItemTextA
  GetDlgItemTextA这次获得的是SERIAL
 
 
  004013B4  |.  09C0          or      eax, eax
  004013B6  |. /0F84 48010000 je      00401504;判断SERIAL是否为0
  004013BC  |. |B8 CF110000   mov     eax, 11CF
  004013C1  |. |0FB68D E1FCFF>movzx   ecx, byte ptr [ebp-31F]
  004013C8  |. |99            cdq
  004013C9  |. |F7F9          idiv    ecx
  004013CB  |. |83FA 17       cmp     edx, 17
  004013CE  |. |74 07         je      short 004013D7
  004013D0  |. |31C0          xor     eax, eax
  004013D2  |. |E9 2D010000   jmp     00401504
  004013D7  |> |31DB          xor     ebx, ebx
  004013D9  |. |EB 0B         jmp     short 004013E6
  这里判断SERIAL的第一位,通过求0X11cf%BUF[0],判断结果是否是0x17,如果不是则出错,满足结果的有6,8,H,Q,T,l(我怎么
  知道的?写个C的循环不就算出来的么~~)
  于是重新开始NAME仍然是gchao,但SERIAL的第一位必须是以上几个数,这里我选了H
  重复上面过程,结果跳过了出错的004013D2  |. /E9 2D010000   jmp     00401504
  跳向了这:
  004013DB  |> /8B45 10       /mov     eax, dword ptr [ebp+10]
  004013DE  |. |0FBE0418      |movsx   eax, byte ptr [eax+ebx]
  004013E2  |. |0145 FC       |add     dword ptr [ebp-4], eax
  004013E5  |. |43            |inc     ebx
  004013E6  |> |3B5D 0C        cmp     ebx, dword ptr [ebp+C]
  004013E9  |.^/7C F0         /jl      short 004013DB
 
  这段是把NAME的各个位的ASCII相加
  跳出上面的循环后再运行一行,就开始了算出注册号的过程
  004013F2  |> /8B55 10       /mov     edx, dword ptr [ebp+10]
  004013F5  |. |0FBE3C1A      |movsx   edi, byte ptr [edx+ebx]        
  004013F9  |. |8B75 FC       |mov     esi, dword ptr [ebp-4];刚刚上面算出来的总ASCII值
  004013FC  |. |89D9          |mov     ecx, ebx
  004013FE  |. |C1E1 02       |shl     ecx, 2
  00401401  |. |89DA          |mov     edx, ebx
  00401403  |. |42            |inc     edx
  00401404  |. |29D1          |sub     ecx, edx
  00401406  |. |0FB68C0D E1FE>|movzx   ecx, byte ptr [ebp+ecx-11F]
  0040140E  |. |89FA          |mov     edx, edi
  00401410  |. |31CA          |xor     edx, ecx
  00401412  |. |89F1          |mov     ecx, esi
  00401414  |. |0FAFCB        |imul    ecx, ebx
  00401417  |. |29F1          |sub     ecx, esi
  00401419  |. |89CE          |mov     esi, ecx
  0040141B  |. |83F6 FF       |xor     esi, FFFFFFFF
  0040141E  |. |8DB432 4D0100>|lea     esi, dword ptr [edx+esi+14D]
  00401425  |. |8B4D 0C       |mov     ecx, dword ptr [ebp+C]
  00401428  |. |89DA          |mov     edx, ebx
  0040142A  |. |83C2 03       |add     edx, 3
  0040142D  |. |0FAFCA        |imul    ecx, edx
  00401430  |. |0FAFCF        |imul    ecx, edi
  00401433  |. |89F0          |mov     eax, esi
  00401435  |. |01C8          |add     eax, ecx
  00401437  |. |B9 0A000000   |mov     ecx, 0A
  0040143C  |. |31D2          |xor     edx, edx
  0040143E  |. |F7F1          |div     ecx
  00401440  |. |83C2 30       |add     edx, 30
  00401443  |. |88941D FCFEFF>|mov     byte ptr [ebp+ebx-104], dl
  0040144A  |. |0FB6BC1D FCFE>|movzx   edi, byte ptr [ebp+ebx-104]
  00401452  |. |81F7 ACAD0000 |xor     edi, 0ADAC
  00401458  |. |89DE          |mov     esi, ebx
  0040145A  |. |83C6 02       |add     esi, 2
  0040145D  |. |89F8          |mov     eax, edi
  0040145F  |. |0FAFC6        |imul    eax, esi
  00401462  |. |B9 0A000000   |mov     ecx, 0A
  00401467  |. |99            |cdq
  00401468  |. |F7F9          |idiv    ecx
  0040146A  |. |83C2 30       |add     edx, 30
  0040146D  |. |88941D FCFEFF>|mov     byte ptr [ebp+ebx-104], dl
  00401474  |. |43            |inc     ebx
  00401475  |> |3B5D 0C        cmp     ebx, dword ptr [ebp+C]
  00401478  |.^/0F8C 74FFFFFF /jl      004013F2
 
  通过反复的跟踪,他的过程相当于是:
  k = ~(i*total-total) + (i+3)*n*bufn[i] + (bufn[i]^table[4*i-(i+1)+1]) + 0x14d;
  j = (((k%0xa +0x30)^0xADAC) * (i+2)) % 0xa + 0x30;
  (bufn[i]为第i位注册名的ASCII值,table[]是程序算SERIAL的查询表,这里就是从A-Z,
  我怎么知道?在这一句00401406  |.  0FB68C0D E1FE>|movzx   ecx, byte ptr [ebp+ecx-11F]
  突然来了一个ss:[0012f7d7]=43(‘C’)(我是第2次循环才发现的,第一次是0,没注意,嘿嘿)于是内存中
  跟入就看到啦~~~
  )
  好了,跳出循环后
  0040147E  |.  8D85 FCFEFFFF lea     eax, dword ptr [ebp-104]        
  00401484  |.  50            push    eax                              ;获得6位注册码入栈
  00401485  |.  6A 54         push    54
  00401487  |.  8D85 DCFBFFFF lea     eax, dword ptr [ebp-424]
  0040148D  |.  50            push    eax                              ; |Format
  0040148E  |.  8D85 E1FBFFFF lea     eax, dword ptr [ebp-41F]         ; |
  00401494  |.  50            push    eax                              ; |s
  00401495  |.  E8 CE020000   call              ; /wsprintfA
  这里在获得6位注册码前加T
  0040149A  |.  8B7D 0C       mov     edi, dword ptr [ebp+C]
  0040149D  |.  89F8          mov     eax, edi
  0040149F  |.  0FAF45 FC     imul    eax, dword ptr [ebp-4]
  004014A3  |.  B9 64000000   mov     ecx, 64
  004014A8  |.  99            cdq
  004014A9  |.  F7F9          idiv    ecx
  004014AB  |.  89D7          mov     edi, edx
  004014AD  |.  83C7 30       add     edi, 30
  这段相当于是
  把n (NAME的总位数)* total(前面说过了) % 0x64 +0x30;做为后面的几位
  004014B0  |.  57            push    edi
  004014B1  |.  8DBD E1FBFFFF lea     edi, dword ptr [ebp-41F]
  004014B7  |.  57            push    edi
  004014B8  |.  8DBD D6FBFFFF lea     edi, dword ptr [ebp-42A]
  004014BE  |.  57            push    edi                              ; |Format
  004014BF  |.  8DBD E1FDFFFF lea     edi, dword ptr [ebp-21F]         ; |
  004014C5  |.  57            push    edi                              ; |s
  004014C6  |.  E8 9D020000   call              ; /wsprintfA
  这里是在前面的7位注册码T00004(我这是这个)后加上‘-’和把上面算出来的n * total % 0x64 +0x30转化10进制当作SERIAL
  ,我这算出来的是0x76,转换成10进制就是118
  到目前为止得到了T00004-118,很像是SERIAL了吧,但很不幸,还不是啦~~~不信你输入看看嘿嘿
  继续
  004014D4  |.  83C8 FF       or      eax, FFFFFFFF
  004014D7  |>  40            /inc     eax
  004014D8  |.  803C01 00     |cmp     byte ptr [ecx+eax], 0
  004014DC  |.^ 75 F9         /jnz     short 004014D7
  这段是计算下目前的注册码是多少位的
  然后又有一个CALL,当然是跟入啦
  004012C8  |.  8B5D 10       mov     ebx, dword ptr [ebp+10]
  004012CB  |.  31F6          xor     esi, esi
  004012CD  |.  46            inc     esi
  004012CE  |.  EB 29         jmp     short 004012F9
  004012D0  |>  8B55 08       /mov     edx, dword ptr [ebp+8]
  004012D3  |.  0FBE3C32      |movsx   edi, byte ptr [edx+esi]
  004012D7  |.  89F8          |mov     eax, edi
  004012D9  |.  83F0 20       |xor     eax, 20
  004012DC  |.  B9 0A000000   |mov     ecx, 0A
  004012E1  |.  99            |cdq
  004012E2  |.  F7F9          |idiv    ecx
  004012E4  |.  89D7          |mov     edi, edx
  004012E6  |.  83C7 30       |add     edi, 30
  004012E9  |.  8B55 0C       |mov     edx, dword ptr [ebp+C]
  004012EC  |.  0FBE1432      |movsx   edx, byte ptr [edx+esi]
  004012F0  |.  39D7          |cmp     edi, edx
  004012F2      74 04         je      short 004012F8          
  ;这里每算一位就要和你输入的注册码相比较,我是改成JMP的,方便调试,免得每次都要重来
  004012F4  |.  31C0          |xor     eax, eax
  004012F6  |.  EB 08         |jmp     short 00401300
  004012F8  |>  46            |inc     esi
  004012F9  |>  39DE           cmp     esi, ebx
  004012FB  |.^ 7C D3         /jl      short 004012D0
  这里吧刚刚算出来的位数做为循环次数,对刚刚的注册码进行2次加工~~
  算法是:
  bufms[i]^0x20) %0xa +0x30
  bufms[i]为当前暂时注册码的第i位~~
  于是到目前为止,大功造成,追出注册码了
  我的是T66660774
  下面是整个的算法,我用的是C:
  #include<stdio.h>
  #include<string.h>
 
  char table[28] = {0x00,'A','B','C','D','E','F','G','H','I','J','K','L',
       'M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','/0'};
 
  void print()
  {
   printf("/t/tThe keygen of TheBigMan's CrackMe #6/n");
   printf("/t/t/t/t/tcracked by gchao/n");
  }
  int getlen(int n)
  {
   int i = 1;
   while((n/=10) != 0){
    i++;
   }
   return i;
  }
 
  void itoc(int temp,int j,char * buf)
  {
   while(j > 0){
    buf[--j]=temp%10+0x30;
    temp /= 10;
   }
 
  }
  int main()
  {
   long int i,j,n,total,k,temp;
   char bufn[20]={0},bufs[40]={'T'},bufms[40]={'T'},ch;
   
   total = 0;
   print();
   printf("type in your name,/nthe name must more than 3 lettles:/n");
   scanf("%s",bufn);
   n = strlen(bufn);
   for(i = 0;i < n;i++)
    total += bufn[i];     //算出注册名的ASCII的总和
   for(i = 0;i < n;i++){
    k = ~(i*total-total) + (i+3)*n*bufn[i] + (bufn[i]^table[4*i-(i+1)+1]) + 0x14d;
   
    j = (((k%0xa +0x30)^0xADAC) * (i+2)) % 0xa + 0x30;
    bufms[i+1] = j;
   }
   bufms[++i] = '-';
   temp = n * total % 0x64 +0x30;
   j=getlen(temp);       //j中存放-之后的数字
   itoc(temp,j,&bufms[++i]);      //将整型数据转化成字符串并写入到后续序列号
   
   for(i = 1; i <= (n+j+1); i++)
    bufs[i]=(((long int)bufms[i])^0x20) %0xa +0x30;
 
   printf("Serial is: %s/n",bufs);
   return 0;
  }



【经验总结】
  1.因为没有提示对话框,于是在获得输入时下断点。
    用OD载入,运行CRACKME,输入NAME和SERIAL,在COMMAND中输入BPX GetDlgItemTextA
 




                                                       2008年05月18日 上午 10:01:39

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 [安全攻防进阶篇] 中,有关于逆向分析的教程可以帮助你了解如何使用OllyDbg逆向CrackMe程序。 OllyDbg是一种常用的逆向工具,可以用于分析和修改程序的执行流程和内存。使用内存断点和普通断点,可以在程序执行过程中捕获关键的代码位置,帮助我们找到CrackMe程序的OEP(Original Entry Point),即程序的入口点。 在 [安全攻防进阶篇] 中还有关于逆向分析两个CrackMe程序的详细教程,包括逆向分析和源码还原的步骤。这些教程将帮助你理解逆向分析的基本概念和技巧,提升你的安全能力。 如果你想深入学习如何使用OllyDbg逆向CrackMe程序,可以参考这些教程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [[安全攻防进阶篇] 六.逆向分析之OllyDbg逆向CrackMe01-02及加壳判断](https://blog.csdn.net/Eastmount/article/details/107777190)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [逆向crackme之ESp定律脱壳](https://blog.csdn.net/qq_58970968/article/details/125357834)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值