【软件名称】ScreenHunter 4.2 Pro
【破文作者】forever[RCT]
【编程语言】VC
【保护方式】简单运算
【使用工具】peid0.93,exescope6.5,ida4.6,ollydbg1.1
【软件简介】ScreenHunter 是一个非常好的屏幕抓取工具,除了基本常见的功能外,他还可以抓取椭圆的选取区,抓取Word文件,还可以自动产生文件名称,定时抓取屏幕,抓取DirectX游戏及屏幕保护程序的屏幕,转存JPEG、GIF、PNG、BMP文件。
【下载地址】http://www4.skycn.com/soft/5021.html
【破文正文】
    首先声明一下,这篇帖子是写给新手的。:) 
    突然发现,写破文其实是一件很辛苦的事,尤其是想把整个过程写清楚的时候。向那些写了大量破文的前辈们道声辛苦吧。;)
    我尽量把过程写的易懂些,不过我还是假定你会使用基本的工具,懂得编程的基本知识。关于MFC的消息处理函数的查找过程
我前面有过一篇帖子<从对话框的构造函数找到消息处理过程>,如果你不太清楚下面的过程可以参考一下前面的帖子。下面我只写
下整个过程。我不在这里对代码做逆向分析了,我只是在注释里尽量写的清楚些。这样可以省掉很多时间:)
    
    首先检查软件的编程语言,peid侦测出是VC,大多数情况下这是可信的。用od和ida载入也证实确实是VC的。
    软件启动时有个NAP窗口提示输入注册码,我用exescope找到这个窗口的资源id是1797h,ok按钮的id是1d4h。了解这些信息是有用的。
    现在用ida载入软件分析。我以前做过一个mfc4.2的sig,如果你使用这个sig,会检测出更多的函数名。
    在Name窗口里查找"CDialog::CDialog(unsigned int,class CWnd *)",来到下面,
    
.text:0054A50F public: __thiscall CDialog::CDialog(unsigned int,class CWnd *) proc near
.text:0054A50F
.text:0054A50F arg_0           = dword ptr  0Ch
.text:0054A50F arg_4           = dword ptr  10h
.text:0054A50F
.text:0054A50F                 push    esi
.text:0054A510                 push    edi
.text:0054A511                 mov     esi, ecx
.text:0054A513                 call    CWnd::CWnd(void)
.text:0054A518                 lea     edi, [esi+3Ch]
.text:0054A51B                 push    20h             ; size_t
.text:0054A51D                 push    0               ; int
.text:0054A51F                 push    edi             ; void *
.text:0054A520                 mov     dword ptr [esi], offset off_5838D4
.text:0054A526                 call    _memset
.text:0054A52B                 mov     eax, [esp+0Ch+arg_4]
.text:0054A52F                 add     esp, 0Ch
.text:0054A532                 mov     [esi+50h], eax
.text:0054A535                 mov     eax, [esp+arg_0]
.text:0054A539                 movzx   ecx, ax
.text:0054A53C                 mov     [edi], eax
.text:0054A53E                 mov     [esi+40h], ecx
.text:0054A541                 mov     eax, esi
.text:0054A543                 pop     edi
.text:0054A544                 pop     esi
.text:0054A545                 retn    8
.text:0054A545 public: __thiscall CDialog::CDialog(unsigned int,class CWnd *) endp
;=================================================================================
    为什么要找这个函数呢?因为这个函数是对话框类的构造函数,自定义对话框在初始化时肯定要调用这个函数。
    
    在名字CDialog::CDialog上右击,选择菜单Jump to xref to operand,来到下面,
Up   p sub_40E7A7+C                                                         call    CDialog::CDialog(uint,CWnd *)
Up   p sub_411987+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_414C64+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_437218+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_43F20C+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4460F4+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_44D3FD+1A                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_46F72B+C                                                         call    CDialog::CDialog(uint,CWnd *)
Up   p sub_486E87+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4A89B6+1D                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4AF524+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4BC73F+1B                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4C0301+1A                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4C2F1A+1A                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4C5B16+1A                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p sub_4C8639+1A                                                        call    CDialog::CDialog(uint,CWnd *)
Up   p CFileDialog::CFileDialog(int,char const *,char const *,ulong,char const *,CWnd *)+19 call    CDialog::CDia
Up   p CFontDialog::CFontDialog(tagLOGFONTA *,ulong,CDC *,CWnd *)+19        call    CDialog::CDialog(uint,CWnd *)
Up   p CFontDialog::CFontDialog(_charformat const &,ulong,CDC *,CWnd *)+19  call    CDialog::CDialog(uint,CWnd *)
Up   p CColorDialog::CColorDialog(ulong,ulong,CWnd *)+17                    call    CDialog::CDialog(uint,CWnd *)
Up   p CPageSetupDialog::CPageSetupDialog(ulong,CWnd *)+17                  call    CDialog::CDialog(uint,CWnd *)
Up   p CPrintDialog::CPrintDialog(int,ulong,CWnd *)+18                      call    CDialog::CDialog(uint,CWnd *)
Up   p CPrintDialog::CPrintDialog(tagPDA &)+7                               call    CDialog::CDialog(uint,CWnd *)
Up   p CFindReplaceDialog::CFindReplaceDialog(void)+17                      call    CDialog::CDialog(uint,CWnd *)
Down p CDocManager::OnFileNew(void)+3D                                      call    CDialog::CDialog(uint,CWnd *)

;=================================================================================
    
    这里就是对CDialog::CDialog引用的地方了。注意找对话框资源号为1797h的函数。(使用exescope查看注册对话框资源)
    来到下面:
.text:0043F20C sub_43F20C      proc near               ; CODE XREF: sub_46973F+31p
.text:0043F20C                 mov     eax, offset unknown_libname_1324
.text:0043F211                 call    __EH_prolog
.text:0043F216                 push    ecx
.text:0043F217                 push    ebx
.text:0043F218                 push    esi
.text:0043F219                 push    edi
.text:0043F21A                 mov     esi, ecx
.text:0043F21C                 push    dword ptr [ebp+8]
.text:0043F21F                 mov     [ebp-10h], esi
.text:0043F222                 push    1797h           ; 注册对话框
.text:0043F227                 call    CDialog::CDialog(uint,CWnd *) //构造注册对话框的地方,这就是
.text:0043F22C                 and     dword ptr [ebp-4], 0          //从CDialog::CDialog下手的原因
.text:0043F230                 lea     ebx, [esi+5Ch]
.text:0043F233                 mov     ecx, ebx
.text:0043F235                 call    CWnd::CWnd(void)
.text:0043F23A                 mov     edi, offset off_584E04
.text:0043F23F                 mov     [ebx], edi
.text:0043F241                 lea     ebx, [esi+98h]
.text:0043F247                 mov     byte ptr [ebp-4], 1
.text:0043F24B                 mov     ecx, ebx
.text:0043F24D                 call    CWnd::CWnd(void)
.text:0043F252                 mov     [ebx], edi
.text:0043F254                 lea     ebx, [esi+0D4h]
.text:0043F25A                 mov     byte ptr [ebp-4], 2
.text:0043F25E                 mov     ecx, ebx
.text:0043F260                 call    CWnd::CWnd(void)
.text:0043F265                 mov     [ebx], edi
.text:0043F267                 lea     ebx, [esi+110h]
.text:0043F26D                 mov     byte ptr [ebp-4], 3
.text:0043F271                 mov     ecx, ebx
.text:0043F273                 call    CWnd::CWnd(void)
.text:0043F278                 mov     [ebx], edi
.text:0043F27A                 lea     ebx, [esi+14Ch]
.text:0043F280                 mov     byte ptr [ebp-4], 4
.text:0043F284                 mov     ecx, ebx
.text:0043F286                 call    CWnd::CWnd(void)
.text:0043F28B                 mov     [ebx], edi
.text:0043F28D                 mov     eax, dword_5D537C
.text:0043F292                 lea     ebx, [esi+188h]
.text:0043F298                 mov     [ebx], eax
.text:0043F29A                 mov     eax, dword_5D537C
.text:0043F29F                 mov     [esi+18Ch], eax
.text:0043F2A5                 mov     eax, dword_5D537C
.text:0043F2AA                 mov     [esi+190h], eax
.text:0043F2B0                 mov     eax, dword_5D537C
.text:0043F2B5                 mov     [esi+194h], eax
.text:0043F2BB                 mov     eax, dword_5D537C
.text:0043F2C0                 mov     [esi+198h], eax
.text:0043F2C6                 lea     ecx, [esi+19Ch]
.text:0043F2CC                 mov     byte ptr [ebp-4], 0Ah
.text:0043F2D0                 call    sub_5430CA
.text:0043F2D5                 mov     edi, offset WindowName
.text:0043F2DA                 mov     ecx, ebx
.text:0043F2DC                 push    edi
.text:0043F2DD                 mov     byte ptr [ebp-4], 0Bh
.text:0043F2E1                 mov     dword ptr [esi], offset off_57AEE0  //这个地址里对话框的虚函数表
.text:0043F2E7                 call    CString::operator=(char const *)    //一般都是在ESI或者EDI里
.text:0043F2EC                 push    edi
.text:0043F2ED                 lea     ecx, [esi+18Ch]
.text:0043F2F3                 call    CString::operator=(char const *)
.text:0043F2F8                 push    edi
.text:0043F2F9                 lea     ecx, [esi+190h]
.text:0043F2FF                 call    CString::operator=(char const *)
.text:0043F304                 push    edi
.text:0043F305                 lea     ecx, [esi+194h]
.text:0043F30B                 call    CString::operator=(char const *)
.text:0043F310                 push    edi
.text:0043F311                 lea     ecx, [esi+198h]
.text:0043F317                 call    CString::operator=(char const *)    //上面连续5个字符串应该是保存
.text:0043F31C                 push    0FFFFFFFFh                          //注册码用的
.text:0043F31E                 push    5
.text:0043F320                 lea     ecx, [esi+19Ch]
.text:0043F326                 call    CStringArray::SetSize(int,int)
.text:0043F32B                 mov     ecx, [ebp-0Ch]
.text:0043F32E                 mov     eax, esi
.text:0043F330                 pop     edi
.text:0043F331                 pop     esi
.text:0043F332                 pop     ebx
.text:0043F333                 mov     large fs:0, ecx
.text:0043F33A                 leave
.text:0043F33B                 retn    4
.text:0043F33B sub_43F20C      endp ; sp =  4
;=================================================================================
    跟踪对话框的虚函数表地址57AEE0,来到下面:

