壹只老虎 发表于 2006-8-28 22:32:59

一个挺有创意的crackme算法分析+注册机

【文章标题】: 一个挺有创意的crackme算法分析+注册机
【文章作者】: 壹只老虎
【作者邮箱】: [email protected]
【作者QQ号】: 609841314
【软件名称】: step4.exe
【软件大小】: 31kb
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 1.06b / 1.061b
【保护方式】: ASPack 1.06b / 1.061b
【编写语言】: Borland C++ 1999
【使用工具】: peid+od+windows计算器
【操作平台】: xp
【软件介绍】: 五个crackme中的第四个,算法分析,写的有点特别!
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
先说明一下,本人破解经验不多,所以才会觉得这个crackme有点创意,高手见笑了!呵呵!
前几天就分析好了,今天写个破文拿出来共享一下,请大家多多指教!呵呵!

再介绍一下这个Crackme的特点:点击运行后,首先弹出提示框,"step4 has not been solved",然后打开一个窗口,
上面有一个关闭按钮!其他什么也没有了!嘿嘿!是不是有点特别呢!我开始的时候也不知道怎么办!嘿嘿!看我一步一步分析!
不是很难!倒是有点意思的!

1:peid查壳-->ASPack 1.06b / 1.061b,好说,我还是写的详细点,以便新手看得明白点!
    这个壳算是初级壳把!看看我们怎么脱壳!首先od载入,会异常的!然后确定!shift+f9过去,然后选择否!
    好了,开始分析!f8四次,在esp上下硬件访问断点, f9一次,f8一次,选择不重建输入表的方式脱壳!保存为3.exe,
    打开LoarPE,点击"PE编辑器",选择未脱壳的文件,修改入口点地址为3.EXE的入口地址(1000),"确定","重建PE",
    选择 3.EXE,确定,ok,修复成功!!

2:好了,修复好了,我们现在运行下看看,点击运行后,首先弹出提示框,"step4 has not been solved",然后打开一个窗口,
上面有一个关闭按钮!其他什么也没有了!郁闷哦,什么都没有哦!有个输入框也好啊!现在什么也没有!晕了!

3:好了想想把!的确有点特别哦!没遇见过!在想想!刚才什么也没输入就来个错误提示!嘿嘿!是不是想到什么了呢!
    对!文件或者注册表!嘿嘿!不过!先别忙去注册表监视!因为现在没用的!呵呵!为什么了!看后面就知道了!

4:既然想到了注册表,不管3721,也不知道对不对,先试试再说吧!od载入脱壳后的程序!先看看有没有敏感的字符串把!嘿嘿!
    字符串参考,看到了这个,嘿嘿!"Step4 has not been solved",双击来到这里看看!

主函数模块
00401150   /$55               push ebp
00401151   |.8BEC               mov ebp,esp
00401153   |.53               push ebx
00401154   |.8B5D 08            mov ebx,dword ptr ss:
00401157   |.6A 19            push 19                           ; /Arg3 = 00000019
00401159   |.6A 30            push 30                           ; |Arg2 = 00000030
0040115B   |.68 F4C54000      push 43.0040C5F4                  ; |Arg1 = 0040C5F4 ASCII "12345678"
00401160   |.E8 3B120000      call 43.004023A0                  ; \43.004023A0
00401165   |.83C4 0C            add esp,0C
00401168   |.6A 19            push 19                           ; /Arg3 = 00000019
0040116A   |.6A 30            push 30                           ; |Arg2 = 00000030
0040116C   |.68 0DC64000      push 43.0040C60D                  ; |Arg1 = 0040C60D ASCII "admin"
00401171   |.E8 2A120000      call 43.004023A0                  ; \43.004023A0
00401176   |.83C4 0C            add esp,0C
00401179   |.E8 0A010000      call 43.00401288                  ;这里很关键,跟进去看看!
0040117E   |.A3 30C64000      mov dword ptr ds:,eax
00401183   |.E8 CC000000      call 43.00401254                  ;这里也要根进去!里面有算法!
00401188   |.A3 4CA14000      mov dword ptr ds:,eax       ;注册名运算后的数据-->0040a14c
0040118D   |.A1 30C64000      mov eax,dword ptr ds:       ;注册码数据送eax
00401192   |.3B05 4CA14000      cmp eax,dword ptr ds:       ;关键比较
00401198       75 18            jnz short 43.004011B2               ;关键跳转,跳向失败
0040119A   |.68 30000400      push 40030                        ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL|40000
0040119F   |.68 9DA14000      push 43.0040A19D                  ; |Title = "You Did It!"
004011A4   |.68 54A14000      push 43.0040A154                  ; |Text = "Congradulations, you have figured out Step4
Step4 unlock code is: 6DEWS3"
004011A9   |.53               push ebx                            ; |hOwner
004011AA   |.E8 E37E0000      call 43.00409092                  ; \MessageBoxA
004011AF   |.5B               pop ebx
004011B0   |.5D               pop ebp
004011B1   |.C3               retn                              ; 下面就错误了
004011B2   |>68 30000400      push 40030                        ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL|40000
004011B7   |.68 C3A14000      push 43.0040A1C3                  ; |Title = "Not Done"
004011BC   |.68 A9A14000      push 43.0040A1A9                  ; |Text = "Step4 has not been solved"
004011C1   |.53               push ebx                            ; |hOwner
004011C2   |.E8 CB7E0000      call 43.00409092                  ; \MessageBoxA
004011C7   |.5B               pop ebx
004011C8   |.5D               pop ebp
004011C9   \.C3               retn

