-
-
[原创]ScreenHunter 4.2 Pro 注册算法分析
-
发表于: 2006-1-15 19:03 7053
-
【软件名称】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);
}
=========================================================================
[全文完]
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!