.rdata:0057AEE0 off_57AEE0      dd offset sub_563B94    ; DATA XREF: sub_43F20C+D5o
.rdata:0057AEE4                 dd offset sub_43F33E
.rdata:0057AEE8                 dd offset nullsub_50
.rdata:0057AEEC                 dd offset unknown_libname_12862 ; ?OnCmdMsg@CPropertySheet@@UAEHIHPAXPAUAFX_CMDHANDLERINFO@@@Z
.rdata:0057AEEC                                         ; doubtful name
.rdata:0057AEF0                 dd offset CWnd::OnFinalRelease(void)
.rdata:0057AEF4                 dd offset unknown_libname_884
.rdata:0057AEF8                 dd offset unknown_libname_885
.rdata:0057AEFC                 dd offset sub_54B286
.rdata:0057AF00                 dd offset sub_54B289
.rdata:0057AF04                 dd offset CCmdTarget::GetTypeLib(ulong,ITypeLib * *)
.rdata:0057AF08                 dd offset sub_43F4E4      //消息映射函数,继续跟踪这里
.rdata:0057AF0C                 dd offset sub_54B336
.rdata:0057AF10                 dd offset sub_54B2D9
.rdata:0057AF14                 dd offset sub_54B326
.rdata:0057AF18                 dd offset sub_54B2E5
.rdata:0057AF1C                 dd offset sub_54B2DF
.rdata:0057AF20                 dd offset sub_54B31D
.rdata:0057AF24                 dd offset unknown_libname_886
.rdata:0057AF28                 dd offset unknown_libname_888
.rdata:0057AF2C                 dd offset unknown_libname_887
.rdata:0057AF30                 dd offset nullsub_24
.rdata:0057AF34                 dd offset CWnd::Create(char const *,char const *,ulong,tagRECT const &,CWnd *,uint,CCreateContext *)
.rdata:0057AF38                 dd offset CWnd::DestroyWindow(void)
.rdata:0057AF3C                 dd offset CWnd::PreCreateWindow(tagCREATESTRUCTA &)
.rdata:0057AF40                 dd offset CWnd::CalcWindowRect(tagRECT *,uint)
.rdata:0057AF44                 dd offset CWnd::OnToolHitTest(CPoint,tagTOOLINFOA *)
.rdata:0057AF48                 dd offset unknown_libname_880
.rdata:0057AF4C                 dd offset CWnd::WinHelpA(ulong,uint)
.rdata:0057AF50                 dd offset CWnd::ContinueModal(void)
.rdata:0057AF54                 dd offset CWnd::EndModalLoop(int)
.rdata:0057AF58                 dd offset CWnd::OnCommand(uint,long)
.rdata:0057AF5C                 dd offset CWnd::OnNotify(uint,long,long *)
.rdata:0057AF60                 dd offset sub_546855
.rdata:0057AF64                 dd offset sub_43F428
.rdata:0057AF68                 dd offset CWnd::BeginModalState(void)
.rdata:0057AF6C                 dd offset CWnd::EndModalState(void)
.rdata:0057AF70                 dd offset CDialog::PreTranslateMessage(tagMSG *)
.rdata:0057AF74                 dd offset CWnd::OnAmbientProperty(COleControlSite *,long,tagVARIANT *)
.rdata:0057AF78                 dd offset CWnd::WindowProc(uint,uint,long)
.rdata:0057AF7C                 dd offset CWnd::OnWndMsg(uint,uint,long,long *)
.rdata:0057AF80                 dd offset CWnd::DefWindowProcA(uint,uint,long)
.rdata:0057AF84                 dd offset nullsub_25
.rdata:0057AF88                 dd offset CWnd::OnChildNotify(uint,uint,long,long *)
.rdata:0057AF8C                 dd offset CDialog::CheckAutoCenter(void)
.rdata:0057AF90                 dd offset sub_548E97
.rdata:0057AF94                 dd offset CDialog::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO *)
.rdata:0057AF98                 dd offset CDialog::DoModal(void)
.rdata:0057AF9C                 dd offset sub_43F4EA
.rdata:0057AFA0                 dd offset nullsub_52
.rdata:0057AFA4                 dd offset CDialog::OnOK(void)
.rdata:0057AFA8                 dd offset CDialog::OnCancel(void)
.rdata:0057AFAC                 dd offset nullsub_53
;=================================================================================

    注意CCmdTarget::GetTypeLib,跟踪这个函数下面的那个函数的地址43F4E4,可以找到处理这个对话框消息的函数。

.text:0043F4E4 sub_43F4E4      proc near               ; DATA XREF: .rdata:0057AF08o
.text:0043F4E4                 mov     eax, offset off_57AE30
.text:0043F4E9                 retn
.text:0043F4E9 sub_43F4E4      endp
;=================================================================================
    继续跟踪地址57AE30,来到下面:
.rdata:0057AE30 off_57AE30      dd offset off_5837E8    //指向父类的消息处理函数
.rdata:0057AE34                 dd offset dword_57AE38  //本对话框的消息处理函数
.rdata:0057AE38 dword_57AE38    dd 111h                 
.rdata:0057AE3C                 dd 0
.rdata:0057AE40                 dd 627h
.rdata:0057AE44                 dd 627h
.rdata:0057AE48                 dd 0Ch
.rdata:0057AE4C                 dd 43F682h
.rdata:0057AE50                 dd 111h
.rdata:0057AE54                 dd 0
.rdata:0057AE58                 dd 1D3h
.rdata:0057AE5C                 dd 1D3h
.rdata:0057AE60                 dd 0Ch
.rdata:0057AE64                 dd 43F6A0h
.rdata:0057AE68                 dd 111h                 //WM_COMMAND消息
.rdata:0057AE6C                 dd 0
.rdata:0057AE70                 dd 1D4h
.rdata:0057AE74                 dd 1D4h                 //ok按钮id
.rdata:0057AE78                 dd 0Ch
.rdata:0057AE7C                 dd 43F6B7h              //ok按钮的处理函数
.rdata:0057AE80                 dd 111h
.rdata:0057AE84                 dd 0
.rdata:0057AE88                 dd 7D6h
.rdata:0057AE8C                 dd 7D6h
.rdata:0057AE90                 dd 0Ch
.rdata:0057AE94                 dd 43F7A4h
.rdata:0057AE98                 dd 19h
.rdata:0057AE9C                 dd 0
.rdata:0057AEA0                 dd 0
.rdata:0057AEA4                 dd 0
.rdata:0057AEA8                 dd 4
.rdata:0057AEAC                 dd 43F7ADh
.rdata:0057AEB0                 dd 111h
.rdata:0057AEB4                 dd 0
.rdata:0057AEB8                 dd 623h
.rdata:0057AEBC                 dd 623h
.rdata:0057AEC0                 dd 0Ch
.rdata:0057AEC4                 dd 43F867h
.rdata:0057AEC8                 dd 0
.rdata:0057AECC                 dd 0
.rdata:0057AED0                 dd 0
.rdata:0057AED4                 dd 0
.rdata:0057AED8                 dd 0
.rdata:0057AEDC                 dd 0
;=================================================================================

    好了,现在找到了注册对话框中的ok按钮的处理函数,看一下这个函数:
.text:0043F6B7 sub_43F6B7      proc near
.text:0043F6B7                 mov     eax, offset unknown_libname_1327
.text:0043F6BC                 call    __EH_prolog
.text:0043F6C1                 push    ecx
.text:0043F6C2                 push    esi
.text:0043F6C3                 mov     esi, ecx
.text:0043F6C5                 push    1
.text:0043F6C7                 call    CWnd::UpdateData(int)
.text:0043F6CC                 mov     ecx, [esi+1A0h]
.text:0043F6D2                 lea     eax, [esi+188h]
.text:0043F6D8                 push    eax
.text:0043F6D9                 call    CString::operator=(CString const &)
.text:0043F6DE                 mov     ecx, [esi+1A0h]
.text:0043F6E4                 lea     eax, [esi+18Ch]
.text:0043F6EA                 push    eax
.text:0043F6EB                 add     ecx, 4
.text:0043F6EE                 call    CString::operator=(CString const &)
.text:0043F6F3                 mov     ecx, [esi+1A0h]
.text:0043F6F9                 lea     eax, [esi+190h]
.text:0043F6FF                 push    eax
.text:0043F700                 add     ecx, 8
.text:0043F703                 call    CString::operator=(CString const &)
.text:0043F708                 mov     ecx, [esi+1A0h]
.text:0043F70E                 lea     eax, [esi+194h]
.text:0043F714                 push    eax
.text:0043F715                 add     ecx, 0Ch
.text:0043F718                 call    CString::operator=(CString const &)
.text:0043F71D                 mov     ecx, [esi+1A0h]
.text:0043F723                 lea     eax, [esi+198h]
.text:0043F729                 push    eax
.text:0043F72A                 add     ecx, 10h
.text:0043F72D                 call    CString::operator=(CString const &)
.text:0043F732                 lea     eax, [esi+19Ch]
.text:0043F738                 push    0
.text:0043F73A                 push    eax
.text:0043F73B                 mov     ecx, offset unk_5ECE48
.text:0043F740                 call    sub_46CB82             //这里是关键函数,下面着重分析
.text:0043F745                 test    eax, eax
.text:0043F747                 jz      short loc_43F750       //返回0就失败了
.text:0043F749                 mov     ecx, esi
.text:0043F74B                 call    CDialog::OnOK(void)
.text:0043F750
.text:0043F750 loc_43F750:                            
.text:0043F750                 mov     eax, dword_5D537C      //到这里就是注册失败提示了
.text:0043F755                 mov     [ebp-10h], eax
.text:0043F758                 and     dword ptr [ebp-4], 0
.text:0043F75C                 push    0Dh             ; Invalid License Key. Please try again or contact Wisdom Software
.text:0043F75E                 lea     ecx, [ebp-10h]
.text:0043F761                 call    CString::LoadStringA(uint)
.text:0043F766                 push    1037h
.text:0043F76B                 mov     ecx, esi
.text:0043F76D                 call    CWnd::GetDlgItem(int)
.text:0043F772                 test    eax, eax
.text:0043F774                 jz      short loc_43F780
.text:0043F776                 push    dword ptr [ebp-10h]
.text:0043F779                 mov     ecx, eax
.text:0043F77B                 call    CWnd::SetWindowTextA(char const *)
.text:0043F780
.text:0043F780 loc_43F780:                             
.text:0043F780                 lea     ecx, [esi+14Ch]
.text:0043F786                 call    CWnd::SetFocus(void)
.text:0043F78B                 or      dword ptr [ebp-4], 0FFFFFFFFh
.text:0043F78F                 lea     ecx, [ebp-10h]
.text:0043F792                 call    CString::~CString(void)
.text:0043F797                 mov     ecx, [ebp-0Ch]
.text:0043F79A                 pop     esi
.text:0043F79B                 mov     large fs:0, ecx
.text:0043F7A2                 leave
.text:0043F7A3                 retn
.text:0043F7A3 sub_43F6B7      endp ; sp =  4
;=================================================================================

    跟进关键函数46CB82:

.text:0046CB82 sub_46CB82      proc near              
.text:0046CB82                 mov     eax, offset unknown_libname_1421
.text:0046CB87                 call    __EH_prolog
.text:0046CB8C                 push    ecx
.text:0046CB8D                 push    ebx
.text:0046CB8E                 xor     ebx, ebx
.text:0046CB90                 push    esi
.text:0046CB91                 push    edi
.text:0046CB92                 mov     esi, ecx
.text:0046CB94                 mov     [ebp-10h], ebx
.text:0046CB97                 push    ebx
.text:0046CB98                 push    ebx
.text:0046CB99                 push    0F003Fh
.text:0046CB9E                 push    ebx
.text:0046CB9F                 push    ebx
.text:0046CBA0                 lea     ecx, [ebp-10h]
.text:0046CBA3                 push    dword_5F0CC8
.text:0046CBA9                 mov     [ebp-4], ebx
.text:0046CBAC                 push    80000001h
.text:0046CBB1                 call    sub_466121
.text:0046CBB6                 cmp     eax, ebx
.text:0046CBB8                 jl      loc_46CCFE
.text:0046CBBE                 push    dword ptr [ebp+0Ch]
.text:0046CBC1                 mov     edi, [ebp+8]
.text:0046CBC4                 push    edi
.text:0046CBC5                 call    fun1_422C8E       //检验函数1 *****
.text:0046CBCA                 pop     ecx
.text:0046CBCB                 test    eax, eax
.text:0046CBCD                 pop     ecx
.text:0046CBCE                 jz      loc_46CCFC
.text:0046CBD4
.text:0046CBD4 loc_46CBD4:                             
.text:0046CBD4                 mov     eax, ebx
.text:0046CBD6                 mov     ecx, ebx
.text:0046CBD8                 add     eax, [edi+4]
.text:0046CBDB                 add     ecx, [esi+120h]
.text:0046CBE1                 push    eax
.text:0046CBE2                 call    CString::operator=(CString const &)
.text:0046CBE7                 add     ebx, 4
.text:0046CBEA                 cmp     ebx, 20            //把5组注册码拷贝到[esi+120h]处
.text:0046CBED                 jl      short loc_46CBD4
.text:0046CBEF                 push    1
.text:0046CBF1                 lea     eax, [esi+11Ch]
.text:0046CBF7                 pop     ebx
.text:0046CBF8                 push    eax
.text:0046CBF9                 mov     [esi+130h], ebx
.text:0046CBFF                 call    fun2_422EF1        //检验函数2 *****
.text:0046CC04                 test    eax, eax
.text:0046CC06                 pop     ecx
.text:0046CC07                 jz      short loc_46CC0F
.text:0046CC09                 mov     [esi+134h], ebx
.text:0046CC0F
.text:0046CC0F loc_46CC0F:                             
.text:0046CC0F                 mov     ecx, [esi+120h]
.text:0046CC15                 lea     eax, [ebp+0Ch]
.text:0046CC18                 push    ebx             ; 1
.text:0046CC19                 push    eax
.text:0046CC1A                 add     ecx, 8
.text:0046CC1D                 call    CString::Left(int) //取第三组注册码左边一个字符
.text:0046CC22                 push    eax
.text:0046CC23                 lea     ecx, [esi+4C4h]    //保存到这里
.text:0046CC29                 mov     [ebp-4], bl
.text:0046CC2C                 call    CString::operator=(CString const &)
.text:0046CC31                 and     byte ptr [ebp-4], 0
.text:0046CC35                 lea     ecx, [ebp+0Ch]
.text:0046CC38                 call    CString::~CString(void)
.text:0046CC3D                 mov     ecx, [esi+120h]
.text:0046CC43                 lea     eax, [ebp+0Ch]
.text:0046CC46                 push    2
.text:0046CC48                 push    eax
.text:0046CC49                 add     ecx, 4
.text:0046CC4C                 call    CString::Left(int) //取第二组注册码左边2个字符
.text:0046CC51                 push    eax
.text:0046CC52                 lea     ecx, [esi+4C8h]    //保存到这里
.text:0046CC58                 mov     byte ptr [ebp-4], 2
.text:0046CC5C                 call    CString::operator=(CString const &)
.text:0046CC61                 and     byte ptr [ebp-4], 0
.text:0046CC65                 lea     ecx, [ebp+0Ch]
.text:0046CC68                 call    CString::~CString(void)
.text:0046CC6D                 xor     edi, edi
.text:0046CC6F
.text:0046CC6F loc_46CC6F:                             
.text:0046CC6F                 mov     eax, edi
.text:0046CC71                 push    ebx             ; 1
.text:0046CC72                 add     eax, [esi+120h]
.text:0046CC78                 push    eax
.text:0046CC79                 call    sub_4230E4      ; 对字符串加密处理
.text:0046CC7E                 add     edi, 4
.text:0046CC81                 pop     ecx
.text:0046CC82                 cmp     edi, 14h
.text:0046CC85                 pop     ecx
.text:0046CC86                 jl      short loc_46CC6F
.text:0046CC88                 mov     eax, [esi+120h]
.text:0046CC8E                 lea     ecx, [ebp-10h]
.text:0046CC91                 push    dword ptr [eax] ; 以下5个函数保存注册码到注册表
.text:0046CC93                 push    key_5F0F5C
.text:0046CC99                 call    sub_466387
.text:0046CC9E                 mov     eax, [esi+120h]
.text:0046CCA4                 lea     ecx, [ebp-10h]
.text:0046CCA7                 push    dword ptr [eax+4]
.text:0046CCAA                 push    key_5F0F58
.text:0046CCB0                 call    sub_466387
.text:0046CCB5                 mov     eax, [esi+120h]
.text:0046CCBB                 lea     ecx, [ebp-10h]
.text:0046CCBE                 push    dword ptr [eax+8]
.text:0046CCC1                 push    key_5F0F54
.text:0046CCC7                 call    sub_466387
.text:0046CCCC                 mov     eax, [esi+120h]
.text:0046CCD2                 lea     ecx, [ebp-10h]
.text:0046CCD5                 push    dword ptr [eax+0Ch]
.text:0046CCD8                 push    key_5F0F50
.text:0046CCDE                 call    sub_466387
.text:0046CCE3                 mov     eax, [esi+120h]
.text:0046CCE9                 lea     ecx, [ebp-10h]
.text:0046CCEC                 push    dword ptr [eax+10h]
.text:0046CCEF                 push    key_5F0F4C
.text:0046CCF5                 call    sub_466387
.text:0046CCFA                 jmp     short loc_46CCFE
.text:0046CCFC ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:0046CCFC
.text:0046CCFC loc_46CCFC:                            
.text:0046CCFC                 xor     ebx, ebx
.text:0046CCFE
.text:0046CCFE loc_46CCFE:                            
.text:0046CCFE                                         
.text:0046CCFE                 or      dword ptr [ebp-4], 0FFFFFFFFh
.text:0046CD02                 lea     ecx, [ebp-10h]
.text:0046CD05                 call    sub_46610A
.text:0046CD0A                 mov     ecx, [ebp-0Ch]
.text:0046CD0D                 pop     edi
.text:0046CD0E                 mov     eax, ebx
.text:0046CD10                 pop     esi
.text:0046CD11                 pop     ebx
.text:0046CD12                 mov     large fs:0, ecx
.text:0046CD19                 leave
.text:0046CD1A                 retn    8
.text:0046CD1A sub_46CB82      endp ; sp =  4

    可以看出,上面共有2个验证的函数,下面分别分析:
    先看fun1_422C8E:
