【文章标题】: Registry Crawler 4.0 算法分析
【文章作者】: Suyana
【作者邮箱】: Suyasha@163.com
【软件名称】: Registry Crawler 4.0
【加壳方式】: 无壳
【使用工具】: OD
【软件介绍】: 一款很好的注册表搜索软件
【作者声明】: 我只是一只小菜鸟,失误之处难免,敬望诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  软件没有加壳,用OD载入,我用的是汉化版。查找字符串"你输入的注册信息是无效的"。来到:
  
  0040AFE1      lea     ecx, [esi+3BC]
  0040AFE7      call    0042D9F5                        ;  获得用户名
  0040AFEC      push    0FF
  0040AFF1      push    0045E610
  0040AFF6      lea     ecx, [esi+380]
  0040AFFC      call    0042D9F5                        ;  获得注册码
  0040B001      push    0045E510
  0040B006      lea     ecx, [esp+C]
  0040B00A      call    0042E405
  0040B00F      mov     eax, [eax]
  0040B011      push    00458C84                        ; /trial user
  0040B016      push    eax                             ; |Arg1
  0040B017      call    004196DB                        ; \rcrawler.004196DB
  0040B01C      add     esp, 8                          ; 比较用户名是否等于trial user
  0040B01F      lea     ecx, [esp+8]
  0040B023      test    eax, eax
  0040B025      sete    bl
  0040B028      call    0042E397
  0040B02D      test    bl, bl
  0040B02F      je      short 0040B040
  0040B031      push    1
  0040B033      mov     ecx, esi
  0040B035      call    0042F015
  0040B03A      pop     esi
  0040B03B      pop     ebx
  0040B03C      add     esp, 8
  0040B03F      retn
  0040B040      call    0040ACF0                        ; 这就是计算注册码并判断的函数了,进入
  0040B045      test    eax, eax
  0040B047      je      0040B0EA                        ; 跳到0040B0EA,即注册失败
  ...
  0040B0EA      mov     ecx, esi
  0040B0EC      call    0040AB00
  0040B0F1      test    eax, eax
  0040B0F3      je      short 0040B10E
  ...
  0040B10E      push    30
  0040B110      push    00458DA0                       ; 试用用户
  0040B115      push    00458C90                       ; 你输入的注册信息是无效的
  0040B11A      mov     ecx, esi
  
  F7进入0040B040      call    0040ACF0,来到:
  
  0040ACF0      sub     esp, 24
  0040ACF3      or      ecx, FFFFFFFF
  0040ACF6      xor     eax, eax
  0040ACF8      push    ebp
  0040ACF9      push    edi
  0040ACFA      mov     edi, 0045E510
  0040ACFF      repne   scas byte ptr es:[edi]
  0040AD01      not     ecx
  0040AD03      dec     ecx
  0040AD04      mov     ebp, ecx
  0040AD06      cmp     ebp, 8                        ; 用户名至少为8位才跳转
  0040AD09      jge     short 0040AD11                ; 计算注册码
  ...
  0040AD11      push    ebx
  0040AD12      push    esi
  0040AD13      push    0045E510
  0040AD18      call    00427D62                      ; 处理用户名,大写字母变成小写
  0040AD1D      mov     ecx, 7
  0040AD22      xor     eax, eax
  0040AD24      lea     edi, [esp+19]
  0040AD28      mov     byte ptr [esp+18], 0
  0040AD2D      rep     stos dword ptr es:[edi]
  0040AD2F      stos    word ptr es:[edi]
  0040AD31      add     esp, 4
  0040AD34      stos    byte ptr es:[edi]
  0040AD35      lea     eax, [esp+14]
  0040AD39      push    00458BE4                       ; /8267-      ;第一部分注册码
  0040AD3E      push    eax                            ; |String1
  0040AD3F      call    [<&KERNEL32.lstrcpyA>]         ; \lstrcpyA
  0040AD45      xor     ebx, ebx
  0040AD47       /mov     esi, [458AFC]                ; 0123456789 算是表吧
  0040AD4D       |or      ecx, FFFFFFFF
  0040AD50       |mov     edi, esi
  0040AD52       |xor     eax, eax
  0040AD54       |repne   scas byte ptr es:[edi]
  0040AD56       |not     ecx
  0040AD58       |dec     ecx
  0040AD59       |mov     eax, ebx
  0040AD5B       |xor     edx, edx
  0040AD5D       |mov     edi, esi
  0040AD5F       |div     ecx
  0040AD61       |mov     eax, ebx
  0040AD63       |push    1
  0040AD65       |movsx   ecx, byte ptr [edx+esi]
  0040AD69       |xor     edx, edx
  0040AD6B       |div     ebp
  0040AD6D       |movsx   eax, byte ptr [edx+45E510]    ; 依次取用户名的ASCII,若用户名不足8
                                                        ; 位,则循环获取
  0040AD74       |mov     edx, eax
  0040AD76       |shl     edx, 5                        ; 左移5位
  0040AD79       |add     edx, eax                      ; 加上用户名的ASCII
  0040AD7B       |lea     eax, [eax+edx*2]              ; eax=eax+edx*2
  0040AD7E       |add     ecx, eax                      ; ecx=注册码的第n位+30h
  0040AD80       |mov     eax, ebx                     \ ebx=注册码的第n位,共九位
  0040AD82       |imul    eax, ebx                     |
  0040AD85       |imul    eax, ebx                     |
  0040AD88       |imul    eax, ebp                     | ebp用户名位数
                                                       / eax=eax*eax*eax*ebp
  0040AD8B       |lea     edx, [eax+eax*4]             ; edx=eax+eax*4
  0040AD8E       |lea     eax, [eax+edx*2]             ; eax=eax+edx*2
  0040AD91       |add     ecx, eax                      ; eax=eax+ecx
  0040AD93       |xor     eax, eax
  0040AD95       |mov     edx, ecx
  0040AD97       |or      ecx, FFFFFFFF
  0040AD9A       |repne   scas byte ptr es:[edi]
  0040AD9C       |not     ecx
  0040AD9E       |mov     eax, edx
  0040ADA0       |dec     ecx
  0040ADA1       |xor     edx, edx
  0040ADA3       |div     ecx                           ; eax除以10,余数edx为注册码 
  0040ADA5       |lea     eax, [esp+18]
  0040ADA9       |add     edx, esi
  0040ADAB       |push    edx
  0040ADAC       |push    eax                         ; 这里用查表(表:0123456789)
  0040ADAD       |call    004198E0                     ; 得到注册码,其实根本不用
  0040ADB2       |add     esp, 0C                      ; 直接拿余数就可以了
  0040ADB5       |test    ebx, ebx
  0040ADB7       |je      short 0040ADF6
  0040ADB9       |mov     eax, ebx
  0040ADBB       |xor     edx, edx
  0040ADBD       |mov     ecx, 3
  0040ADC2       |div     ecx
  0040ADC4       |test    edx, edx
  0040ADC6       |jnz     short 0040ADF6
  0040ADC8       |mov     edi, 00458BEC                ;  -
  0040ADCD       |or      ecx, FFFFFFFF
  0040ADD0       |xor     eax, eax
  0040ADD2       |lea     edx, [esp+14]
  0040ADD6       |repne   scas byte ptr es:[edi]
  0040ADD8       |not     ecx
  0040ADDA       |sub     edi, ecx
  0040ADDC       |mov     esi, edi
  0040ADDE       |mov     edi, edx
  0040ADE0       |mov     edx, ecx
  0040ADE2       |or      ecx, FFFFFFFF
  0040ADE5       |repne   scas byte ptr es:[edi]
  0040ADE7       |mov     ecx, edx
  0040ADE9       |dec     edi
  0040ADEA       |shr     ecx, 2
  0040ADED       |rep     movs dword ptr es:[edi], dword >
  0040ADEF       |mov     ecx, edx
  0040ADF1       |and     ecx, 3
  0040ADF4       |rep     movs byte ptr es:[edi], byte pt>
  0040ADF6       |inc     ebx                          ; ebx=注册码的第n位,共九位
  0040ADF7       |cmp     ebx, 9                        ; 循环9次(注册码长度)
  0040ADFA       \jb      0040AD47
  0040AE00      lea     eax, [esp+14]
  ...
  
  现在简要写一下注册码的算法:
  
  1.取用户名ASCII -> eax,eax shl 5 -> ebx,ebx+eax -> ebx
   eax=用户名ASCII
   eax+ebx*2 -> eax,eax+ebp(注册码的第n位+30h) -> ecx
  
  2.ebx=注册码的第n位,共九位
    ebx -> eax,eax*eax*eax*ebp(用户名位数) -> eax
    eax+eax*4 -> edx
    eax+edx*2 -> eax
    eax+ecx ->eax  --> ecx的值看上面 1.
    eax除以10(0A)余数就是注册码
  
  注册码格式:
  8267-%4d-%3d-%2d      如:
  8267-3734-380-87
  
  注册码保存在:
  [HKEY_LOCAL_MACHINE\SOFTWARE\4Developers\RCrawler] - "4D"
  -----------------
  文章写于2007-08-11
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!