• 标 题:文件密使2.6注册码分析详解 (11千字)
  • 作 者:[tieji]
  • 时 间:2001-11-30 8:52:49
  • 链 接:http://bbs.pediy.com

破解者:tieji
破解时间:2001-11-28
破解工具:TRW2000 V1.23  W32dasm黄金版
作者主页:http://www.wjmshome.com

启动软件,弹出注册框,填入注册信息:
注册名:caoxinyu 
注册码:5432112345  <----随便填
打开TRW2000,下断点bpx hmemcpy,点确定,被拦下。
按F10来到:

:00413887 E816540000              Call 00418CA2
:0041388C 8D8E001B0000            lea ecx, dword ptr [esi+00001B00]
:00413892 E817C2FFFF              call 0040FAAE  <=====关键的call,分析比较注册码,跟进
:00413897 85C0                    test eax, eax  <=====eax是否为零
:00413899 751E                    jne 004138B9  <=====不为零,正确就跳[多经典!]
:0041389B 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"warning"
                                  |
:0041389D 68C4614200              push 004261C4

* Possible StringData Ref from Data Obj ->"注册码错误,请重新输入"
                                  |
:004138A2 6820784200              push 00427820
:004138A7 8BCB                    mov ecx, ebx

=============================================================================================
关键的cal:
* Referenced by a CALL at Addresses:
|:0040702B  , :00413892 
|
:0040FAAE B820B64100              mov eax, 0041B620

* Reference To: MSVCRT._EH_prolog, Ord:0042h
                                  |         
:0040FAB3 E858960000              Call 00419110
:0040FAB8 83EC2C                  sub esp, 0000002C  <==== esp-0x2c
:0040FABB 56                      push esi          <==== 保存esi
:0040FABC 57                      push edi          <==== 保存edi
:0040FABD 8B7D08                  mov edi, dword ptr [ebp+08]  <==== 将ebp+08的内容传给edi,即将
                                                                用户名caoxinyu所在的地址传给edi
:0040FAC0 33F6                    xor esi, esi      <====esi清零
:0040FAC2 8975EC                  mov dword ptr [ebp-14], esi  <====ebp-14处的内容清零
:0040FAC5 8B4FF8                  mov ecx, dword ptr [edi-08]  <====将用户名长度(本例为8)传给ecx
:0040FAC8 3BCE                    cmp ecx, esi      <====比较用户名长度是否为零
:0040FACA 0F84AD000000            je 0040FB7D        <====为零跳到0040FB7D (本例不为零不跳)
:0040FAD0 83F920                  cmp ecx, 00000020  <====比较用户名长度是否为32位
:0040FAD3 7E03                    jle 0040FAD8      <====小于32位就跳到0040FAD8
:0040FAD5 6A20                    push 00000020      <====大于32位就将32给ecx
:0040FAD7 59                      pop ecx            <====既用户名长度截取前32位

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAD3(C)
|
:0040FAD8 3BCE                    cmp ecx, esi      <====用户名长度与零比较
:0040FADA 7E13                    jle 0040FAEF      <====小于等于零就跳
:0040FADC 8D45C8                  lea eax, dword ptr [ebp-38]    <====eax装入ebp-38的地址
:0040FADF 2BF8                    sub edi, eax      <====edi-eax-->edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAED(C)
|
:0040FAE1 8D4435C8                lea eax, dword ptr [ebp+esi-38]  <====eax装入ebp+esi-38的地址
:0040FAE5 46                      inc esi            <====esi加1
:0040FAE6 3BF1                    cmp esi, ecx      <====esi与ecx用户名长度比较
:0040FAE8 8A1407                  mov dl, byte ptr [edi+eax]    <====将用户名的一个字母传给dl
:0040FAEB 8810                    mov byte ptr [eax], dl        <====将用户名的一个字母放入eax所
                                                                    在的地址中