=================================================================
text:00422C8E fun1_422C8E     proc near              
.text:00422C8E                                        
.text:00422C8E                 mov     eax, offset unknown_libname_1253
.text:00422C93                 call    __EH_prolog
.text:00422C98                 sub     esp, 44h
.text:00422C9B                 push    ebx
.text:00422C9C                 push    esi
.text:00422C9D                 mov     esi, [ebp+8]
.text:00422CA0                 push    edi
.text:00422CA1                 mov     eax, [esi+8]
.text:00422CA4                 cmp     eax, 5
.text:00422CA7                 jnz     loc_422E62
.text:00422CAD                 mov     eax, [esi+4]
.text:00422CB0                 xor     ebx, ebx
.text:00422CB2                 xor     ecx, ecx
.text:00422CB4
.text:00422CB4 loc_422CB4:                             
.text:00422CB4                 mov     edx, [eax]
.text:00422CB6                 cmp     dword ptr [edx-8], 4
.text:00422CBA                 jnz     loc_422E64
.text:00422CC0                 inc     ecx
.text:00422CC1                 add     eax, 4
.text:00422CC4                 cmp     ecx, 5                  ; 检查5组注册码是否都是4个字符
.text:00422CC7                 jl      short loc_422CB4
.text:00422CC9                 xor     edi, edi
.text:00422CCB
.text:00422CCB loc_422CCB:                            
.text:00422CCB                 mov     eax, [esi+4]
.text:00422CCE                 push    dword ptr [edi+eax]     ; char *
.text:00422CD1                 lea     eax, [ebp-28h]
.text:00422CD4                 push    eax                     ; char *
.text:00422CD5                 call    _strcpy                 ; 拷贝一组注册码到 [ebp-28]
.text:00422CDA                 movzx   eax, byte ptr [ebp-26h] ; 取第三个字符到eax
.text:00422CDE                 pop     ecx
.text:00422CDF                 pop     ecx
.text:00422CE0                 movzx   ecx, byte ptr [ebp-27h] ; 取第二个字符到ecx
.text:00422CE4                 add     eax, ecx                ; 第三个字符和第二个字符相加,和到eax
.text:00422CE6                 push    26
.text:00422CE8                 movzx   ecx, byte ptr [ebp-28h] ; 取第一个字符到ecx
.text:00422CEC                 add     eax, ecx                ; 上面的和和第一个字符相加,和到eax
.text:00422CEE                 pop     ecx
.text:00422CEF                 cdq
.text:00422CF0                 idiv    ecx                     ; 和模上26
.text:00422CF2                 add     dl, 40h                 ; 加上40h
.text:00422CF5                 cmp     dl, 40h
.text:00422CF8                 jnz     short loc_422CFD
.text:00422CFA                 add     dl, 26                  ; 结果为40h则再加上26
.text:00422CFD
.text:00422CFD loc_422CFD:                             
.text:00422CFD                 cmp     dl, [ebp-25h]           ; 和第四个字符比较,不等则失败
.text:00422D00                 jnz     loc_422E64
.text:00422D06                 add     edi, 4
.text:00422D09                 cmp     edi, 10h                ; 依次处理前4组
.text:00422D0C                 jl      short loc_422CCB
.text:00422D0E                 mov     [ebp-10h], ebx          ;索引初始化为0
.text:00422D11                 mov     ebx, offset asc_5C8424 ; "------"
.text:00422D16
.text:00422D16 loc_422D16:                            
.text:00422D16                 mov     esi, ebx
.text:00422D18                 lea     edi, [ebp-48h]           ;[ebp-48]填充6个"-"字符
.text:00422D1B                 movsd
.text:00422D1C                 push    1
.text:00422D1E                 lea     eax, [ebp-14h]
.text:00422D21                 push    dword ptr [ebp-10h]      ;索引
.text:00422D24                 movsw
.text:00422D26                 push    eax
.text:00422D27                 mov     eax, [ebp+8]
.text:00422D2A                 movsb
.text:00422D2B                 mov     ecx, [eax+4]             ;第一组注册码 
.text:00422D2E                 call    CString::Mid(int,int)
.text:00422D33                 push    dword ptr [eax] ; char * ;取第一组注册码索引处一个字符
.text:00422D35                 lea     eax, [ebp-48h]
.text:00422D38                 push    eax             ; char *
.text:00422D39                 call    _strcpy                  ;拷贝到[ebp-48]
.text:00422D3E                 pop     ecx
.text:00422D3F                 pop     ecx
.text:00422D40                 lea     ecx, [ebp-14h]
.text:00422D43                 call    CString::~CString(void)
.text:00422D48                 mov     esi, ebx
.text:00422D4A                 lea     edi, [ebp-40h]
.text:00422D4D                 push    1
.text:00422D4F                 lea     eax, [ebp-18h]
.text:00422D52                 push    dword ptr [ebp-10h]      ;索引
.text:00422D55                 movsd
.text:00422D56                 push    eax
.text:00422D57                 mov     eax, [ebp+8]
.text:00422D5A                 movsw
.text:00422D5C                 mov     ecx, [eax+4]
.text:00422D5F                 add     ecx, 4                   ;第二组注册码
.text:00422D62                 movsb
.text:00422D63                 call    CString::Mid(int,int)
.text:00422D68                 push    dword ptr [eax] ; char * ;取第二组注册码索引处一个字符
.text:00422D6A                 lea     eax, [ebp-40h]
.text:00422D6D                 push    eax             ; char *
.text:00422D6E                 call    _strcpy                  ;拷贝到[ebp-40]
.text:00422D73                 pop     ecx
.text:00422D74                 pop     ecx
.text:00422D75                 lea     ecx, [ebp-18h]
.text:00422D78                 call    CString::~CString(void)
.text:00422D7D                 mov     esi, ebx
.text:00422D7F                 lea     edi, [ebp-38h]
.text:00422D82                 push    1
.text:00422D84                 lea     eax, [ebp-1Ch]
.text:00422D87                 push    dword ptr [ebp-10h]      ;索引
.text:00422D8A                 movsd
.text:00422D8B                 push    eax
.text:00422D8C                 mov     eax, [ebp+8]
.text:00422D8F                 movsw
.text:00422D91                 mov     ecx, [eax+4]
.text:00422D94                 add     ecx, 8                    ;第三组注册码
.text:00422D97                 movsb
.text:00422D98                 call    CString::Mid(int,int)     ;取第三组注册码索引处一个字符
.text:00422D9D                 push    dword ptr [eax] ; char *
.text:00422D9F                 lea     eax, [ebp-38h]
.text:00422DA2                 push    eax             ; char *
.text:00422DA3                 call    _strcpy                   ;拷贝到[ebp-38]
.text:00422DA8                 pop     ecx
.text:00422DA9                 pop     ecx
.text:00422DAA                 lea     ecx, [ebp-1Ch]
.text:00422DAD                 call    CString::~CString(void)
.text:00422DB2                 mov     esi, ebx
.text:00422DB4                 lea     edi, [ebp-30h]
.text:00422DB7                 push    1
.text:00422DB9                 lea     eax, [ebp-20h]
.text:00422DBC                 push    dword ptr [ebp-10h]       ;索引
.text:00422DBF                 movsd
.text:00422DC0                 push    eax
.text:00422DC1                 mov     eax, [ebp+8]
.text:00422DC4                 movsw
.text:00422DC6                 mov     ecx, [eax+4]
.text:00422DC9                 add     ecx, 0Ch                  ;第四组注册码
.text:00422DCC                 movsb
.text:00422DCD                 call    CString::Mid(int,int)     ;取第四组注册码索引处一个字符
.text:00422DD2                 push    dword ptr [eax] ; char *
.text:00422DD4                 lea     eax, [ebp-30h]
.text:00422DD7                 push    eax             ; char *
.text:00422DD8                 call    _strcpy                   ;拷贝到[ebp-30]
.text:00422DDD                 pop     ecx
.text:00422DDE                 pop     ecx
.text:00422DDF                 lea     ecx, [ebp-20h]
.text:00422DE2                 call    CString::~CString(void)
.text:00422DE7                 mov     esi, ebx
.text:00422DE9                 lea     edi, [ebp-50h]
.text:00422DEC                 push    1
.text:00422DEE                 lea     eax, [ebp-28h]
.text:00422DF1                 push    dword ptr [ebp-10h]       ;索引
.text:00422DF4                 movsd
.text:00422DF5                 push    eax
.text:00422DF6                 mov     eax, [ebp+8]
.text:00422DF9                 movsw
.text:00422DFB                 mov     ecx, [eax+4]
.text:00422DFE                 add     ecx, 10h                  ;第五组注册码
.text:00422E01                 movsb
.text:00422E02                 call    CString::Mid(int,int)     ;取第五组注册码索引处一个字符
.text:00422E07                 push    dword ptr [eax] ; char *
.text:00422E09                 lea     eax, [ebp-50h]
.text:00422E0C                 push    eax             ; char *
.text:00422E0D                 call    _strcpy                   ;拷贝到[ebp-50]
.text:00422E12                 pop     ecx
.text:00422E13                 pop     ecx
.text:00422E14                 lea     ecx, [ebp-28h]
.text:00422E17                 call    CString::~CString(void)
.text:00422E1C                 movzx   eax, byte ptr [ebp-30h]
.text:00422E20                 movzx   ecx, byte ptr [ebp-38h]
.text:00422E24                 add     eax, ecx
.text:00422E26                 push    36
.text:00422E28                 movzx   ecx, byte ptr [ebp-40h]
.text:00422E2C                 add     eax, ecx
.text:00422E2E                 movzx   ecx, byte ptr [ebp-48h]
.text:00422E32                 add     eax, ecx                  ;前4个字符相加
.text:00422E34                 pop     ecx
.text:00422E35                 cdq
.text:00422E36                 idiv    ecx                       ;和模上36
.text:00422E38                 add     dl, 64                    ;加上64
.text:00422E3B                 cmp     dl, 'Z'
.text:00422E3E                 jbe     short loc_422E43          ;结果大于字符'Z'则减去42
.text:00422E40                 add     dl, -42
.text:00422E43
.text:00422E43 loc_422E43:                             
.text:00422E43                 cmp     dl, [ebp-50h]             ;和第五个字符比较
.text:00422E46                 jnz     short loc_422E62
.text:00422E48                 inc     dword ptr [ebp-10h]       ;索引加1
.text:00422E4B                 cmp     dword ptr [ebp-10h], 4
.text:00422E4F                 jl      loc_422D16
.text:00422E55                 push    dword ptr [ebp+8]         ;注册码压入堆栈
.text:00422E58                 call    fun3_42306F               ;调用验证函数 42306F
.text:00422E5D                 test    eax, eax
.text:00422E5F                 pop     ecx
.text:00422E60                 jnz     short loc_422EDF          ;验证函数 42306F 返回非零值则本函数返回1
.text:00422E62
.text:00422E62 loc_422E62:                             
.text:00422E62                                         
.text:00422E62                 xor     ebx, ebx                  ;跳到这里就验证失败了
.text:00422E64
.text:00422E64 loc_422E64:                            
.text:00422E64                                         
.text:00422E64                 cmp     [ebp+0Ch], ebx
.text:00422E67                 jz      short loc_422EDB
.text:00422E69                 mov     eax, dword_5D537C
.text:00422E6E                 mov     [ebp+0Ch], eax
.text:00422E71                 push    0Dh             ; Invalid License Key. Please try again or contact Wisdom Software.
.text:00422E73                 lea     ecx, [ebp+0Ch]
.text:00422E76                 mov     [ebp-4], ebx
.text:00422E79                 call    CString::LoadStringA(uint)
.text:00422E7E                 mov     eax, dword_5D537C
.text:00422E83                 mov     [ebp+8], eax
.text:00422E86                 push    0Eh             ; ScreenHunter Message
.text:00422E88                 lea     ecx, [ebp+8]
.text:00422E8B                 mov     byte ptr [ebp-4], 1
.text:00422E8F                 call    CString::LoadStringA(uint)
.text:00422E94                 push    dword ptr [ebp+8] ; lpWindowName
.text:00422E97                 push    ebx             ; lpClassName
.text:00422E98                 call    ds:FindWindowA
.text:00422E9E                 cmp     eax, ebx
.text:00422EA0                 mov     eax, [ebp+8]
.text:00422EA3                 jz      short loc_422EAA
.text:00422EA5                 cmp     [eax-8], ebx
.text:00422EA8                 jg      short loc_422EC3
.text:00422EAA
.text:00422EAA loc_422EAA:                             
.text:00422EAA                 cmp     dword_5ED0C4, 6
.text:00422EB1                 jz      short loc_422EC3
.text:00422EB3                 push    40010h          ; uType
.text:00422EB8                 push    eax             ; lpCaption
.text:00422EB9                 push    dword ptr [ebp+0Ch] ; lpText
.text:00422EBC                 push    ebx             ; hWnd
.text:00422EBD                 call    ds:MessageBoxA
.text:00422EC3
.text:00422EC3 loc_422EC3:                             
.text:00422EC3                                         
.text:00422EC3                 and     byte ptr [ebp-4], 0
.text:00422EC7                 lea     ecx, [ebp+8]
.text:00422ECA                 call    CString::~CString(void)
.text:00422ECF                 or      dword ptr [ebp-4], 0FFFFFFFFh
.text:00422ED3                 lea     ecx, [ebp+0Ch]
.text:00422ED6                 call    CString::~CString(void)
.text:00422EDB
.text:00422EDB loc_422EDB:                             
.text:00422EDB                 xor     eax, eax
.text:00422EDD                 jmp     short loc_422EE2
.text:00422EDF ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00422EDF
.text:00422EDF loc_422EDF:                             
.text:00422EDF                 push    1
.text:00422EE1                 pop     eax
.text:00422EE2
.text:00422EE2 loc_422EE2:                             
.text:00422EE2                 mov     ecx, [ebp-0Ch]
.text:00422EE5                 pop     edi
.text:00422EE6                 pop     esi
.text:00422EE7                 pop     ebx
.text:00422EE8                 mov     large fs:0, ecx
.text:00422EEF                 leave
.text:00422EF0                 retn
.text:00422EF0 fun1_422C8E     endp ; sp =  4

