【文章标题】: 某幼儿学习软件的注册码分析
【文章作者】: pojiemyie
【软件名称】: 大家都知道的原因隐藏了
【下载地址】: 自己搜索下载
【使用工具】: PEID,OD
【操作平台】: WinXP
【软件介绍】: 幼儿学习数学的软件
【作者声明】: 给自己小孩用的,注册算法超级简单。为了邀请码,厚脸皮写这篇破文。
--------------------------------------------------------------------------------
【详细过程】
  首先Peid查壳,为Microsoft Visual C++ 6.0,无壳。OD载入,发现是MFC的程序,一大堆jmp <jmp.&MFC42.#641>之类的函数,头晕。想起教程里有导入函数一说,赶紧找MFC42.lib,然后调试→选择导入库,OD重新载入程序,jmp <jmp.&MFC42.#641>之类的函数已经能识别出名称了。
  F9运行,出现注册对话框,随便填入一些东西,点注册出现错误提示。关闭提示,OD中用中文搜索引擎搜索相关提示,找到错误提示处,
  00406359  |>  68 38304100   push 儿童快乐.00413038                       ;  注册号不正确,请重新输入!  ////搜索到的错误提示
  向上找跳转,发现注册关键代码如下,F8单步分析:
  004061B2  |.  8B86 DC070000 mov eax,dword ptr ds:[esi+7DC]
  004061B8  |.  8DAE DC070000 lea ebp,dword ptr ds:[esi+7DC]
  004061BE  |.  8B50 F8       mov edx,dword ptr ds:[eax-8]
  004061C1  |.  83FA 1D       cmp edx,1D                               ;  长度是否等于1D,即29位
  004061C4  |.  0F85 65010000 jnz 儿童快乐.0040632F
  004061CA  |.  8A48 05       mov cl,byte ptr ds:[eax+5]
  004061CD  |.  80F9 2D       cmp cl,2D
  004061D0  |.  0F85 59010000 jnz 儿童快乐.0040632F
  004061D6  |.  8078 0B 2D    cmp byte ptr ds:[eax+B],2D
  004061DA  |.  0F85 4F010000 jnz 儿童快乐.0040632F
  004061E0  |.  8078 11 2D    cmp byte ptr ds:[eax+11],2D
  004061E4  |.  0F85 45010000 jnz 儿童快乐.0040632F
  004061EA  |.  8078 17 2D    cmp byte ptr ds:[eax+17],2D
  004061EE  |.  0F85 3B010000 jnz 儿童快乐.0040632F                        ;  判断每隔5位(第6位)是否是字符-,得注册码形式XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
  004061F4  |.  55            push ebp
  004061F5  |.  8D4C24 2C     lea ecx,dword ptr ss:[esp+2C]
  004061F9  |.  E8 E4790000   call <jmp.&MFC42.#CString::CString_535>
  004061FE  |.  68 18394100   push 儿童快乐.00413918
  00406203  |.  8D4C24 14     lea ecx,dword ptr ss:[esp+14]
  00406207  |.  897C24 20     mov dword ptr ss:[esp+20],edi
  0040620B  |.  E8 CC790000   call <jmp.&MFC42.#CString::CString_537>
  00406210  |.  6A 07         push 7
  00406212  |.  6A 16         push 16
  00406214  |.  8D4C24 30     lea ecx,dword ptr ss:[esp+30]
  00406218  |.  C64424 24 01  mov byte ptr ss:[esp+24],1
  0040621D  |.  E8 B4790000   call <jmp.&MFC42.#CString::Delete_6648>  ;  删除从第16位(即22位)后的7个字符(最后7位)
  00406222  |.  BF 04000000   mov edi,4
  00406227  |>  6A 02         /push 2
  00406229  |.  57            |push edi
  0040622A  |.  8D4C24 30     |lea ecx,dword ptr ss:[esp+30]
  0040622E  |.  E8 A3790000   |call <jmp.&MFC42.#CString::Delete_6648> ;  从第4位开始,每隔4位删除2个字符,即将-和前面一个字符删除
  00406233  |.  83C7 04       |add edi,4
  00406236  |.  83FF 10       |cmp edi,10
  00406239  |.^ 7C EC         \jl short 儿童快乐.00406227
  0040623B  |.  68 18394100   push 儿童快乐.00413918
  00406240  |.  8D4C24 28     lea ecx,dword ptr ss:[esp+28]
  00406244  |.  E8 93790000   call <jmp.&MFC42.#CString::CString_537>
  00406249  |.  8D4C24 24     lea ecx,dword ptr ss:[esp+24]
  0040624D  |.  C64424 1C 02  mov byte ptr ss:[esp+1C],2
  00406252  |.  51            push ecx
  00406253  |.  8BCE          mov ecx,esi
  00406255  |.  E8 B6720000   call 儿童快乐.0040D510                       ;  获取C盘信息以便计算注册码
  0040625A  |.  8D5424 24     lea edx,dword ptr ss:[esp+24]
  0040625E  |.  8BCE          mov ecx,esi
  00406260  |.  52            push edx
  00406261  |.  E8 2A650000   call 儿童快乐.0040C790                       ;  第一次计算注册码
  00406266  |.  8D4424 24     lea eax,dword ptr ss:[esp+24]
  0040626A  |.  8BCE          mov ecx,esi
  0040626C  |.  50            push eax
  0040626D  |.  E8 1E650000   call 儿童快乐.0040C790                       ;  第二次计算注册码
  00406272  |.  8B4C24 24     mov ecx,dword ptr ss:[esp+24]
  00406276  |.  8B5424 28     mov edx,dword ptr ss:[esp+28]
  0040627A  |.  51            push ecx                                 ; /s2
  0040627B  |.  52            push edx                                 ; |s1
  0040627C  |.  FF15 F4024100 call dword ptr ds:[<&MSVCRT._mbscmp>]    ; \_mbscmp    关键比较
  00406282  |.  83C4 08       add esp,8
  00406285  |.  85C0          test eax,eax
  00406287  |.  6A 00         push 0
  00406289  |.  68 74304100   push 儿童快乐.00413074                       ;  提示
  0040628E  |.  75 5F         jnz short 儿童快乐.004062EF
  00406290  |.  68 18324100   push 儿童快乐.00413218                       ;  注册成功, 谢谢使用!
  00406295  |.  8BCE          mov ecx,esi
  00406297  |.  E8 34790000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
  0040629C  |.  B8 01000000   mov eax,1
  004062A1  |.  55            push ebp
  004062A2  |.  8986 C8070000 mov dword ptr ds:[esi+7C8],eax
  004062A8  |.  8986 CC070000 mov dword ptr ds:[esi+7CC],eax
  004062AE  |.  8D4424 10     lea eax,dword ptr ss:[esp+10]
  004062B2  |.  68 54304100   push 儿童快乐.00413054                       ;  SERIAL=
  004062B7  |.  50            push eax
  004062B8  |.  C786 98030000>mov dword ptr ds:[esi+398],0
  004062C2  |.  E8 03790000   call <jmp.&MFC42.#operator+_926>
  004062C7  |.  50            push eax
  004062C8  |.  8D8E C4070000 lea ecx,dword ptr ds:[esi+7C4]
  004062CE  |.  C64424 20 03  mov byte ptr ss:[esp+20],3
  004062D3  |.  E8 EC780000   call <jmp.&MFC42.#CString::operator=_858>
  004062D8  |.  8D4C24 0C     lea ecx,dword ptr ss:[esp+C]
  004062DC  |.  C64424 1C 02  mov byte ptr ss:[esp+1C],2
  004062E1  |.  E8 96780000   call <jmp.&MFC42.#CString::~CString_800>
  004062E6  |.  8BCE          mov ecx,esi
  004062E8  |.  E8 E3C4FFFF   call 儿童快乐.004027D0                       ;  跟进发现保存注册码保存在 DAT\diary.dat,格式SERIAL=注册码
  004062ED  |.  EB 0C         jmp short 儿童快乐.004062FB
  004062EF  |>  68 38304100   push 儿童快乐.00413038                       ;  注册号不正确,请重新输入!
  004062F4  |.  8BCE          mov ecx,esi
  004062F6  |.  E8 D5780000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
  004062FB  |>  8D4C24 24     lea ecx,dword ptr ss:[esp+24]
  004062FF  |.  C64424 1C 01  mov byte ptr ss:[esp+1C],1
  00406304  |.  E8 73780000   call <jmp.&MFC42.#CString::~CString_800>
  00406309  |.  8D4C24 10     lea ecx,dword ptr ss:[esp+10]
  0040630D  |.  C64424 1C 00  mov byte ptr ss:[esp+1C],0
  00406312  |.  E8 65780000   call <jmp.&MFC42.#CString::~CString_800>
  00406317  |.  8D4C24 28     lea ecx,dword ptr ss:[esp+28]
  0040631B  |.  C74424 1C FFF>mov dword ptr ss:[esp+1C],-1
  00406323  |.  E8 54780000   call <jmp.&MFC42.#CString::~CString_800>
  00406328  |.  33FF          xor edi,edi
  0040632A  |.  E9 9D000000   jmp 儿童快乐.004063CC
  0040632F  |>  3BD7          cmp edx,edi
  00406331  |.  57            push edi
  00406332  |.  68 74304100   push 儿童快乐.00413074                       ;  提示
  00406337  |.  75 20         jnz short 儿童快乐.00406359
  00406339  |.  68 28304100   push 儿童快乐.00413028                       ;  请输入注册号!
  0040633E  |.  8BCE          mov ecx,esi
  00406340  |.  E8 8B780000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
  00406345  |.  5F            pop edi
  00406346  |.  5E            pop esi
  00406347  |.  5D            pop ebp
  00406348  |.  8B4C24 08     mov ecx,dword ptr ss:[esp+8]
  0040634C  |.  64:890D 00000>mov dword ptr fs:[0],ecx
  00406353  |.  83C4 14       add esp,14
  00406356  |.  C2 0800       retn 8
  00406359  |>  68 38304100   push 儿童快乐.00413038                       ;  注册号不正确,请重新输入!  ////搜索到的错误提示
  0040635E  |.  8BCE          mov ecx,esi
  00406360  |.  E8 6B780000   call <jmp.&MFC42.#CWnd::MessageBoxA_4224>
  00406365  |.  5F            pop edi
  00406366  |.  5E            pop esi
  00406367  |.  5D            pop ebp
  00406368  |.  8B4C24 08     mov ecx,dword ptr ss:[esp+8]
  0040636C  |.  64:890D 00000>mov dword ptr fs:[0],ecx
  00406373  |.  83C4 14       add esp,14
  00406376  |.  C2 0800       retn 8
  
  注册码的算出没有仔细跟,粗略看了一下,在以下三处(省略部分代码):
  第一处:
  00406255  |.  E8 B6720000   call 儿童快乐.0040D510                       ;  获取C盘信息以便计算注册码
  F7跟进:
  0040D52F  |.  6A 0A              push 0A                                  ; /pFileSystemNameSize = 0000000A
  0040D531  |.  50                 push eax                                 ; |pFileSystemNameBuffer
  0040D532  |.  8D4424 10          lea eax,dword ptr ss:[esp+10]            ; |
  0040D536  |.  50                 push eax                                 ; |pFileSystemFlags
  0040D537  |.  51                 push ecx                                 ; |pMaxFilenameLength
  0040D538  |.  52                 push edx                                 ; |pVolumeSerialNumber
  0040D539  |.  6A 0C              push 0C                                  ; |MaxVolumeNameSize = C (12.)
  0040D53B  |.  56                 push esi                                 ; |VolumeNameBuffer
  0040D53C  |.  68 F4384100        push 儿童快乐.004138F4                       ; |c://
  0040D541  |.  FF15 60004100      call dword ptr ds:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA  获取C盘信息以便计算注册码
  
  第二处:
  00406261  |.  E8 2A650000   call 儿童快乐.0040C790                       ;  第一次计算注册码
  F7跟进:
  0040C7E3  |> /8D3C00          /lea edi,dword ptr ds:[eax+eax]
  0040C7E6  |. |83FF 18         |cmp edi,18
  0040C7E9  |. |7E 05           |jle short 儿童快乐.0040C7F0
  0040C7EB  |. |BF 18000000     |mov edi,18
  0040C7F0  |> |B3 31           |mov bl,31                                        ;  数字1
  0040C7F2  |. |BE 01000000     |mov esi,1
  0040C7F7  |. |885C24 1C       |mov byte ptr ss:[esp+1C],bl
  0040C7FB  |> |8B5424 1C       |/mov edx,dword ptr ss:[esp+1C]
  0040C7FF  |. |8D4C24 14       ||lea ecx,dword ptr ss:[esp+14]
  0040C803  |. |52              ||push edx
  0040C804  |. |56              ||push esi
  0040C805  |. |E8 2C140000     ||call <jmp.&MFC42.#CString::Insert_6778>          ;  每隔两位插入递加数字1、2、3、4、5……
  0040C80A  |. |FEC3            ||inc bl                                           ;  递加
  0040C80C  |. |80FB 3A         ||cmp bl,3A
  0040C80F  |. |885C24 1C       ||mov byte ptr ss:[esp+1C],bl
  0040C813  |. |75 06           ||jnz short 儿童快乐.0040C81B
  0040C815  |. |B3 41           ||mov bl,41
  0040C817  |. |885C24 1C       ||mov byte ptr ss:[esp+1C],bl
  0040C81B  |> |8B4424 14       ||mov eax,dword ptr ss:[esp+14]
  0040C81F  |. |83C6 02         ||add esi,2
  0040C822  |. |8B48 F8         ||mov ecx,dword ptr ds:[eax-8]
  0040C825  |. |3BCF            ||cmp ecx,edi
  0040C827  |.^|7C D2           |\jl short 儿童快乐.0040C7FB
  0040C829  |. |8BC1            |mov eax,ecx
  0040C82B  |. |83F8 18         |cmp eax,18
  0040C82E  |.^\7C B3           \jl short 儿童快乐.0040C7E3
  0040C830  |.  5F              pop edi                                      ;  经过以上计算,补足18位(即24位)字符
  0040C831  |>  68 18394100     push 儿童快乐.00413918
  0040C836  |.  8D4C24 10       lea ecx,dword ptr ss:[esp+10]
  0040C83A  |.  E8 9D130000     call <jmp.&MFC42.#CString::CString_537>
  0040C83F  |.  C64424 28 02    mov byte ptr ss:[esp+28],2
  0040C844  |.  33F6            xor esi,esi
  0040C846  |.  BB 04000000     mov ebx,4
  0040C84B  |>  6A 06           push 6
  0040C84D  |.  8D4424 1C       lea eax,dword ptr ss:[esp+1C]
  0040C851  |.  56              push esi
  0040C852  |.  50              push eax
  0040C853  |.  8D4C24 1C       lea ecx,dword ptr ss:[esp+1C]
  0040C857  |.  E8 D4130000     call <jmp.&MFC42.#CString::Mid_4278>         ;  每6个一组取出计算注册码
  0040C85C  |.  50              push eax
  0040C85D  |.  8D4C24 10       lea ecx,dword ptr ss:[esp+10]
  0040C861  |.  C64424 2C 03    mov byte ptr ss:[esp+2C],3
  0040C866  |.  E8 59130000     call <jmp.&MFC42.#CString::operator=_858>
  0040C86B  |.  8D4C24 18       lea ecx,dword ptr ss:[esp+18]
  0040C86F  |.  C64424 28 02    mov byte ptr ss:[esp+28],2
  0040C874  |.  E8 03130000     call <jmp.&MFC42.#CString::~CString_800>
  0040C879  |.  6A 06           push 6
  0040C87B  |.  6A 06           push 6
  0040C87D  |.  8D4C24 14       lea ecx,dword ptr ss:[esp+14]
  0040C881  |.  E8 A4130000     call <jmp.&MFC42.#CString::GetBuffer_2915>
  0040C886  |.  50              push eax
  0040C887  |.  8BCD            mov ecx,ebp
  0040C889  |.  E8 52FEFFFF     call 儿童快乐.0040C6E0                           ;  计算注册码,转化为字母。跟进,见下
  0040C88E  |.  6A FF           push -1
  0040C890  |.  8D4C24 10       lea ecx,dword ptr ss:[esp+10]
  0040C894  |.  E8 8B130000     call <jmp.&MFC42.#CString::ReleaseBuffer_557>
  0040C899  |.  6A 01           push 1
  0040C89B  |.  53              push ebx
  0040C89C  |.  8D4C24 14       lea ecx,dword ptr ss:[esp+14]
  0040C8A0  |.  E8 31130000     call <jmp.&MFC42.#CString::Delete_6648>
  0040C8A5  |.  8D4C24 0C       lea ecx,dword ptr ss:[esp+C]
  0040C8A9  |.  8D5424 14       lea edx,dword ptr ss:[esp+14]
  0040C8AD  |.  51              push ecx
  0040C8AE  |.  8D4424 20       lea eax,dword ptr ss:[esp+20]
  0040C8B2  |.  52              push edx
  0040C8B3  |.  50              push eax
  0040C8B4  |.  E8 65130000     call <jmp.&MFC42.#operator+_922>
  0040C8B9  |.  50              push eax
  0040C8BA  |.  8D4C24 18       lea ecx,dword ptr ss:[esp+18]
  0040C8BE  |.  885C24 2C       mov byte ptr ss:[esp+2C],bl
  0040C8C2  |.  E8 FD120000     call <jmp.&MFC42.#CString::operator=_858>
  0040C8C7  |.  8D4C24 1C       lea ecx,dword ptr ss:[esp+1C]
  0040C8CB  |.  C64424 28 02    mov byte ptr ss:[esp+28],2
  0040C8D0  |.  E8 A7120000     call <jmp.&MFC42.#CString::~CString_800>
  0040C8D5  |.  83C6 06         add esi,6
  0040C8D8  |.  83FE 18         cmp esi,18
  0040C8DB  |.^ 0F8C 6AFFFFFF   jl 儿童快乐.0040C84B                             ;  循环计算5次,得到5组字母,再经第二次计算即得注册码
  
  0040C889  |.  E8 52FEFFFF     call 儿童快乐.0040C6E0  处跟进如下:
  0040C6F9  |> /83F8 07          /cmp eax,7
  0040C6FC  |. |7E 02            |jle short 儿童快乐.0040C700
  0040C6FE  |. |33C0             |xor eax,eax
  0040C700  |> |33D2             |xor edx,edx
  0040C702  |. |33DB             |xor ebx,ebx
  0040C704  |. |8A1431           |mov dl,byte ptr ds:[ecx+esi]
  0040C707  |. |8A98 A4304100    |mov bl,byte ptr ds:[eax+4130A4]
  0040C70D  |. |0FAFD3           |imul edx,ebx
  0040C710  |. |03FA             |add edi,edx
  0040C712  |. |41               |inc ecx
  0040C713  |. |40               |inc eax
  0040C714  |. |3BCD             |cmp ecx,ebp
  0040C716  |.^\7C E1            \jl short 儿童快乐.0040C6F9
  0040C718  |>  57               push edi                                     ; /<%ld>
  0040C719  |.  68 7C304100      push 儿童快乐.0041307C                           ; |%ld
  0040C71E  |.  56               push esi                                     ; |s
  0040C71F  |.  FF15 6C034100    call dword ptr ds:[<&USER32.wsprintfA>]      ; \wsprintfA
  0040C725  |.  8A4E 02          mov cl,byte ptr ds:[esi+2]                   ;  
  ////经过以上计算转化为四位数字
  0040C728  |.  8A46 03          mov al,byte ptr ds:[esi+3]
  0040C72B  |.  83C4 0C          add esp,0C
  0040C72E  |.  3AC8             cmp cl,al
  0040C730  |.  7D 06            jge short 儿童快乐.0040C738
  0040C732  |.  8AD0             mov dl,al
  0040C734  |.  2AD1             sub dl,cl
  0040C736  |.  EB 04            jmp short 儿童快乐.0040C73C
  0040C738  |>  8AD1             mov dl,cl
  0040C73A  |.  2AD0             sub dl,al
  0040C73C  |>  8A1E             mov bl,byte ptr ds:[esi]
  0040C73E  |.  80C1 11          add cl,11                                    ;  数字加11转化为字母,以下同
  0040C741  |.  04 11            add al,11
  0040C743  |.  02DA             add bl,dl                                    ;  加第四位与第二位差
  0040C745  |.  884E 02          mov byte ptr ds:[esi+2],cl                   ;  所得字母填充入第三位
  0040C748  |.  8846 03          mov byte ptr ds:[esi+3],al                   ;  所得字母填充入第四位
  0040C74B  |.  881E             mov byte ptr ds:[esi],bl                     ;  填充入第一位,继续计算
  0040C74D  |.  8AD3             mov dl,bl
  0040C74F  |.  8A5E 01          mov bl,byte ptr ds:[esi+1]
  0040C752  |.  80C2 11          add dl,11
  0040C755  |.  0FBEC0           movsx eax,al
  0040C758  |.  0FBEC9           movsx ecx,cl
  0040C75B  |.  80C3 11          add bl,11
  0040C75E  |.  03C1             add eax,ecx
  0040C760  |.  0FBECB           movsx ecx,bl
  0040C763  |.  8816             mov byte ptr ds:[esi],dl                     ;  填充入第一位
  0040C765  |.  03C1             add eax,ecx
  0040C767  |.  0FBED2           movsx edx,dl
  0040C76A  |.  03C2             add eax,edx
  0040C76C  |.  885E 01          mov byte ptr ds:[esi+1],bl                   ;  填充入第二位
  0040C76F  |.  99               cdq
  0040C770  |.  83E2 03          and edx,3
  0040C773  |.  C646 05 00       mov byte ptr ds:[esi+5],0
  0040C777  |.  03C2             add eax,edx
  0040C779  |.  5F               pop edi
  0040C77A  |.  C1F8 02          sar eax,2                                    ;  除以4,基本是前四位平均
  0040C77D  |.  8846 04          mov byte ptr ds:[esi+4],al                   ;  填充入第五位
  0040C780  |.  5E               pop esi
  0040C781  |.  5D               pop ebp
  0040C782  |.  5B               pop ebx
  0040C783  \.  C2 0800          retn 8
  
  第三处:
  0040626D  |.  E8 1E650000   call 儿童快乐.0040C790                       ;  第二次计算注册码
  对第一计算结果再次计算,算法完全一样,得到最终注册码。
  
  总结:
  算法非常简单,上面有分析。注册码形式为XXXXX-XXXXX-XXXXX-XXXXX-XXXXX,X全为大写字母。基本是明码比较,对输入码做了简单处理,为了方便找规律,输入ABCDE-FGHIJ-KLMNO-PQRST-UVWXY,输入码转化的规律为:
  将后7位删除,每个-及前面一个字母删除,重新连接得到字符串,即得ABCDFGHIKLMNPQRS,再与真码比较。将真码每四个一组,插入一个字母和-,最后在补足7个字符即可。
  从C盘获得信息得到一串字符,填充变为24位,循环取出6位,转化为四位数字,然后加11变为字母,第五位基本是前四位平均,将几组字母连接成16位字母,再算一次变成注册码。只大概看了一下,可能分析有些不准,谅解。
  
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2011年05月02日 上午 10:11:48