首页
社区
课程
招聘
[原创]CrackMe2.0分析及注册机算法
发表于: 2009-5-31 10:29 12915

[原创]CrackMe2.0分析及注册机算法

2009-5-31 10:29
12915

【文章标题】: [原创]CrackMe2.0分析及注册机算法(含VC写的注册机)
【文章作者】: wuwenyao
【作者邮箱】: [email]wuwenyao.gm@gmail.com[/email]
【软件名称】: CrackMe 2.0
【下载地址】: http://www.unpack.cn/viewthread.php?tid=35910&extra=page%3D1&page=1
【使用工具】: ollydbg,IDA,dede
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------

  第一次写破文,第一次用IDA……,呵呵,太多第一次,发贴留念
  有的朋友没有unpack的帐号,搜索了一下,这个crackme在看雪也有:
  【原创】今年最后一个CrackMe 2.0
  今天发现,作者把源码也发了:
  【原创】今年最后一个CrackMe 2.0 源码

--------------------------------------------------------------------------------
【详细过程】
  这是UNPACK论坛出的unpackme_007,脱壳相对简单,在此略过。
  以下是算法分析:
  peid载入脱壳程序,显示Borland Delphi 6.0-7.0
  CM是delphi写的
  运行脱壳程序,随便填用户名和注册码,跳出对话框“注册码错误,请与软件开发商联系!”
  OD载入脱壳程序,随便填用户名和注册码,下断 bp MessageBoxA,点确定,没断下来,程序中止了:(,看来有anti-debug
  打开插件选项phant0m,选hide from PEB,点save,ctrl+F2重新载入,点Alt+b,禁用断点,F9运行,随便填用户名和注册码,Alt+b开启断点,F9,断在
  
  77D507EA >  8BFF            mov     edi, edi
  77D507EC    55              push    ebp
  77D507ED    8BEC            mov     ebp, esp
  77D507EF    833D BC14D777 0>cmp     dword ptr [77D714BC], 0
   
  Alt+b,禁用断点,Alt+C,ctrl+F9,切换回程序看到跳框了,点确定,断在
  
  00458FD3    8945 F8         mov     dword ptr [ebp-8], eax
  00458FD6    33C0            xor     eax, eax
  00458FD8    5A              pop     edx
  00458FD9    59              pop     ecx

  再按ctrl+F9 2次来到
  
  004857F4    33C0            xor     eax, eax            
  004857F6    5A              pop     edx
  004857F7    59              pop     ecx
  004857F8    59              pop     ecx
  
  往上一行看到
  
  004857EF    E8 F436FDFF     call    00458EE8                         ; 跳框

  跳框是在这里调用的了:)再往上看
  
  004857B8    6A 10           push    10
  004857BA    8D55 D0         lea     edx, dword ptr [ebp-30]
  004857BD    B8 6C584800     mov     eax, 0048586C                    ; ASCII "CCE1CABE"
  004857C2    E8 85F8FFFF     call    0048504C
  004857C7    8B45 D0         mov     eax, dword ptr [ebp-30]
  004857CA    E8 E9EBF7FF     call    004043B8
  004857CF    50              push    eax
  004857D0    8D55 CC         lea     edx, dword ptr [ebp-34]
  004857D3    B8 B8584800     mov     eax, 004858B8                    ; ASCII "D7A2B2E1C2EBB4EDCEF3A3ACC7EBD3EBC8EDBCFEBFAAB7A2C9CCC1AACFB5A3A1"
  004857D8    E8 6FF8FFFF     call    0048504C
  004857DD    8B45 CC         mov     eax, dword ptr [ebp-34]
  004857E0    E8 D3EBF7FF     call    004043B8
  004857E5    8BD0            mov     edx, eax
  004857E7    A1 0C744800     mov     eax, dword ptr [48740C]
  004857EC    8B00            mov     eax, dword ptr [eax]
  004857EE    59              pop     ecx
  004857EF    E8 F436FDFF     call    00458EE8                         ; 跳框

  几个call是在准备跳框用到的数据,再往上看

  004856B9    E8 4E3DFBFF     call    0043940C
  004856BE    8B45 FC         mov     eax, dword ptr [ebp-4]           ; 用户名处理
  004856C1    E8 02F9FFFF     call    00484FC8                         ; 检查用户名
  004856C6    84C0            test    al, al
  004856C8    0F84 EA000000   je      004857B8                         ; 跳框
  004856CE    8D4D F4         lea     ecx, dword ptr [ebp-C]
  004856D1    8B15 088D4800   mov     edx, dword ptr [488D08]
  004856D7    8B83 18030000   mov     eax, dword ptr [ebx+318]
  004856DD    E8 D2FCFFFF     call    004853B4
  004856E2    8B45 F4         mov     eax, dword ptr [ebp-C]
  004856E5    8D55 F8         lea     edx, dword ptr [ebp-8]
  004856E8    E8 132CF8FF     call    00408300
  004856ED    8B45 F8         mov     eax, dword ptr [ebp-8]
  004856F0    50              push    eax
  004856F1    8D55 F0         lea     edx, dword ptr [ebp-10]
  004856F4    8B83 04030000   mov     eax, dword ptr [ebx+304]
  004856FA    E8 0D3DFBFF     call    0043940C
  004856FF    8B55 F0         mov     edx, dword ptr [ebp-10]
  00485702    58              pop     eax
  00485703    E8 FCEBF7FF     call    00404304                        ; 关键call
  00485708    0F85 AA000000   jnz     004857B8                         ; 跳框
  0048570E    8D55 E8         lea     edx, dword ptr [ebp-18]
  00485711    8B83 04030000   mov     eax, dword ptr [ebx+304]
  00485717    E8 F03CFBFF     call    0043940C
  0048571C    8B45 E8         mov     eax, dword ptr [ebp-18]
  0048571F    8D55 EC         lea     edx, dword ptr [ebp-14]
  00485722    E8 E9EFFFFF     call    00484710
  00485727    8B45 EC         mov     eax, dword ptr [ebp-14]
  0048572A    50              push    eax
  0048572B    8D55 E4         lea     edx, dword ptr [ebp-1C]
  0048572E    8B83 FC020000   mov     eax, dword ptr [ebx+2FC]
  00485734    E8 D33CFBFF     call    0043940C
  00485739    8D45 E4         lea     eax, dword ptr [ebp-1C]
  0048573C    50              push    eax
  0048573D    8D55 E0         lea     edx, dword ptr [ebp-20]
  00485740    8B83 F8020000   mov     eax, dword ptr [ebx+2F8]
  00485746    E8 C13CFBFF     call    0043940C
  0048574B    8B55 E0         mov     edx, dword ptr [ebp-20]
  0048574E    58              pop     eax
  0048574F    E8 6CEAF7FF     call    004041C0
  00485754    8B55 E4         mov     edx, dword ptr [ebp-1C]
  00485757    58              pop     eax
  00485758    E8 A7EBF7FF     call    00404304                      ; 关键call
  0048575D    75 59           jnz     short 004857B8                   ; 跳框
  0048575F    6A 40           push    40
  
  有3处跳转
  ……
  004856C8    0F84 EA000000   je      004857B8
  ……
  00485708    0F85 AA000000   jnz     004857B8
  ……
  0048575D    75 59           jnz     short 004857B8
  ……

  是跳转到跳框部分代码,暴破把3处跳转屏蔽就可以了……
  
  再看看这个CM的算法,在几处跳转前的call用OD跟进去分析

  004856BE    8B45 FC         mov     eax, dword ptr [ebp-4]
  004856C1    E8 02F9FFFF     call    00484FC8
  
  两处是用户名处理和检查用户名最后一位是否为大小定字母(B-Y和b-y),如果不符合,在
  
  004856C8    0F84 EA000000   je      004857B8  

  处跳
  
  004856DD    E8 D2FCFFFF     call    004853B4

  处是按pixcel比较程序2处RGB值,并按是否相同(相同置0,不同置1)拼成串,并在
  
  00485703    E8 FCEBF7FF     call    00404304

  处与注册码比较,不相等就跳
  
  00485722    E8 E9EFFFFF     call    00484710

  处是处理注册码,并在
  
  00485758    E8 A7EBF7FF     call    00404304

  处与用户名+序列号进行比较,不相等就跳
  由于程序是delphi写的, 使用了大量的delphi封装、结构和函数调用,用OD分析,要跟入几层call的才搞清楚原来是delphi的封装,浪费大量时间。
  所以用IDA进行静态分析,并载入dede产生的map,使用idc进行delphi结构扫描,分析过程略过,下面是关键代码和分析过程中写的注释

  Tfrmmain_0_Formcreate分析
  ……
  CODE:004859CC                 mov     ebx, eax
  CODE:004859CE                 mov     edi, offset dword_488D08 ; 488D08->edi
  CODE:004859D3                 xor     eax, eax
  CODE:004859D5                 push    ebp
  ……
  CODE:00485AAB                 mov     eax, Timage_0_VmtPtr
  CODE:00485AB0                 call    _PROC_0042DB20  ; TCustomPanel._PROC_0042DB20();创建Tpicture
  CODE:00485AB5                 mov     [edi], eax      ; 句柄写入488D08
  CODE:00485AB7                 mov     edx, ebx
  CODE:00485AB9                 mov     eax, [edi]
  CODE:00485ABB                 mov     ecx, [eax]
  CODE:00485ABD                 call    dword ptr [ecx+68h]
  CODE:00485AC0                 xor     edx, edx
  CODE:00485AC2                 mov     eax, [edi]
  CODE:00485AC4                 call    TControl_SetLeft ; Controls.TControl.SetLeft(TControl;Integer);
  CODE:00485AC9                 mov     edx, -10h
  CODE:00485ACE                 mov     eax, [edi]
  CODE:00485AD0                 call    TControl_SetTop ; Controls.TControl.SetTop(TControl;Integer);
  CODE:00485AD5                 mov     edx, 157h
  CODE:00485ADA                 mov     eax, [edi]
  CODE:00485ADC                 call    TControl_SetWidth ; Controls.TControl.SetWidth(TControl;Integer);
  CODE:00485AE1                 mov     edx, 60h
  CODE:00485AE6                 mov     eax, [edi]
  CODE:00485AE8                 call    TControl_SetHeight ; Controls.TControl.SetHeight(TControl;Integer);
  CODE:00485AED                 mov     eax, [edi]
  CODE:00485AEF                 call    TControl_SendToBack ; Controls.TControl.SendToBack(TControl);
  CODE:00485AF4                 mov     eax, offset a3w_bmp ; "3w.bmp"
  CODE:00485AF9                 call    FileExists      ; SysUtils.FileExists(AnsiString):Boolean;检查文件是否存在
  CODE:00485AFE                 test    al, al
  CODE:00485B00                 jz      short loc_485B14
  CODE:00485B02                 mov     eax, [edi]
  CODE:00485B04                 mov     eax, [eax+168h]
  CODE:00485B0A                 mov     edx, offset a3w_bmp ; "3w.bmp"
  CODE:00485B0F                 call    TPicture_LoadFromFile ; Graphics.TPicture.LoadFromFile(TPicture;AnsiString);3w.bmp文件Load入Tpicture
  ……
  
  这部分的的功能是在建立窗口时,新建Tpicture,并从3w.bmp载入

  Tfrmmain_0_Btnokclick 分析
  ……
  CODE:004856B0                 lea     edx, [ebp+var_4]
  CODE:004856B3                 mov     eax, [ebx+2FCh] ; Edit_Name:TEdit
  CODE:004856B9                 call    TControl_GetText ; Controls.TControl.GetText(TControl):TCaption;
  CODE:004856BE                 mov     eax, [ebp+var_4] ; edit_name值
  CODE:004856C1                 call    sub_484FC8      ; 检查name值是否为空,最后一位是否字母
  CODE:004856C6                 test    al, al          ; 最后一位不是字母跳出
  CODE:004856C8                 jz      loc_4857B8
  CODE:004856CE                 lea     ecx, [ebp+var_C]
  CODE:004856D1                 mov     edx, ds:dword_488D08
  CODE:004856D7                 mov     eax, [ebx+318h] ; Image1:TImage
  CODE:004856DD                 call    sub_4853B4      ; 将image1和488D08处指向的3w.bmp进行运算
  CODE:004856E2                 mov     eax, [ebp+var_C] ; 将上个call产生string指针->EAX
  CODE:004856E5                 lea     edx, [ebp+var_8] ; 将var地址->edx做为接收地址
  CODE:004856E8                 call    Trim            ; SysUtils.Trim(AnsiString):AnsiString;overload;
  CODE:004856ED                 mov     eax, [ebp+var_8]
  CODE:004856F0                 push    eax             ; 处理后的string指针入栈
  CODE:004856F1                 lea     edx, [ebp+var_10]
  CODE:004856F4                 mov     eax, [ebx+304h] ; Edit_Code:TEdit
  CODE:004856FA                 call    TControl_GetText ; Controls.TControl.GetText(TControl):TCaption;
  CODE:004856FF                 mov     edx, [ebp+var_10] ; edit_code值
  CODE:00485702                 pop     eax
  CODE:00485703                 call    System_@LStrCmp ; System.@LStrCmp;
  CODE:00485708                 jnz     loc_4857B8      ; 比较code和string值,不符合跳出
  CODE:0048570E                 lea     edx, [ebp+var_18]
  CODE:00485711                 mov     eax, [ebx+304h] ; Edit_Code:TEdit
  CODE:00485717                 call    TControl_GetText ; Controls.TControl.GetText(TControl):TCaption;
  CODE:0048571C                 mov     eax, [ebp+var_18] ; 取code值
  CODE:0048571F                 lea     edx, [ebp+var_14]
  CODE:00485722                 call    sub_484710      ; code处理
  CODE:00485727                 mov     eax, [ebp+var_14] ; var_14为运算结果
  CODE:0048572A                 push    eax
  CODE:0048572B                 lea     edx, [ebp+var_1C]
  CODE:0048572E                 mov     eax, [ebx+2FCh] ; Edit_Name:TEdit
  CODE:00485734                 call    TControl_GetText ; Controls.TControl.GetText(TControl):TCaption;
  CODE:00485739                 lea     eax, [ebp+var_1C] ; 取name
  CODE:0048573C                 push    eax
  CODE:0048573D                 lea     edx, [ebp+var_20]
  CODE:00485740                 mov     eax, [ebx+2F8h] ; Edit_ID:TEdit
  CODE:00485746                 call    TControl_GetText ; Controls.TControl.GetText(TControl):TCaption;
  CODE:0048574B                 mov     edx, [ebp+var_20] ; 取ID
  CODE:0048574E                 pop     eax
  CODE:0048574F                 call    System_@LStrCat ; System.@LStrCat;
  CODE:00485754                 mov     edx, [ebp+var_1C] ; name+ID
  CODE:00485757                 pop     eax
  CODE:00485758                 call    System_@LStrCmp ; System.@LStrCmp;比较code运算结果和name+id
  CODE:0048575D                 jnz     short loc_4857B8
  ……
  
  这部分是注册码验证的主体部分,功能是:
  1.校验用户名
  2.将3w.bmp按象素与BMP1比较,并产生一个字串,字串再与注册码比较
  3.注册码运算后与用户名与序列号连接后产生的字符串比较

  call    sub_484FC8 处用户名检查分析
  ……
  CODE:00484FE9                 mov     eax, [ebp+var_4] ; 取name
  CODE:00484FEC                 call    sub_4041B8      ; 取name长度
  CODE:00484FF1                 mov     esi, eax
  CODE:00484FF3                 cmp     esi, 1
  CODE:00484FF6                 jge     short loc_484FFD
  CODE:00484FF8                 call    @Sysutils@Abort$qqrv ; Sysutils::Abort(void)
  CODE:00484FFD
  CODE:00484FFD loc_484FFD:                             ; CODE XREF: sub_484FC8+2Ej
  CODE:00484FFD                 mov     eax, esi
  CODE:00484FFF                 test    eax, eax
  CODE:00485001                 jl      short loc_485027
  CODE:00485003                 inc     eax
  CODE:00485004                 xor     edx, edx        ; byte指针初始化
  CODE:00485006
  CODE:00485006 loc_485006:                             ; CODE XREF: sub_484FC8+5Dj
  CODE:00485006                 mov     ecx, [ebp+var_4] ; 取name
  CODE:00485009                 mov     cl, [ecx+edx-1] ; 取一个byte
  CODE:0048500D                 add     cl, 0BEh        ; -0xBE=0x42(B)
  CODE:00485010                 sub     cl, 18h         ; 0x18=24
  CODE:00485013                 jb      short loc_485021 ; 在0x42-0x59间(B-Y),bl置1
  CODE:00485015                 add     cl, 0F8h        ; -0xF8+0x18-0xbe=0x62(b)
  CODE:00485018                 sub     cl, 18h
  CODE:0048501B                 jb      short loc_485021 ; 在0x62-0x79间(b-y),bl置1
  CODE:0048501D                 xor     ebx, ebx
  CODE:0048501F                 jmp     short loc_485023 ; byte指针加1
  CODE:00485021 ; ---------------------------------------------------------------------------
  CODE:00485021
  CODE:00485021 loc_485021:                             ; CODE XREF: sub_484FC8+4Bj
  CODE:00485021                                         ; sub_484FC8+53j
  CODE:00485021                 mov     bl, 1
  CODE:00485023
  CODE:00485023 loc_485023:                             ; CODE XREF: sub_484FC8+57j
  CODE:00485023                 inc     edx             ; byte指针加1
  CODE:00485024                 dec     eax             ; 循环指针-1
  CODE:00485025                 jnz     short loc_485006 ; 取name
  ……

  这部分是用户名校验过程  

  call    sub_4853B4处picture比较分析
  ……
  CODE:004853E3                 mov     [ebp+var_11], 0 ; 初始化var_11
  CODE:004853E7                 mov     eax, [ebp+var_4] ; var_4为原EAX值
  CODE:004853EA                 mov     eax, [eax+168h]
  CODE:004853F0                 call    TPicture_GetBitmap ; BDS 2005-2006 and Delphi6-7 Visual Component Library
  CODE:004853F5                 mov     edx, [eax]      ; EAX指向tbitmap
  CODE:004853F7                 call    dword ptr [edx+20h] ; Graphics::TBitmap::GetHeight(void)
  CODE:004853FA                 dec     eax             ; EAX=BitMap高度
  CODE:004853FB                 test    eax, eax
  CODE:004853FD                 jl      loc_4854AC
  CODE:00485403                 inc     eax
  CODE:00485404                 mov     [ebp+var_18], eax
  CODE:00485407                 mov     [ebp+var_10], 0
  CODE:0048540E
  CODE:0048540E loc_48540E:                             ; CODE XREF: sub_4853B4+F2j
  CODE:0048540E                 mov     eax, [ebp+var_4]
  CODE:00485411                 mov     eax, [eax+168h]
  CODE:00485417                 call    TPicture_GetBitmap ; BDS 2005-2006 and Delphi6-7 Visual Component Library
  CODE:0048541C                 mov     edx, [eax]
  CODE:0048541E                 call    dword ptr [edx+2Ch] ; Graphics::TBitmap::GetWidth(void)
  CODE:00485421                 dec     eax             ; EAX=BitMap宽度
  CODE:00485422                 test    eax, eax
  CODE:00485424                 jl      short loc_4854A0 ; y++
  CODE:00485426                 inc     eax
  CODE:00485427                 mov     [ebp+var_1C], eax
  CODE:0048542A                 xor     esi, esi
  CODE:0048542C
  CODE:0048542C loc_48542C:                             ; CODE XREF: sub_4853B4+EAj
  CODE:0048542C                 mov     eax, [ebp+var_4] ; var_4为原EAX值
  CODE:0048542F                 mov     eax, [eax+168h]
  CODE:00485435                 call    TPicture_GetBitmap ; BDS 2005-2006 and Delphi6-7 Visual Component Library
  CODE:0048543A                 call    @Graphics@TBitmap@GetCanvas$qqrv ; Graphics::TBitmap::GetCanvas(void)
  CODE:0048543F                 mov     ecx, [ebp+var_10] ; X值
  CODE:00485442                 mov     edx, esi        ; Y值
  CODE:00485444                 call    @Graphics@TCanvas@GetPixel$qqrii ; Graphics::TCanvas::GetPixel(int,int)
  CODE:00485449                 mov     edi, eax        ; pixel的RGB值放入EDI
  CODE:0048544B                 mov     eax, [ebp+var_8] ; var_8为原EDX值
  CODE:0048544E                 mov     eax, [eax+168h]
  CODE:00485454                 call    TPicture_GetBitmap ; BDS 2005-2006 and Delphi6-7 Visual Component Library
  CODE:00485459                 call    @Graphics@TBitmap@GetCanvas$qqrv ; Graphics::TBitmap::GetCanvas(void)
  CODE:0048545E                 mov     ecx, [ebp+var_10] ; X值
  CODE:00485461                 mov     edx, esi        ; Y值
  CODE:00485463                 call    @Graphics@TCanvas@GetPixel$qqrii ; Graphics::TCanvas::GetPixel(int,int)
  CODE:00485468                 cmp     edi, eax
  CODE:0048546A                 jz      short loc_48546F
  CODE:0048546C                 or      [ebp+var_11], bl ; 比较两组RGB值,相同处置var_11相应位为0,不同处置相应位为1
  CODE:0048546F
  CODE:0048546F loc_48546F:                             ; CODE XREF: sub_4853B4+B6j
  CODE:0048546F                 xor     eax, eax
  CODE:00485471                 mov     al, bl
  CODE:00485473                 shr     eax, 1          ; 初始值80,每次右移1位,8次跳出,bit->byte
  CODE:00485475                 mov     ebx, eax
  CODE:00485477                 test    bl, bl
  CODE:00485479                 jnz     short loc_48549A ; x++
  CODE:0048547B                 lea     eax, [ebp+var_20]
  CODE:0048547E                 mov     dl, [ebp+var_11]
  CODE:00485481                 call    unknown_libname_67 ; 把var_11转化为string,返回指针
  CODE:00485486                 mov     edx, [ebp+var_20] ; 把string返回指针放入EDX
  CODE:00485489                 mov     eax, [ebp+var_C] ; 原ECX值
  CODE:0048548C                 call    System_@LStrCat ; var_11转换值放入var_c指针指向的字符串尾
  CODE:00485491                 mov     eax, [ebp+var_C]
  CODE:00485494                 mov     bl, 80h         ; 初始化bl
  CODE:00485496                 mov     [ebp+var_11], 0 ; 初始化var_11
  CODE:0048549A
  CODE:0048549A loc_48549A:                             ; CODE XREF: sub_4853B4+C5j
  CODE:0048549A                 inc     esi             ; x++
  CODE:0048549B                 dec     [ebp+var_1C]    ; 高度指针-1
  CODE:0048549E                 jnz     short loc_48542C ; 高度指针指向0跳出
  CODE:004854A0
  CODE:004854A0 loc_4854A0:                             ; CODE XREF: sub_4853B4+70j
  CODE:004854A0                 inc     [ebp+var_10]    ; y++
  CODE:004854A3                 dec     [ebp+var_18]    ; 宽度指针-1
  CODE:004854A6                 jnz     loc_48540E      ; 宽度指针指向0跳出
  ……
  
  这部分是3w.bmp与BMP1比较产生字符串的过程

  call    sub_484710处注册码处理分析
    ……
  CODE:00484723                 mov     esi, edx        ; 指针放入esi
  CODE:00484725                 mov     [ebp+var_4], eax ; code值地址放入var_4
  CODE:00484728                 mov     eax, [ebp+var_4]
  CODE:0048472B                 call    @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *)
  CODE:00484730                 mov     ebx, offset aAbcdefghijklmn ; 引入字符表A,字符表地址放入ebx
  CODE:00484735                 xor     eax, eax
  ……
  CODE:00484747                 jz      loc_48496E      ; code为空跳出
  CODE:0048474D                 lea     eax, [ebp+var_10]
  CODE:00484750                 mov     dl, [ebx+29h]
  CODE:00484753                 mov     [eax+1], dl
  CODE:00484756                 mov     byte ptr [eax], 1 ; var_10低位=1 高位=字符表+29h(O)
  CODE:00484759                 lea     edx, [ebp+var_10]
  CODE:0048475C                 lea     eax, [ebp+var_14]
  CODE:0048475F                 call    @System@@PStrCpy$qqrp28System@_SmallString$iuc$255_t1 ; System::__linkproc__ PStrCpy(System::SmallString<(uchar)255> *,System::SmallString<(uchar)255> *)
  CODE:00484764                 lea     eax, [ebp+var_18]
  CODE:00484767                 mov     dl, [ebx+2]
  CODE:0048476A                 mov     [eax+1], dl
  CODE:0048476D                 mov     byte ptr [eax], 1 ; var_18低位=1,高位=字符表+2h(b)
  ……
  CODE:0048493B                 lea     eax, [ebp+var_9C]
  CODE:00484941                 mov     cl, 0Eh
  CODE:00484943                 call    @System@@PStrNCat$qqrv ; System::__linkproc__ PStrNCat(void)
  CODE:00484948                 lea     edx, [ebp+var_9C] ; var_9c=0E4F626A656374466F725A312E3021h(ObjectForZ1.0!)
  CODE:0048494E                 lea     eax, [ebp+var_8]
  CODE:00484951                 call    unknown_libname_70 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
  CODE:00484956                 lea     edx, [ebp+var_C] ; 处理后的字符表A为ObjectForZ1.0!,string(ObjectForZ1.0!)地址->var_8
  CODE:00484959                 mov     eax, [ebp+var_4] ; 取Code
  CODE:0048495C                 call    sub_484420      ; code处理
  CODE:00484961                 mov     ecx, esi        ; 指针
  CODE:00484963                 mov     edx, [ebp+var_8] ; 处理后的字符表A指针
  CODE:00484966                 mov     eax, [ebp+var_C] ; 处理后的code指针
  CODE:00484969                 call    sub_484578      ; 再加入2个字符表,运算后再分为两个0xA长度的表并根据处理后code的长度进行运算
  ……
   
  这部分的功能是对注册码进行运算,具体分为:
  1.由字符表A产生字符串“ObjectForZ1.0!”
  2.引入一个长度为64的字符串“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”对注册码进行第一次处理
  3.由1和2产的字符串,再引入2张字符表, 进行运算,得到最终结果

  call    sub_484420处注册码第一次处理分析,引入长度为0x3F(63)的字符表B
  ……
  CODE:00484477                 mov     eax, edi        ; code分成4个byte一组处理
  CODE:00484479                 shl     eax, 2
  CODE:0048447C                 inc     eax             ; edi*4+1
  CODE:0048447D                 mov     edx, [ebp+var_4] ; edx=code地址
  CODE:00484480                 mov     al, [edx+eax-1] ; 取edi*4位
  CODE:00484484                 call    sub_4843CC      ; 取在字母表中位置
  CODE:00484489                 mov     [ebp+var_5], al ; var_5=第1个字符在字母表中位置
  CODE:0048448C                 mov     eax, edi
  CODE:0048448E                 shl     eax, 2
  CODE:00484491                 add     eax, 2          ; edi*4+2
  CODE:00484494                 mov     edx, [ebp-4]    ; 取code
  CODE:00484497                 mov     al, [edx+eax-1] ; 取edi*4+1位
  CODE:0048449B                 call    sub_4843CC      ; 取在字母表中位置
  CODE:004844A0                 mov     [ebp+var_6], al ; var_6=第2个字符在字母表中位置
  CODE:004844A3                 mov     eax, edi
  CODE:004844A5                 shl     eax, 2
  CODE:004844A8                 add     eax, 3
  CODE:004844AB                 mov     edx, [ebp+var_4]
  CODE:004844AE                 mov     al, [edx+eax-1]
  CODE:004844B2                 call    sub_4843CC      ; 取在字母表中位置
  CODE:004844B7                 mov     ebx, eax        ; ebx=第3个字符在字母表中位置
  CODE:004844B9                 mov     eax, edi
  CODE:004844BB                 shl     eax, 2
  CODE:004844BE                 add     eax, 4
  CODE:004844C1                 mov     edx, [ebp+var_4]
  CODE:004844C4                 mov     al, [edx+eax-1]
  CODE:004844C8                 call    sub_4843CC      ; 取在字母表中位置
  CODE:004844CD                 mov     [ebp+var_7], al ; var_7=第4个字符在字母表中位置
  CODE:004844D0                 shl     [ebp+var_5], 2  ; var_5<<2
  CODE:004844D4                 xor     eax, eax
  CODE:004844D6                 mov     al, [ebp+var_6]
  CODE:004844D9                 shr     eax, 4
  CODE:004844DC                 or      [ebp+var_5], al ; var_5<<2|var_6>>4
  CODE:004844DF                 shl     [ebp+var_6], 4  ; var_6<<4
  CODE:004844E3                 lea     eax, [ebp+var_10]
  CODE:004844E6                 mov     dl, [ebp+var_5] ; 计算后,第2-7位为第1字符在字符表中索引,第0-1位为第2字符在字符表中索引的4-5位
  CODE:004844E9                 call    unknown_libname_67 ; string()
  CODE:004844EE                 mov     edx, [ebp+var_10]
  CODE:004844F1                 mov     eax, esi
  CODE:004844F3                 call    System_@LStrCat ; var_10填入esi指向的string
  CODE:004844F8                 cmp     bl, 40h
  CODE:004844FB                 jz      short loc_484546 ; bl=40h跳出
  CODE:004844FD                 xor     eax, eax
  CODE:004844FF                 mov     al, bl
  CODE:00484501                 shr     eax, 2
  CODE:00484504                 or      [ebp+var_6], al ; var_6|bl>>2
  CODE:00484507                 shl     bl, 6           ; bl<<6
  CODE:0048450A                 lea     eax, [ebp+var_14]
  CODE:0048450D                 mov     dl, [ebp+var_6] ; 计算后,第4-7位为第2字符在字符表中索引的0-3位,第0-3位为第3字符在字符表中索引的2-5位
  CODE:00484510                 call    unknown_libname_67 ; string()
  CODE:00484515                 mov     edx, [ebp+var_14]
  CODE:00484518                 mov     eax, esi
  CODE:0048451A                 call    System_@LStrCat ; var_14->esi指向的string
  CODE:0048451F                 cmp     [ebp+var_7], 40h
  CODE:00484523                 jz      short loc_484546 ; var_7=40跳出
  CODE:00484525                 or      bl, [ebp+var_7] ; bl<<6|var_7
  CODE:00484528                 lea     eax, [ebp+var_18]
  CODE:0048452B                 mov     edx, ebx        ; 计算后,第6-7位为第3字符在字符表中索引的0-1位,第0-5位为第4字符在字符表中索引
  CODE:0048452D                 call    unknown_libname_67 ; string()
  CODE:00484532                 mov     edx, [ebp+var_18]
  CODE:00484535                 mov     eax, esi
  CODE:00484537                 call    System_@LStrCat ; var_18->esi指向的string
  CODE:0048453C                 inc     edi             ; edi++
  CODE:0048453D                 dec     [ebp+var_C]     ; 计数指针--
  CODE:00484540                 jnz     loc_484477      ; code分成4个byte一组处理
  ……
  这部分是把注册码(code)按4个字节分成段,引入一个64字节长的字串“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”(code3),每段按字节在字串中的索引组成1个3字节长的串,最终形成一个长度为注册码长度3/4的串key。C的等同算法:

len=strlen(code);
for (i=0,i<len,i=i+4)
{
  key[i/4*3]=(strchr(code3,code[i])-code3)<<2|(strchr(code3,code[i+1])-code3)>>4;
  key[i/4*3+1]=(strchr(code3,code[i+1])-code3)<<4|(strchr(code3,code[i+2])-code3)>>2;
  key[i/4*3+2]=(strchr(code3,code[i+2])-code3)<<6|(strchar(code3,code[i+3])-code3);
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (20)
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
2
不错,学习了.
2009-5-31 10:39
0
雪    币: 319
活跃值: (49)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
牛。

只是感觉注释不怎么详细。。。。。。
2009-5-31 13:55
0
雪    币: 423
活跃值: (11)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
4
UNPACKME 006 对 手动脱壳满难的,反调试挺耗时间的。

端午大部分的休闲时间都耗上面了。

注释很详细了,学习。。。
2009-5-31 18:32
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
那个论坛我没权限下载啊
2009-5-31 19:51
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
6
请问你是那个 ID ?
2009-5-31 20:24
0
雪    币: 423
活跃值: (11)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
7
今天才注册的,NBA2005.

主要是手动脱壳练习和反调试.
2009-5-31 22:46
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
8
多多指教
你应该很快能发挥出来的
2009-6-1 00:13
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
值得我学习的好文章。
2009-6-1 00:15
0
雪    币: 423
活跃值: (11)
能力值: ( LV9,RANK:230 )
在线值:
发帖
回帖
粉丝
10
还要靠大侠多多提携!

扎实基本功,
学习无止境。
不敢高声语,
恐惊大牛侠。

楼主就是学习的榜样。

见面礼之水贴,手动脱壳的概述:
http://www.unpack.cn/viewthread.php?tid=36528&extra=page%3D1
2009-6-1 09:15
0
雪    币: 1074
活跃值: (160)
能力值: ( LV13,RANK:760 )
在线值:
发帖
回帖
粉丝
11
学习不刻苦,不如卖红薯....
2009-6-1 10:13
0
雪    币: 334
活跃值: (151)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
对不起,注册机是用vs2008写的,生成时选项搞好,在没装vs2008的机器上运行会出错,已经改好,更新了附件
2009-6-3 21:38
0
雪    币: 334
活跃值: (151)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
13
虽然没拿到精华,毕竟是在看雪发的第一篇文章,有空还是整理了一下
2009-6-9 13:12
0
雪    币: 318
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
来学习!!!!!!!!!
2009-6-11 09:07
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
楼主辛苦,学习了!!!!!!!!!!!
2009-6-11 11:40
0
雪    币: 4687
活跃值: (253)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
辛苦了!不错!学习了!!!!!!!!!!!!!!!!!!!!!!!!!!!
2009-6-12 19:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
学习,很深奥。。
2009-6-12 20:02
0
雪    币: 455
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
wuwenyao的基础扎实呀!
2009-9-2 02:10
0
雪    币: 161
活跃值: (261)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
下載試試看.
感恩
2010-7-10 18:22
0
雪    币: 97697
活跃值: (200839)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
20
sustain.
2010-7-10 18:37
0
雪    币: 145
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
有见地,学习啦
2010-7-20 18:19
0
游客
登录 | 注册 方可回帖
返回
//