;=================================================================================
    fun1_422C8E里还调用到了函数 fun3_42306F,来到下面看看:

.text:0042306F fun3_42306F     proc near               
.text:0042306F                                        
.text:0042306F                                        
.text:0042306F
.text:0042306F arg_0           = dword ptr  8
.text:0042306F
.text:0042306F                 push    ebp
.text:00423070                 mov     ebp, esp
.text:00423072                 push    esi
.text:00423073                 mov     esi, [ebp+arg_0]
.text:00423076                 push    edi
.text:00423077                 lea     eax, [ebp+arg_0]
.text:0042307A                 mov     ecx, [esi+4]              ;第一组注册码
.text:0042307D                 push    3
.text:0042307F                 push    eax
.text:00423080                 call    CString::Left(int)        ;取前3位
.text:00423085                 push    dword ptr [eax] ; char *
.text:00423087                 push    dword_5DFEA0    ; "SH4"
.text:0042308D                 call    _strcmp                   ;比较是否是"SH4"
.text:00423092                 pop     ecx
.text:00423093                 mov     edi, eax
.text:00423095                 pop     ecx
.text:00423096                 lea     ecx, [ebp+arg_0]
.text:00423099                 call    CString::~CString(void)
.text:0042309E                 test    edi, edi
.text:004230A0                 jnz     short loc_4230D2          ;不等则跳
.text:004230A2                 mov     ecx, [esi+4]
.text:004230A5                 push    1
.text:004230A7                 lea     eax, [ebp+arg_0]
.text:004230AA                 push    2
.text:004230AC                 push    eax
.text:004230AD                 add     ecx, 4                    ;第二组注册码
.text:004230B0                 call    CString::Mid(int,int)     ;取第三个字符
.text:004230B5                 push    dword ptr [eax] ; char *
.text:004230B7                 push    dword_5DFE9C    ; "9"
.text:004230BD                 call    _strcmp                   ;比较是否是"9"
.text:004230C2                 pop     ecx
.text:004230C3                 mov     esi, eax
.text:004230C5                 pop     ecx
.text:004230C6                 lea     ecx, [ebp+arg_0]
.text:004230C9                 call    CString::~CString(void)
.text:004230CE                 test    esi, esi
.text:004230D0                 jz      short loc_4230DD
.text:004230D2
.text:004230D2 loc_4230D2:                             
.text:004230D2                 and     dword_5ECF7C, 0           ;置全局注册失败标志
.text:004230D9                 xor     eax, eax                  ;失败则返回0
.text:004230DB                 jmp     short loc_4230E0
.text:004230DD ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:004230DD
.text:004230DD loc_4230DD:                          
.text:004230DD                 push    1
.text:004230DF                 pop     eax
.text:004230E0
.text:004230E0 loc_4230E0:                            
.text:004230E0                 pop     edi
.text:004230E1                 pop     esi
.text:004230E2                 pop     ebp
.text:004230E3                 retn
.text:004230E3 fun3_42306F     endp

=================================================================
    下面开始看 fun2_422EF1:

.text:00422EF1 fun2_422EF1     proc near               
.text:00422EF1                                         
.text:00422EF1
.text:00422EF1 var_30          = byte ptr -30h
.text:00422EF1 var_28          = byte ptr -28h
.text:00422EF1 var_20          = byte ptr -20h
.text:00422EF1 var_18          = dword ptr -18h
.text:00422EF1 var_14          = dword ptr -14h
.text:00422EF1 var_10          = dword ptr -10h
.text:00422EF1 var_C           = dword ptr -0Ch
.text:00422EF1 var_8           = dword ptr -8
.text:00422EF1 var_1           = byte ptr -1
.text:00422EF1 arg_0           = dword ptr  8
.text:00422EF1
.text:00422EF1                 push    ebp
.text:00422EF2                 mov     ebp, esp
.text:00422EF4                 sub     esp, 30h
.text:00422EF7                 push    ebx
.text:00422EF8                 push    esi
.text:00422EF9                 xor     esi, esi
.text:00422EFB                 push    edi
.text:00422EFC                 cmp     dword_5ECF88, esi
.text:00422F02                 jle     loc_423054
.text:00422F08                 cmp     dword_5ECF8C, esi
.text:00422F0E                 jle     loc_423054
.text:00422F14                 cmp     dword_5ECF90, esi
.text:00422F1A                 jle     loc_423054
.text:00422F20                 lea     eax, [ebp+var_C]
.text:00422F23                 push    eax
.text:00422F24                 call    CTime::GetTickCount(void)
.text:00422F29                 push    0FFFFFFFFh
.text:00422F2B                 push    esi
.text:00422F2C                 push    esi
.text:00422F2D                 push    esi
.text:00422F2E                 push    dword_5ECF90
.text:00422F34                 lea     ecx, [ebp+var_8]
.text:00422F37                 push    dword_5ECF8C
.text:00422F3D                 push    dword_5ECF88
.text:00422F43                 call    CTime::CTime(int,int,int,int,int,int,int)
.text:00422F48                 push    ecx
.text:00422F49                 mov     ecx, [ebp+var_8]
.text:00422F4C                 mov     eax, esp
.text:00422F4E                 mov     [ebp+var_18], esp
.text:00422F51                 mov     [eax], ecx
.text:00422F53                 lea     eax, [ebp+var_18]
.text:00422F56                 push    eax
.text:00422F57                 lea     ecx, [ebp+var_C]
.text:00422F5A                 call    sub_423060
.text:00422F5F                 mov     eax, [eax]
.text:00422F61                 mov     ecx, 15180h
.text:00422F66                 cdq
.text:00422F67                 idiv    ecx
.text:00422F69                 cmp     eax, 7          ; 随即检查
.text:00422F6C                 jl      loc_423054
.text:00422F72                 mov     eax, dword ptr a815 ; "815"
.text:00422F77                 mov     [ebp+var_8], esi ; 索引清零
.text:00422F7A                 mov     [ebp+var_14], eax
.text:00422F7D                 mov     ebx, offset asc_5C8424 ; "------"
.text:00422F82
.text:00422F82 loc_422F82:                            
.text:00422F82                 mov     esi, ebx
.text:00422F84                 lea     edi, [ebp+var_28]
.text:00422F87                 push    1
.text:00422F89                 lea     eax, [ebp+var_C]
.text:00422F8C                 push    [ebp+var_8]     ; 索引
.text:00422F8F                 movsd
.text:00422F90                 push    eax
.text:00422F91                 mov     eax, [ebp+arg_0]
.text:00422F94                 movsw
.text:00422F96                 mov     ecx, [eax+4]
.text:00422F99                 add     ecx, 4          ; 第二组注册码
.text:00422F9C                 movsb
.text:00422F9D                 call    CString::Mid(int,int) ; 取索引处一个字符
.text:00422FA2                 push    dword ptr [eax] ; char *
.text:00422FA4                 lea     eax, [ebp+var_28]
.text:00422FA7                 push    eax             ; char *
.text:00422FA8                 call    _strcpy         ; 拷贝到var_28
.text:00422FAD                 pop     ecx
.text:00422FAE                 pop     ecx
.text:00422FAF                 lea     ecx, [ebp+var_C]
.text:00422FB2                 call    CString::~CString(void)
.text:00422FB7                 mov     esi, ebx
.text:00422FB9                 lea     edi, [ebp+var_20]
.text:00422FBC                 movsd
.text:00422FBD                 movsw
.text:00422FBF                 movsb
.text:00422FC0                 mov     esi, [ebp+var_8] ; 索引
.text:00422FC3                 push    1
.text:00422FC5                 lea     eax, [ebp+var_10]
.text:00422FC8                 push    esi
.text:00422FC9                 push    eax
.text:00422FCA                 mov     eax, [ebp+arg_0]
.text:00422FCD                 mov     ecx, [eax+4]
.text:00422FD0                 add     ecx, 8          ; 第三组注册码
.text:00422FD3                 call    CString::Mid(int,int) ; 取索引处一个字符
.text:00422FD8                 push    dword ptr [eax] ; char *
.text:00422FDA                 lea     eax, [ebp+var_20]
.text:00422FDD                 push    eax             ; char *
.text:00422FDE                 call    _strcpy         ; 拷贝到var_20
.text:00422FE3                 pop     ecx
.text:00422FE4                 pop     ecx
.text:00422FE5                 lea     ecx, [ebp+var_10]
.text:00422FE8                 call    CString::~CString(void)
.text:00422FED                 movzx   eax, byte ptr [ebp+esi+var_14] ; 取字符串"815"索引处一个字符
.text:00422FF2                 movzx   ecx, [ebp+var_20]
.text:00422FF6                 add     eax, ecx        ; 加上第三组注册码一个字符
.text:00422FF8                 push    10
.text:00422FFA                 movzx   ecx, [ebp+var_28]
.text:00422FFE                 add     eax, ecx        ; 加上第二组注册码一个字符
.text:00423000                 pop     ecx
.text:00423001                 cdq
.text:00423002                 idiv    ecx             ; 模上10
.text:00423004                 mov     esi, ebx
.text:00423006                 lea     edi, [ebp+var_30]
.text:00423009                 push    1
.text:0042300B                 lea     eax, [ebp+var_18]
.text:0042300E                 push    [ebp+var_8]     ; 索引
.text:00423011                 movsd
.text:00423012                 push    eax
.text:00423013                 mov     eax, [ebp+arg_0]
.text:00423016                 movsw
.text:00423018                 mov     ecx, [eax+4]
.text:0042301B                 add     ecx, 12         ; 第四组注册码
.text:0042301E                 movsb
.text:0042301F                 add     dl, '0'         ; 模加上'0'
.text:00423022                 mov     [ebp+var_1], dl
.text:00423025                 call    CString::Mid(int,int) ; 取索引处一个字符
.text:0042302A                 push    dword ptr [eax] ; char *
.text:0042302C                 lea     eax, [ebp+var_30]
.text:0042302F                 push    eax             ; char *
.text:00423030                 call    _strcpy         ; 拷贝到var_30
.text:00423035                 pop     ecx
.text:00423036                 pop     ecx
.text:00423037                 lea     ecx, [ebp+var_18]
.text:0042303A                 call    CString::~CString(void)
.text:0042303F                 mov     al, [ebp+var_1]
.text:00423042                 cmp     al, [ebp+var_30] ; 比较
.text:00423045                 jnz     short loc_42305C
.text:00423047                 inc     [ebp+var_8]     ; 索引加1
.text:0042304A                 cmp     [ebp+var_8], 3  ; 共比较3次
.text:0042304E                 jl      loc_422F82
.text:00423054
.text:00423054 loc_423054:                             
.text:00423054                                                                                 
.text:00423054                 push    1
.text:00423056                 pop     eax
.text:00423057
.text:00423057 loc_423057:                             
.text:00423057                 pop     edi
.text:00423058                 pop     esi
.text:00423059                 pop     ebx
.text:0042305A                 leave
.text:0042305B                 retn
.text:0042305C ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:0042305C
.text:0042305C loc_42305C:                             
.text:0042305C                 xor     eax, eax
.text:0042305E                 jmp     short loc_423057
.text:0042305E fun2_422EF1     endp

===================================================================

    跟踪对话框的调用过程,可以来到下面,这里是取协议到多少用户的。
    第三组注册码第一个字符决定协议类型。
    如果协议类型是'G'则第二组注册码前两个字符是协议用户数。