好吧!不管!现在我们现在这里下个断点再说!嘿嘿!
00401150   /$55               push ebp

f9运行起来了!嘿嘿!没有探出对话框,断下来了!
开始单步分析把!

前面我都写了注释了!heihei!

下面我跟进

00401179   |.E8 0A010000      call 43.00401288

这个call要根近来看看的!很重要的!

00401288   /$55               push ebp
00401289   |.8BEC               mov ebp,esp
0040128B   |.53               push ebx
0040128C   |.56               push esi
0040128D   |.57               push edi
0040128E   |.BB 28C64000      mov ebx,43.0040C628
00401293   |.BE 0DC64000      mov esi,43.0040C60D               ;ASCII "0000000000000000000000000"
00401298   |.BF 4CA14000      mov edi,43.0040A14C
0040129D   |.68 34C64000      push 43.0040C634                  ; /pHandle = 43.0040C634
004012A2   |.68 19000200      push 20019                        ; |Access = KEY_READ
004012A7   |.6A 00            push 0                              ; |Reserved = 0
004012A9   |.68 E6A14000      push 43.0040A1E6                  ; |Subkey = "Software\Step4"
004012AE   |.68 02000080      push 80000002                     ; |hKey = HKEY_LOCAL_MACHINE
004012B3   |.E8 B67C0000      call 43.00408F6E                  ; \RegOpenKeyExA
004012B8   |.68 50A14000      push 43.0040A150                  ; /pBufSize = 43.0040A150
004012BD   |.68 F4C54000      push 43.0040C5F4                  ; |Buffer = 43.0040C5F4
004012C2   |.68 2CC64000      push 43.0040C62C                  ; |pValueType = 43.0040C62C
004012C7   |.6A 00            push 0                              ; |Reserved = NULL
004012C9   |.68 F5A14000      push 43.0040A1F5                  ; |ValueName = "Serial"
004012CE   |.FF35 34C64000      push dword ptr ds:          ; |hKey = 0
004012D4   |.E8 9B7C0000      call 43.00408F74                  ; \RegQueryValueExA
004012D9   |.68 50A14000      push 43.0040A150                  ; /pBufSize = 43.0040A150
004012DE   |.56               push esi                            ; |Buffer => 43.0040C60D
004012DF   |.68 2CC64000      push 43.0040C62C                  ; |pValueType = 43.0040C62C
004012E4   |.6A 00            push 0                              ; |Reserved = NULL
004012E6   |.68 FCA14000      push 43.0040A1FC                  ; |ValueName = "Name"
004012EB   |.FF35 34C64000      push dword ptr ds:          ; |hKey = 0
004012F1   |.E8 7E7C0000      call 43.00408F74                  ; \RegQueryValueExA
004012F6   |.FF35 34C64000      push dword ptr ds:          ; /hKey = NULL
004012FC   |.E8 677C0000      call 43.00408F68                  ; \RegCloseKey
00401301   |.68 F4C54000      push 43.0040C5F4                  ; /Arg1 = 0040C5F4 ASCII "00000000000000000000000000000000000000000000000000"
00401306   |.E8 CD2E0000      call 43.004041D8                  ; \43.004041D8
0040130B   |.59               pop ecx                           ;ecx=注册码字符串,esi=注册名字符串
0040130C   |.A3 30C64000      mov dword ptr ds:,eax       ;eax=edx=注册码数据
00401311   |.33C0               xor eax,eax                         ;eax=0
00401313   |.8903               mov dword ptr ds:,eax
00401315   |.EB 13            jmp short 43.0040132A
00401317   |>8B13               /mov edx,dword ptr ds:
00401319   |.33C9               |xor ecx,ecx                        ;ecx=0
0040131B   |.8A0C16             |mov cl,byte ptr ds:       ;cl=按位取注册名数据的ascii码
0040131E   |.010F               |add dword ptr ds:,ecx         ;ecx=+ecx
00401320   |.6907 77070000      |imul eax,dword ptr ds:,777    ;eax=ecx*1911
00401326   |.8907               |mov dword ptr ds:,eax         ;eax-->0040a14c
00401328   |.FF03               |inc dword ptr ds:
0040132A   |>56                  push esi
0040132B   |.E8 50110000      |call 43.00402480                   ;eax=注册名长度(<=10时)(>10时为25)
00401330   |.59               |pop ecx                            ;ecx=注册名字符串
00401331   |.3B03               |cmp eax,dword ptr ds:         ;循环次数为eax
00401333   |.^ 77 E2            \ja short 43.00401317               ;>就跳
00401335   |.A1 30C64000      mov eax,dword ptr ds:       ;eax=注册码数据
0040133A   |.5F               pop edi                           ;注意:0040a14c保存了注册名计算后的数据
0040133B   |.5E               pop esi
0040133C   |.5B               pop ebx
0040133D   |.5D               pop ebp
0040133E   \.C3               retn