:0040FAED 7CF2                    jl 0040FAE1        <====循环将用户名caoxinyu依次放到eax所指的地址中

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FADA(C)                        <====用户名长度小于等于零跳到这里
|
:0040FAEF 83F920                  cmp ecx, 00000020  <==== 比较用户名长度是否为32位
:0040FAF2 53                      push ebx            <==== 保存ebx
:0040FAF3 7D2C                    jge 0040FB21        <==== 大于等于32位跳
:0040FAF5 8D7DC8                  lea edi, dword ptr [ebp-38]  <====edi装入ebp-38所指的内容
:0040FAF8 8D45C8                  lea eax, dword ptr [ebp-38]  <====eax装入ebp-38所指的内容
                                                          即将放有caoxinyu处的地址-->edi,eax
:0040FAFB 4F                      dec edi            <====edi-1
:0040FAFC 2BC7                    sub eax, edi        <====eax-edi--->eax 即eax=0x1
:0040FAFE 8945F0                  mov dword ptr [ebp-10], eax  <====eax-->[ebp-10]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB1F(C)
|
:0040FB01 8A1C0F                  mov bl, byte ptr [edi+ecx]  <====将用户名的最后一个字母(本例为u)-->bl
:0040FB04 8D340F                  lea esi, dword ptr [edi+ecx]<====esi装入u所在的地址
:0040FB07 0FB6C3                  movzx eax, bl    <====将u放入eax
:0040FB0A 99                      cdq              <====双字节扩展 edx为00000000
:0040FB0B F7F9                    idiv ecx        <====除ecx 即0x75/0x8 即eax中为0xE,edx中为0x5
:0040FB0D 8BD0                    mov edx, eax    <====eax-->edx 即edx为0xE
:0040FB0F 8AC3                    mov al, bl      <====bl--->al  即al=0x75
:0040FB11 F6E9                    imul cl          <====乘cl 即0x75*0x8=0x3A8 --->eax
:0040FB13 02D0                    add dl, al      <====dl+al-->dl 即0xE+0xA8=0xB6-->dl
:0040FB15 8B45F0                  mov eax, dword ptr [ebp-10]  <====[ebp-10]--->eax=0x1
:0040FB18 41                      inc ecx          <====ecx+1
:0040FB19 83F920                  cmp ecx, 00000020    <====ecx与32比较,即用户名长度是否到了32位
:0040FB1C 881430                  mov byte ptr [eax+esi], dl  <====将0xB6放到用户名的最后一个字母
                                                                  "u"的后面
:0040FB1F 7CE0                    jl 0040FB01        <====用户名长度是不到32位就循环

注:上面这个循环是将用户名不到32位的补齐到32位,以用户名为caoxinyu为例计算如下:
第一次循环:
      0x75/0x8=0xE
      0x75*0x8=0xA8 因用al寄存器计算,故0x3A8-->0xA8
      0xE+0xA8=0xB6
    将计算所得的0xB6接到用户名caoxinyu的后面,变为:63616F78696E7975B6
第二次循环:
      0xB6/0x9=0x14
      0xB6*0x9=0x66
      0x14+0x66=0x7A
    将计算所得的0x7A再接到用户名的后面,变为:63616F78696E7975B67A
如此经过32-8次循环,补齐到32位的用户名为:
    63616F78696E7975B67AD0021839220000000000000000000000000000000000
     
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAF3(C)                        <===========用户名长度大于等于32位跳到这里
|
:0040FB21 33F6                    xor esi, esi                  <====esi清零
:0040FB23 8975F0                  mov dword ptr [ebp-10], esi  <====ebp-10处内容清零

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB59(C)                 
|                                <======四次循环开始,为何是四次循环,见下面说明:
:0040FB26 8B45F0                  mov eax, dword ptr [ebp-10]    <====将ebp-10的内容-->eax
:0040FB29 806435E800              and byte ptr [ebp+esi-18], 00  <====和0x00与
:0040FB2E 8D4C35E8                lea ecx, dword ptr [ebp+esi-18]<====ebp+esi-18的地址-->ecx
:0040FB32 6A04                    push 00000004          <====
:0040FB34 99                      cdq                    <====双字节扩展
:0040FB35 5B                      pop ebx                <====将0x4放入ebx
:0040FB36 33FF                    xor edi, edi          <====edi清零
:0040FB38 F7FB                    idiv ebx              <====eax/0x4
:0040FB3A 8A19                    mov bl, byte ptr [ecx] <====bl=0
:0040FB3C 8D4405C8                lea eax, dword ptr [ebp+eax-38] <====将ebp+eax-38的地址-->eax
                            即ebp-38为用户名所在的地方,ebp+eax-38 就是用户名所在的地址+eax 
                             
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB49(C)
|
:0040FB40 8A1438                  mov dl, byte ptr [eax+edi]  <====将eax+edi所在的内容-->dl
:0040FB43 32DA                    xor bl, dl                  <====bl^dl-->bl
:0040FB45 47                      inc edi                    <====edi+1
:0040FB46 83FF08                  cmp edi, 00000008          <====循环8次
:0040FB49 7CF5                    jl 0040FB40                 
:0040FB4B 8345F020                add dword ptr [ebp-10], 00000020  <====加20
:0040FB4F 46                      inc esi                          <====esi+1
:0040FB50 817DF080000000          cmp dword ptr [ebp-10], 00000080  <====与0x80比较
:0040FB57 8819                    mov byte ptr [ecx], bl            <====bl-->[ecx]
:0040FB59 7CCB                    jl 0040FB26          <====循环,因每次加20,加到80,所以循环四次