.text:00423130 sub_423130      proc near              
.text:00423130                                        
.text:00423130                 push    esi
.text:00423131                 xor     esi, esi
.text:00423133                 push    my_5ED30C       ; char *
.text:00423139                 push    q_5DFE94_D      ; char *
.text:0042313F                 call    _strcmp
.text:00423144                 pop     ecx
.text:00423145                 test    eax, eax
.text:00423147                 pop     ecx
.text:00423148                 jnz     short loc_423152
.text:0042314A                 push    1
.text:0042314C
.text:0042314C loc_42314C:                            
.text:0042314C                 pop     esi
.text:0042314D                 jmp     loc_42329A
.text:00423152 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00423152
.text:00423152 loc_423152:                            
.text:00423152                 push    my_5ED30C       ; char *
.text:00423158                 push    q_5DFE8C_M      ; char *
.text:0042315E                 call    _strcmp
.text:00423163                 pop     ecx
.text:00423164                 test    eax, eax
.text:00423166                 pop     ecx
.text:00423167                 jnz     short loc_42316D
.text:00423169                 push    5
.text:0042316B                 jmp     short loc_42314C
.text:0042316D ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:0042316D
.text:0042316D loc_42316D:                            
.text:0042316D                 push    my_5ED30C       ; char *
.text:00423173                 push    q_5DFE88_P      ; char *
.text:00423179                 call    _strcmp
.text:0042317E                 pop     ecx
.text:0042317F                 test    eax, eax
.text:00423181                 pop     ecx
.text:00423182                 jnz     short loc_423188
.text:00423184                 push    10
.text:00423186                 jmp     short loc_42314C
.text:00423188 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00423188
.text:00423188 loc_423188:                           
.text:00423188                 push    my_5ED30C       ; char *
.text:0042318E                 push    q_5DFE84_Q      ; char *
.text:00423194                 call    _strcmp
.text:00423199                 pop     ecx
.text:0042319A                 test    eax, eax
.text:0042319C                 pop     ecx
.text:0042319D                 jnz     short loc_4231A3
.text:0042319F                 push    20
.text:004231A1                 jmp     short loc_42314C
.text:004231A3 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:004231A3
.text:004231A3 loc_4231A3:                            
.text:004231A3                 push    my_5ED30C       ; char *
.text:004231A9                 push    q_5DFE80_R      ; char *
.text:004231AF                 call    _strcmp
.text:004231B4                 pop     ecx
.text:004231B5                 test    eax, eax
.text:004231B7                 pop     ecx
.text:004231B8                 jnz     short loc_4231BE
.text:004231BA                 push    50
.text:004231BC                 jmp     short loc_42314C
.text:004231BE ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:004231BE
.text:004231BE loc_4231BE:                            
.text:004231BE                 push    my_5ED30C       ; char *
.text:004231C4                 push    q_5DFE7C_S      ; char *
.text:004231CA                 call    _strcmp
.text:004231CF                 pop     ecx
.text:004231D0                 test    eax, eax
.text:004231D2                 pop     ecx
.text:004231D3                 jnz     short loc_4231DC
.text:004231D5                 push    100
.text:004231D7                 jmp     loc_42314C
.text:004231DC ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:004231DC
.text:004231DC loc_4231DC:                            
.text:004231DC                 push    my_5ED30C       ; char *
.text:004231E2                 push    q_5DFE78_T      ; char *
.text:004231E8                 call    _strcmp
.text:004231ED                 pop     ecx
.text:004231EE                 test    eax, eax
.text:004231F0                 pop     ecx
.text:004231F1                 jnz     short loc_4231FD
.text:004231F3                 mov     esi, 200
.text:004231F8                 jmp     loc_42329A
.text:004231FD ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:004231FD
.text:004231FD loc_4231FD:                            
.text:004231FD                 push    my_5ED30C       ; char *
.text:00423203                 push    q_5DFE74_U      ; char *
.text:00423209                 call    _strcmp
.text:0042320E                 pop     ecx
.text:0042320F                 test    eax, eax
.text:00423211                 pop     ecx
.text:00423212                 jnz     short loc_42321B
.text:00423214                 mov     esi, 500
.text:00423219                 jmp     short loc_42329A
.text:0042321B ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:0042321B
.text:0042321B loc_42321B:                            
.text:0042321B                 push    my_5ED30C       ; char *
.text:00423221                 push    q_5DFE70_V      ; char *
.text:00423227                 call    _strcmp
.text:0042322C                 pop     ecx
.text:0042322D                 test    eax, eax
.text:0042322F                 pop     ecx
.text:00423230                 jnz     short loc_423239
.text:00423232                 mov     esi, 1000
.text:00423237                 jmp     short loc_42329A
.text:00423239 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00423239
.text:00423239 loc_423239:                            
.text:00423239                 push    my_5ED30C       ; char *
.text:0042323F                 push    q_5DFE6C_W      ; char *
.text:00423245                 call    _strcmp
.text:0042324A                 pop     ecx
.text:0042324B                 test    eax, eax
.text:0042324D                 pop     ecx
.text:0042324E                 jnz     short loc_423257
.text:00423250                 mov     esi, 2000
.text:00423255                 jmp     short loc_42329A
.text:00423257 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00423257
.text:00423257 loc_423257:                             
.text:00423257                 push    my_5ED30C       ; char *
.text:0042325D                 push    q_5DFE68_X      ; char *
.text:00423263                 call    _strcmp
.text:00423268                 pop     ecx
.text:00423269                 test    eax, eax
.text:0042326B                 pop     ecx
.text:0042326C                 jnz     short loc_423275
.text:0042326E                 mov     esi, 5000
.text:00423273                 jmp     short loc_42329A
.text:00423275 ; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪
.text:00423275
.text:00423275 loc_423275:                             
.text:00423275                 push    my_5ED30C       ; char *
.text:0042327B                 push    q_5DFE90_G      ; char *
.text:00423281                 call    _strcmp
.text:00423286                 pop     ecx
.text:00423287                 test    eax, eax
.text:00423289                 pop     ecx
.text:0042328A                 jnz     short loc_42329A
.text:0042328C                 push    my_5ED310       ; char *
.text:00423292                 call    _atoi
.text:00423297                 pop     ecx
.text:00423298                 mov     esi, eax
.text:0042329A
.text:0042329A loc_42329A:                            
.text:0042329A                 mov     eax, esi
.text:0042329C                 pop     esi
.text:0042329D                 retn
.text:0042329D sub_423130      endp

GetUserCnt(void)
{
    char UserCnt;     //第三组注册码左边一个字符
    char count[3];    //第二组注册码左边两个字符
    
    if(UserCnt == 'D')return 1;
    if(UserCnt == 'M')return 5;
    if(UserCnt == 'P')return 10;
    if(UserCnt == 'Q')return 20;
    if(UserCnt == 'R')return 50;
    if(UserCnt == 'S')return 100;
    if(UserCnt == 'T')return 200;
    if(UserCnt == 'U')return 500;
    if(UserCnt == 'V')return 1000;
    if(UserCnt == 'W')return 2000;
    if(UserCnt == 'X')return 5000;
    if(UserCnt == 'G')reutrn atoi(count);
    return 0;
}
======================================================================
    好了,该总结一下了:
    
    先看看注册码的格式: XXXX-XXXX-XXXX-XXXX-XXXX
    这里注册码分了5组,每组4位。为了方便表示,我把5组注册码简称key[0],key[1],key[2],key[3],key[4],
并且把每组注册码中的一个字符简称key[0][0],key[0][1] ...。
    key[0]的前3位是固定的,为"SH4"。
    key[1][2]也是固定的,为'9'。
    key[3]的前3个字符由key[1],key[2]和字符串"815"决定。
    每组的第4个字符由前面的3个字符决定。
    第5组的4个字符由前面的4组决定。
    第三组注册码前一个字符决定协议类型。
    第二组注册码和协议用户数有关。
    
    下面给出注册机的源代码:
{
    SYSTEMTIME tm;
  unsigned long seed;
  char key[5][5];
  int i;
  int sum;
  char tmp[4] = "815";
  char lk[25];

  GetSystemTime(&tm);
  seed = tm.wDay + tm.wDayOfWeek + tm.wHour + tm.wMilliseconds 
    + tm.wMinute + tm.wMonth + tm.wSecond + tm.wYear;
  srand(seed);

  memset(key,0,sizeof(key) / sizeof(char));
  strcpy(key[0],"SH4Y");

  key[1][0] = rand() % 9 + '1';
  key[1][1] = rand() % 10 + '0';
  key[1][2] = '9';

  key[2][0] = 'X';
  key[2][1] = rand() % 26 + 'A';
  key[2][2] = rand() % 26 + 'A';

  for(i = 0; i < 3; i ++)
  {
    sum = tmp[i] + key[1][i] + key[2][i];
    sum = sum % 10 + '0';
    key[3][i] = sum;
  }

    for(i = 1; i < 4; i ++)
  {
    sum = key[i][0] + key[i][1] + key[i][2];
    sum = sum % 26 + 0x40;
        if(sum == 0x40)sum += 26;
    key[i][3] = sum;
  }
  for(i = 0; i < 4; i ++)
  {
    sum = key[0][i] + key[1][i] + key[2][i] + key[3][i];
    sum = sum % 36 + 64;
    if(sum > 'Z') sum -= 42;
    key[4][i] = sum;
  }

  sprintf(lk,"%s-%s-%s-%s-%s",key[0],key[1],key[2],key[3],key[4]);
  m_key = lk;
    UpdateData(false);
}

=========================================================================
    [全文完]