首页
社区
课程
招聘
[原创]yingyue's CrackMe[BUG]版本的暴力破解的可能性探讨 + 穷举注册机的实现!
发表于: 2007-5-10 22:45 9480

[原创]yingyue's CrackMe[BUG]版本的暴力破解的可能性探讨 + 穷举注册机的实现!

2007-5-10 22:45
9480

yingyue's CrackMe【BUG】版本的暴力破解的可能性探讨 + 穷举注册机的实现!

今天下载了yingyue兄在论坛上的一个CrackMe,后来被证实为BuG版本,开始还以为是yingyue兄故意这样写的哪!不得已用暴力穷举计算的方式,得到了正确的注册码!写出来的目的,就是让大家论论,其实那个BUG版本,我个人认为理论上还是可以被注册成功的,最后将放上菜鸟我写的一个暴力注册机!

先看算法,如下:

》》》》》》

00401598  |.  E8 E7E90000   call    <jmp.&msvcrt.strlen>             ; \strlen
0040159D  |.  83C4 10       add     esp, 10
004015A0  |.  8945 A4       mov     dword ptr [ebp-5C], eax
004015A3  |.  8B45 A4       mov     eax, dword ptr [ebp-5C]
004015A6  |.  48            dec     eax                              ;  i := 注册名长度 - 1;
004015A7  |.  8945 AC       mov     dword ptr [ebp-54], eax          ;  54 : i
004015AA  |.  8DB6 00000000 lea     esi, dword ptr [esi]
004015B0  |>  837D AC 00    /cmp     dword ptr [ebp-54], 0
004015B4  |.  7D 02         |jge     short 练习.004015B8
004015B6  |.  EB 3C         |jmp     short 练习.004015F4
004015B8  |>  8D45 C0       |lea     eax, dword ptr [ebp-40]         ;  注册名 -> EAX
004015BB  |.  8B55 AC       |mov     edx, dword ptr [ebp-54]         ;  i ->EDX
004015BE  |.  0FBE0402      |movsx   eax, byte ptr [edx+eax]         ;  ord(cz[i+1])
004015C2  |.  89C2          |mov     edx, eax
004015C4  |.  2B55 AC       |sub     edx, dword ptr [ebp-54]         ;  ord(cz[i+1]) - i -》 EDX
004015C7  |.  8955 9C       |mov     dword ptr [ebp-64], edx         ;  -> key[length(注册名)]
004015CA  |.  8B45 A4       |mov     eax, dword ptr [ebp-5C]         ;  注册名长度
004015CD  |.  8B4D AC       |mov     ecx, dword ptr [ebp-54]         ;  i
004015D0  |.  89C2          |mov     edx, eax
004015D2  |.  29CA          |sub     edx, ecx                        ;  注册名长度 - i
004015D4  |.  89D0          |mov     eax, edx
004015D6  |.  0345 AC       |add     eax, dword ptr [ebp-54]         ;  注册名长度 -> eax
004015D9  |.  8D55 B0       |lea     edx, dword ptr [ebp-50]         ;  [0242FF10] -> edx
004015DC  |.  8A4D 9C       |mov     cl, byte ptr [ebp-64]           ;  key[length(注册名)] -> cl
004015DF  |.  880C10        |mov     byte ptr [eax+edx], cl          ;  cl -> [0242FF10 + 注册名长度]
004015E2  |.  8D45 B0       |lea     eax, dword ptr [ebp-50]         ;  [0242FF10] -> eax
004015E5  |.  8B55 AC       |mov     edx, dword ptr [ebp-54]         ;  i -> edx
004015E8  |.  0FBE0402      |movsx   eax, byte ptr [edx+eax]         ;  [0242FF10 + i] -> eax
004015EC  |.  0145 A0       |add     dword ptr [ebp-60], eax         ;  累加 temp1
004015EF  |.  FF4D AC       |dec     dword ptr [ebp-54]              ;  i - 1
004015F2  |.^ EB BC         \jmp     short 练习.004015B0
004015F4  |>  8B45 A0       mov     eax, dword ptr [ebp-60]          ;  temp2A-> eax
004015F7  |.  89C2          mov     edx, eax                         ;  -> edx
004015F9  |.  8D0412        lea     eax, dword ptr [edx+edx]         ;  2 x (edx) -> eax
004015FC  |.  8D90 D6860000 lea     edx, dword ptr [eax+86D6]        ;  + $86D6 ->edx
00401602  |.  89D1          mov     ecx, edx
00401604  |.  83F1 06       xor     ecx, 6                           ;  xor $6
00401607  |.  894D A0       mov     dword ptr [ebp-60], ecx          ;  temp2A
0040160A  |.  0FBE45 B0     movsx   eax, byte ptr [ebp-50]           ;  key[0] -> eax
0040160E  |.  8D90 EF78FFFF lea     edx, dword ptr [eax+FFFF78EF]    ;  + $FFFF78EF -> edx
00401614  |.  8B45 98       mov     eax, dword ptr [ebp-68]          ;  注册码->16进制->eax
00401617  |.  29D0          sub     eax, edx                         ;  注册码 - (key[0] + $FFFF78EF)
00401619  |.  89C2          mov     edx, eax
0040161B  |.  83F2 06       xor     edx, 6                           ;  xor 6
0040161E  |.  8955 98       mov     dword ptr [ebp-68], edx          ;  temp3
00401621  |.  0FBE55 B1     movsx   edx, byte ptr [ebp-4F]           ;  key[1]
00401625  |.  8B4D 98       mov     ecx, dword ptr [ebp-68]
00401628  |.  29D1          sub     ecx, edx                         ;  temp4 := temp3 - key[1]
0040162A  |.  898D 7CFFFFFF mov     dword ptr [ebp-84], ecx
00401630  |.  8B75 A0       mov     esi, dword ptr [ebp-60]          ;  temp2A
00401633  |.  89F0          mov     eax, esi                         ;  -> eax
00401635  |.  99            cdq
00401636  |.  F77D A4       idiv    dword ptr [ebp-5C]               ;  temp2B:=temp2 div 注册名长度
00401639  |.  89C1          mov     ecx, eax                         ;  -> ecx
0040163B  |.  8B85 7CFFFFFF mov     eax, dword ptr [ebp-84]          ;  temp4
00401641  |.  01C8          add     eax, ecx                         ;  temp4 := temp4 + temp2B; -> eax
00401643  |.  8B55 98       mov     edx, dword ptr [ebp-68]          ;  temp3
00401646  |.  29C2          sub     edx, eax                         ;  temp5(edx) := temp3(edx) - temp4(eax);
00401648  |.  8955 94       mov     dword ptr [ebp-6C], edx          ;  -> edx temp5
0040164B  |.  8B45 98       mov     eax, dword ptr [ebp-68]          ;  temp3
0040164E  |.  8B55 94       mov     edx, dword ptr [ebp-6C]          ;  temp5
00401651  |.  29D0          sub     eax, edx                         ;  temp6 := temp3 - temp5;
00401653  |.  8D55 B0       lea     edx, dword ptr [ebp-50]          ;  key[0]
00401656  |.  8B4D AC       mov     ecx, dword ptr [ebp-54]          ;  $FFFFFFFF
00401659  |.  0FBE1411      movsx   edx, byte ptr [ecx+edx]          ;  $FFFFFFFF -> edx
0040165D  |.  89C1          mov     ecx, eax                         ;  temp6 -> ecx
0040165F  |.  29D1          sub     ecx, edx                         ;  temp6 := temp6 - $FFFFFFFF
00401661  |.  894D 90       mov     dword ptr [ebp-70], ecx
00401664  |.  8B45 98       mov     eax, dword ptr [ebp-68]          ;  temp3
00401667  |.  8B55 94       mov     edx, dword ptr [ebp-6C]          ;  temp5
0040166A  |.  89C1          mov     ecx, eax
0040166C  |.  29D1          sub     ecx, edx                         ;  ecx := temp3 - temp5
0040166E  |.  898D 7CFFFFFF mov     dword ptr [ebp-84], ecx          ;  temp4 = ecx
00401674  |.  8B75 A0       mov     esi, dword ptr [ebp-60]          ;  temp2A
00401677  |.  89F0          mov     eax, esi
00401679  |.  99            cdq
0040167A  |.  F77D A4       idiv    dword ptr [ebp-5C]               ;  temp2A/注册名长度
0040167D  |.  89C1          mov     ecx, eax
0040167F  |.  8B95 7CFFFFFF mov     edx, dword ptr [ebp-84]          ;  temp4
00401685  |.  29CA          sub     edx, ecx                         ;  temp7 := temp4 - temp2B;
00401687  |.  8955 8C       mov     dword ptr [ebp-74], edx
0040168A  |.  8B45 A0       mov     eax, dword ptr [ebp-60]          ;  ? -> eax
0040168D  |.  8B4D 94       mov     ecx, dword ptr [ebp-6C]          ;  temp5 -> ecx
00401690  |.  8D1401        lea     edx, dword ptr [ecx+eax]         ;  +
00401693  |.  89D0          mov     eax, edx
00401695  |.  2B45 98       sub     eax, dword ptr [ebp-68]          ;  - temp3 -> EAX
00401698  |.  8B55 90       mov     edx, dword ptr [ebp-70]          ;  temp6
0040169B  |.  8B4D 8C       mov     ecx, dword ptr [ebp-74]          ;  temp7
0040169E  |.  01CA          add     edx, ecx                         ;  temp6 + temp7 ->EDX
004016A0  |.  39D0          cmp     eax, edx
004016A2      75 1C         jnz     short 练习.004016C0
004016A4  |.  83C4 F8       add     esp, -8
004016A7  |.  68 30134000   push    练习.00401330                      ;  \n                          严重佩服,你真行
004016AC  |.  68 28504100   push    练习.00415028                      ;  d`A
004016B1  |.  E8 921B0000   call    练习.00403248
004016B6  |.  83C4 10       add     esp, 10
004016B9  |.  EB 1A         jmp     short 练习.004016D5
004016BB  |   90            nop
004016BC  |   8D7426 00     lea     esi, dword ptr [esi]
004016C0  |>  83C4 F8       add     esp, -8
004016C3  |.  68 70134000   push    练习.00401370                      ;  \n                          恭喜你,你还要努力
004016C8  |.  68 28504100   push    练习.00415028                      ;  d`A
004016CD  |.  E8 761B0000   call    练习.00403248
004016D2  |.  83C4 10       add     esp, 10
004016D5  |>  83C4 F8       add     esp, -8
004016D8  |.  68 9E134000   push    练习.0040139E                      ;  \n
004016DD  |.  68 28504100   push    练习.00415028                      ;  d`A
004016E2  |.  E8 611B0000   call    练习.00403248
004016E7  |.  83C4 10       add     esp, 10
004016EA  |.  E8 6DE80000   call    <jmp.&msvcrt.getchar>            ; [getchar
004016EF  |.  8D53 04       lea     edx, dword ptr [ebx+4]
》》》》》》

通过上面的算法,我们知道了其计算的方式如下(我是以注册名8位数及以下为探讨):

var
  temp1                                      : byte;
  temp2A, temp2B, temp3, temp4, temp5, temp6,
   temp7, tempT, czCode, i, SN1, SN2         : integer;
  czName, str                                : string;
const
  key: array[0 .. 7] of byte =
  ($AD,$AE,$C0,$77,$38,$07,$93,$7C);
begin

  czName := EditName.Text;
  czCode := strToint(EditCode.text);
  temp1 := 0;
  for i := (length(czName)-1) downto 0 do
    begin
      key[length(czName)] := ord(czName[i+1]) - i;
      temp1 := temp1 + key[i];
    end;
    str := '$FFFFFF' + intTohex(temp1,2);
    temp2A:= strToint(str);

    temp2A := ((temp2A * 2) + $86D6) xor $6;

  str := '$FFFFFF' + intTohex(key[0],2);
  tempT := strToint(str); //key[0] = $FFFFFFAD
  temp3 := tempT + $FFFF78EF;

  temp3 := (czCode - temp3) xor 6;             //与注册吗有关

  str := '$FFFFFF' + intTohex(key[1],2);
  tempT := strToint(str); //key[1] = $FFFFFFAE
  temp4 := temp3 - tempT;

  temp2B := temp2A div length(czName); //除以注册名长度

  temp4 := temp4 + temp2B;

  temp5 := temp3 - temp4;

  temp6 := (temp3 - temp5) - $FFFFFFFF;

  temp4 := temp3 - temp5;

  temp7 := temp4 - temp2B;

  SN1 := intTohex((temp2A + temp5) - temp3,8);
  SN2 := intTohex((temp6 + temp7),8);

通过上面反汇编的代码我们知道:当 SN1 = SN2 时,即寄存器 EAX=EDX  时便注册成功了!

那么,我们就可以写一个用穷举的方式来得到本地计算机的正确注册码的KeyGen了!

思路如下:

将上面的总算法独立分成SN1和SN2来独立运算,SN1运算中带入注册名,SN2运算则带入从-99999开始的数字,依次增大,然后对SN1的运算结果值和SN2

的运算结果值比较,如若当SN1=SN2时,那么带入SN2中的那个数字就是正确的注册码了!

呵呵,最后放上我的暴力注册机的源代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    EditName: TEdit;
    EditCode: TEdit;
    EditSN1: TEdit;
    EditSN2: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

var
  czI : integer;
  
{$R *.DFM}

//SN1
function SN1(Name: String): integer;   //定义函数
var
  temp1                                      : byte;
  temp2A, temp2B, temp3, temp4, temp5, temp6,
   temp7, tempT, czCode, i, SN1, SN2         : integer;
  czName, str                                : string;
const
  key: array[0 .. 7] of byte =
  ($AD,$AE,$C0,$77,$38,$07,$93,$7C);
begin
  czName := Form1.EditName.Text;
  czCode := czI;   //?????
  temp1 := 0;
  for i := (length(czName)-1) downto 0 do
    begin
      key[length(czName)] := ord(czName[i+1]) - i;
      temp1 := temp1 + key[i];
    end;
    str := '$FFFFFF' + intTohex(temp1,2);
    temp2A:= strToint(str);

    temp2A := ((temp2A * 2) + $86D6) xor $6;

  str := '$FFFFFF' + intTohex(key[0],2);
  tempT := strToint(str); //key[0] = $FFFFFFAD
  temp3 := tempT + $FFFF78EF;

  temp3 := (czCode - temp3) xor 6;             //####与注册吗有关

  str := '$FFFFFF' + intTohex(key[1],2);
  tempT := strToint(str); //key[1] = $FFFFFFAE
  temp4 := temp3 - tempT;

  temp2B := temp2A div length(czName); //除以注册名长度

  temp4 := temp4 + temp2B;

  temp5 := temp3 - temp4;

  temp6 := (temp3 - temp5) - $FFFFFFFF;

  temp4 := temp3 - temp5;

  temp7 := temp4 - temp2B;

//当 SN1 = SN2 便成功!
  Result := (temp2A + temp5) - temp3;
//Result := (temp6 + temp7);
end;

//SN2
function SN2(Code: integer): integer;   //定义函数
var
  temp1                                      : byte;
  temp2A, temp2B, temp3, temp4, temp5, temp6,
   temp7, tempT, czCode, i, SN1, SN2         : integer;
  czName, str                                : string;
const
  key: array[0 .. 7] of byte =
  ($AD,$AE,$C0,$77,$38,$07,$93,$7C);
begin
  czName := Form1.EditName.Text;
  czCode := czI;      //???
  temp1 := 0;
  for i := (length(czName)-1) downto 0 do
    begin
      key[length(czName)] := ord(czName[i+1]) - i;
      temp1 := temp1 + key[i];
    end;
    str := '$FFFFFF' + intTohex(temp1,2);
    temp2A:= strToint(str);

    temp2A := ((temp2A * 2) + $86D6) xor $6;

  str := '$FFFFFF' + intTohex(key[0],2);
  tempT := strToint(str); //key[0] = $FFFFFFAD
  temp3 := tempT + $FFFF78EF;

  temp3 := (czCode - temp3) xor 6;             //####与注册吗有关

  str := '$FFFFFF' + intTohex(key[1],2);
  tempT := strToint(str); //key[1] = $FFFFFFAE
  temp4 := temp3 - tempT;

  temp2B := temp2A div length(czName); //除以注册名长度

  temp4 := temp4 + temp2B;

  temp5 := temp3 - temp4;

  temp6 := (temp3 - temp5) - $FFFFFFFF;

  temp4 := temp3 - temp5;

  temp7 := temp4 - temp2B;

//当 SN1 = SN2 便成功!
//Result := (temp2A + temp5) - temp3;
  Result := (temp6 + temp7);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  temp1                                      : byte;
  temp2A, temp2B, temp3, temp4, temp5, temp6,
   temp7, tempT, czCode, i, SN1, SN2         : integer;
  czName, str                                : string;
const
  key: array[0 .. 7] of byte =
  ($AD,$AE,$C0,$77,$38,$07,$93,$7C);
begin

  czName := EditName.Text;
  czCode := strToint(EditCode.text);
  temp1 := 0;
  for i := (length(czName)-1) downto 0 do
    begin
      key[length(czName)] := ord(czName[i+1]) - i;
      temp1 := temp1 + key[i];
    end;
    str := '$FFFFFF' + intTohex(temp1,2);
    temp2A:= strToint(str);
//showmessage(intTohex(temp2A,8));
    temp2A := ((temp2A * 2) + $86D6) xor $6;
//showmessage(intTohex(temp2A,8));
  str := '$FFFFFF' + intTohex(key[0],2);
  tempT := strToint(str); //key[0] = $FFFFFFAD
  temp3 := tempT + $FFFF78EF;
//showmessage(intTohex(temp3,8));
  temp3 := (czCode - temp3) xor 6;             //与注册吗有关
//showmessage(intTohex(temp3,8));
  str := '$FFFFFF' + intTohex(key[1],2);
  tempT := strToint(str); //key[1] = $FFFFFFAE
  temp4 := temp3 - tempT;
//showmessage(intTohex(temp4,8));
  temp2B := temp2A div length(czName); //除以注册名长度
//showmessage(intTohex(temp2B,8));
  temp4 := temp4 + temp2B;

  temp5 := temp3 - temp4;
//showmessage(intTohex(temp5,8));
  temp6 := (temp3 - temp5) - $FFFFFFFF;

  temp4 := temp3 - temp5;

  temp7 := temp4 - temp2B;

//当 SN1 = SN2 便成功!
  EditSN1.Text := intTohex((temp2A + temp5) - temp3,8);
  EditSN2.Text := intTohex((temp6 + temp7),8);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  czI := strToint(EditCode.Text);
  EditSN1.Text := intTohex(SN1(EditName.Text),8);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  czI := strToint(EditCode.Text);
  EditSN2.Text := intTohex(SN2(czI),8);
end;

procedure TForm1.Button4Click(Sender: TObject);
var
  pos : integer;
begin
  for pos := -30000 to -10000 do
    begin
      czI := pos;
      if SN2(czI) = SN1(EditName.Text)
      then begin
             showmessage('正确注册码:'+ intTostr(czI));
             EditCode.Text := intTostr(czI);
             exit;
           end
      else begin
             memo1.Lines.Add(intTostr(czI));
             if pos = -10000
             then begin
                    showmessage('没有找到正确的注册码!'+#13+'扩大范围再试一试?');
                    exit;
                  end;
           end;     
    end;
//timer.Enabled := True;
end;

end.

而且,通过测试,事实证明,这个KeyGen确实起到作用了! 最后,感谢 yingyue 兄的这个【BUG】版本的CM,让我有幸写出个穷举注册机了!


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 1969
活跃值: (46)
能力值: (RANK:550 )
在线值:
发帖
回帖
粉丝
2
[QUOTE=acafeel;307684]const
  key: array[0 .. 7] of byte =
  ($AD,$AE,$C0,$77,$38,$07,$93,$7C);
[/QUOTE]
首先学习一下,但是感觉上面的key是个例,这里穷举出来的注册码没有通用性,换台电脑、换个操作系统可能就不能用了。
上传的附件:
2007-5-10 23:46
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
很不错了,就如上面的兄弟所说,夸不了平台

但也从中理解了部分的原因能令人更难计算的道理

严重佩服兄弟的能力。。。。。。。。。。。。。强
2007-5-11 00:51
0
雪    币: 333
活跃值: (116)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
4
那个Key就是传说中的BUG,N[i]了
所以我只能从理论上来让其在本机上注册成功!
还有更好的方法没有?大家一起来探讨一下吧!
2007-5-11 11:11
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
5
i 值为遁去的 1,故每台机器上都不同,故没人能写一个通用的注册机,
也如兄弟的写法,我的开头意向就是要你们穷举出自己的注册码的,
谁知道,就再写第二次修正的时候把 1 写成了 i 晕死,当时没发现
(因为第一次调试时已经通过了,就马马虎虎的上传了)(搞死好多人)

下次我写一个,要你们交出这个 i 值 (当本机的硬件码用)
2007-5-11 16:29
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习!!!!
2007-5-11 17:44
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习了。看来高手很多。很难呀
2007-5-27 19:28
0
雪    币: 200
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
下载下来学习一下,谢谢
2011-4-19 17:23
0
雪    币: 233
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习学习
2011-4-20 21:13
0
游客
登录 | 注册 方可回帖
返回
//