注:上面有两个循环,循环中套循环
  因已得到32位的用户名16进制为:63616F78696E7975B67AD0021839220000000000000000000000000000000000
第一次循环:(第一个字母c , 16进制为:63)
  0x63^0x61=0x2
    0x2^0x6F=0x6D
  如此循环8次最后得到0x1E
第二次循环:(第九个字母16进制为:B6)
    0xB6^0x7A=0xCC
    0xCC^0xD0=0x1C
  如此循环8次最后得到0x1D
第三次循环:同理最后得到00
第四次循环:同理最后得到00
将四次循环所得的结果反过来看00001D1E即为正确的注册码,不过要将他转换为十进制数.               

:0040FB5B 8B45EC                  mov eax, dword ptr [ebp-14]    <====[ebp-14]-->eax
:0040FB5E 6A03                    push 00000003                  <====
:0040FB60 59                      pop ecx                        <====3放入ecx
:0040FB61 5B                      pop ebx                        <====还原ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB71(C)
|
:0040FB62 0FB6540DE8              movzx edx, byte ptr [ebp+ecx-18]
:0040FB67 03C2                    add eax, edx          <=====eax+edx-->eax
:0040FB69 85C9                    test ecx, ecx
:0040FB6B 7406                    je 0040FB73          <====ecx为零跳
:0040FB6D C1E008                  shl eax, 08          <====左移8位
:0040FB70 49                      dec ecx              <====ecx-1
:0040FB71 79EF                    jns 0040FB62
                                            <=====上面的循环将正确的注册码放入eax中

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB6B(C)
|
:0040FB73 2B450C                  sub eax, dword ptr [ebp+0C] <====将eax中正确的注册码与输入的假
                                                                  注册码相减
:0040FB76 F7D8                    neg eax            <====取eax二补码
:0040FB78 1BC0                    sbb eax, eax        <====借位减
:0040FB7A 40                      inc eax            <====eax+1 若为0表示注册码错误,0x1表示正确
:0040FB7B 8BF0                    mov esi, eax        <====eax-->esi 注册标记保存

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FACA(C)                                  <====用户名长度为零跳到这里
|
:0040FB7D 834DFCFF                or dword ptr [ebp-04], FFFFFFFF
:0040FB81 8D4D08                  lea ecx, dword ptr [ebp+08]

* Reference To: MFC42.Ordinal:0320, Ord:0320h
                                  |
:0040FB84 E8E78F0000              Call 00418B70
:0040FB89 8B4DF4                  mov ecx, dword ptr [ebp-0C]
:0040FB8C 8BC6                    mov eax, esi        <====esi--->eax 注册标记传给eax
:0040FB8E 5F                      pop edi
:0040FB8F 5E                      pop esi
:0040FB90 64890D00000000          mov dword ptr fs:[00000000], ecx
:0040FB97 C9                      leave
:0040FB98 C20800                  ret 0008

写得真累,希望能给初学者有帮助,也望各位大侠指教........