好了,进来了!我们看到什么了!仔细看看下面一段

004012A9   |.68 E6A14000      push 43.0040A1E6                  ; |Subkey = "Software\Step4"
004012AE   |.68 02000080      push 80000002                     ; |hKey = HKEY_LOCAL_MACHINE
004012B3   |.E8 B67C0000      call 43.00408F6E                  ; \RegOpenKeyExA
004012B8   |.68 50A14000      push 43.0040A150                  ; /pBufSize = 43.0040A150
004012BD   |.68 F4C54000      push 43.0040C5F4                  ; |Buffer = 43.0040C5F4
004012C2   |.68 2CC64000      push 43.0040C62C                  ; |pValueType = 43.0040C62C
004012C7   |.6A 00            push 0                              ; |Reserved = NULL
004012C9   |.68 F5A14000      push 43.0040A1F5                  ; |ValueName = "Serial"
004012CE   |.FF35 34C64000      push dword ptr ds:          ; |hKey = 0
004012D4   |.E8 9B7C0000      call 43.00408F74                  ; \RegQueryValueExA
004012D9   |.68 50A14000      push 43.0040A150                  ; /pBufSize = 43.0040A150
004012DE   |.56               push esi                            ; |Buffer => 43.0040C60D
004012DF   |.68 2CC64000      push 43.0040C62C                  ; |pValueType = 43.0040C62C
004012E4   |.6A 00            push 0                              ; |Reserved = NULL
004012E6   |.68 FCA14000      push 43.0040A1FC                  ; |ValueName = "Name"
004012EB   |.FF35 34C64000      push dword ptr ds:          ; |hKey = 0
004012F1   |.E8 7E7C0000      call 43.00408F74                  ; \RegQueryValueExA
004012F6   |.FF35 34C64000      push dword ptr ds:          ; /hKey = NULL
004012FC   |.E8 677C0000      call 43.00408F68                  ; \RegCloseKey

看见没有,这里是注册表键值啊!

位置是多少呢!嘿嘿!看了就知道!很明显是这两个!如下!


"Serial"
"Name"

好了,你可以继续分析!自然会失败了!呵呵!想想啊!这里两个地方的数据是怎么产生的呢?我们从头到尾都没输如果数据阿!
好到这里就好了!好了!我们打开注册表去找找这两个键看看!我找啊!找啊!找了很久,没找到!好奇怪哦!怎么办!找不到阿!
嘿嘿!没关系!没有的话!我们就给他建一个试试看行不行!

在HKEY_LOCAL_MACHINE\SOFTWARE下面新建一个项"Step4",然后在这个项里面新建两个字符串,名字就叫"Serial"和"Name",
Name 的数据设置为tiger, Serial 数据设置为12345678,好了,关闭注册表,od重新载入脱壳后的程序,运行,断下来了!
按照上面的方法,来跟中,具体注释就看上面面的了!我都写好了!赫赫!

下面从这里分析出来后!就到达!
0040117E   |.A3 30C64000      mov dword ptr ds:,eax
这里就直接过去好了!

然后又看见一个call,这里要根进去看看了,里面的算法很简单,但是也很关键!看看下面的分析

跟进

00401183   |.E8 CC000000      call 43.00401254

分析如下:

00401254   /$55               push ebp
00401255   |.8BEC               mov ebp,esp                            ;设注册名计算后的数据为num
00401257   |.8135 4CA14000 1063>xor dword ptr ds:,83746310   ;num=num xor 2205442832
00401261   |.8135 4CA14000 1ED4>xor dword ptr ds:,54ADD41E   ;num=num xor 1420678174
0040126B   |.8135 4CA14000 E9DE>xor dword ptr ds:,ABCDDEE9   ;num=num xor 2882395881
00401275   |.810D 4CA14000 1232>or dword ptr ds:,12323212      ;num=num or 305279506
0040127F   |.A1 4CA14000      mov eax,dword ptr ds:          ;eax=num
00401284   |.5D               pop ebp
00401285   \.C3               retn
00401286       90               nop
00401287       90               nop
00401288   /$55               push ebp

这里出来马上就是关键比较了,总的说来,注册名经过n次运算后,把结果和注册码比较,相等就成功了!呵呵!
好了!就这样!下面说说注册机的编写!

5:注册机编写如下:

unit key;

interface

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

type
    TForm1 = class(TForm)
      SkinData1: TSkinData;
      Label1: TLabel;
      Label2: TLabel;
      Edit1: TEdit;
      Edit2: TEdit;
      Button1: TButton;
      Button2: TButton;
      Button3: TButton;
      Image1: TImage;
      Label3: TLabel;
      procedure Button2Click(Sender: TObject);
      procedure Button3Click(Sender: TObject);
      procedure Button1Click(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;

var
    Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
      Application.MessageBox('本注册机由壹只老虎制作!QQ:609841314','关于',MB_ICONINFORMATION+MB_OK);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
       Close;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   name:string;
   code:Longword;
   i:integer;
begin
       name:=edit1.Text;
       code:=0;
       if length(name)>10 then
         begin
                for i:=1 to 25 do
                  code:=(code+48)*1911;
         end
       else
         begin
                for i:=1 to length(name) do
                  code:=1911*(ord(name)+code);
         end;
       code:=2205442832 xor code;
       code:=code xor 1420678174;
       code:=code xor 2882395881;
       code:=code or 305279506;
       edit2.Text:=inttostr(code);
end;

end.

好了,就这样了!欢迎大家一起交流!共同进步!

--------------------------------------------------------------------------------
【经验总结】
这个东西是挺有意思的!呵呵!这次收获不少!欢迎大家一起交流!

--------------------------------------------------------------------------------
【版权声明】: BY:壹只老虎

                                                       2006年08月28日 22:19:47

wofan 发表于 2006-8-28 23:07:25

我顶你一下,你可愿意?

壹只老虎 发表于 2006-8-29 00:14:20

HEIHEI !谢谢兄弟支持

caterpilla 发表于 2006-8-30 08:03:59

支持。。。。。。

mwdir1025 发表于 2006-10-19 23:16:06

只有慢慢学了
页: [1]
查看完整版本: 一个挺有创意的crackme算法分析+注册机