【文章标题】: [原创]RealVNC Enterprice Edition 4.5算法分析
【文章作者】: wuwenyao
【作者邮箱】: [email]wuwenyao.gm@gmail.com[/email]
【软件名称】: RealVNC Enterprice Edition 4.5
【下载地址】: http://www.realvnc.com/index.html
【加壳方式】: 未加壳
【编写语言】: C
【使用工具】: OllyDbg,peid,IDA
【操作平台】: win32
【软件介绍】: 远程控制软件,有免费版本,企业版需要注册
【作者声明】: 本文只是分析算法,不提供注册机,如果要使用,请向开发商购买。
--------------------------------------------------------------------------------
【详细过程】
最近用到远程控制,试了几个VNC版本,发现还是最原始的RealVNC好用,不过企业是收费的:(,花了几天分析了一下算法。
安装后,查看菜单,是使用"vncconfig.exe -noconsole -license"弹出注册码窗口,随便输入一个注册码,会弹出信息窗口提示注册错误。
OD载入vncconfig.exe,参数-noconsole -license,F9运行后,下MessageBoxW断点,F7,F8,CTRL+F9几次就可以找到验证注册码的部分了,这里不再详述过程。
下面看看算法过程:
注册码验证主体
.text:004084B0 ; =============== S U B R O U T I N E =======================================
.text:004084B0
.text:004084B0
.text:004084B0 sub_4084B0 proc near ; DATA XREF: .rdata:00459DC0o
.text:004084B0
.text:004084B0 var_2C = dword ptr -2Ch
.text:004084B0 var_28 = dword ptr -28h
.text:004084B0 Args = byte ptr -24h
.text:004084B0 var_20 = dword ptr -20h
.text:004084B0 Memory = dword ptr -1Ch
.text:004084B0 var_18 = dword ptr -18h
.text:004084B0 var_14 = dword ptr -14h
.text:004084B0 var_10 = dword ptr -10h
.text:004084B0 var_C = dword ptr -0Ch
.text:004084B0 var_4 = dword ptr -4
.text:004084B0
.text:004084B0 push -1
.text:004084B2 push offset sub_451258
.text:004084B7 mov eax, large fs:0
.text:004084BD push eax
.text:004084BE sub esp, 20h
.text:004084C1 push ebx
.text:004084C2 push ebp
.text:004084C3 push esi
.text:004084C4 push edi
.text:004084C5 mov eax, dword_472404
.text:004084CA xor eax, esp
.text:004084CC push eax
.text:004084CD lea eax, [esp+40h+var_C]
.text:004084D1 mov large fs:0, eax
.text:004084D7 mov edi, ecx
.text:004084D9 mov [esp+40h+var_2C], edi
.text:004084DD xor ebx, ebx ;ebx=0
.text:004084DF push ebx
.text:004084E0 lea ecx, [edi+3Ch]
.text:004084E3 call sub_41FDA0 ; 取注册码
.text:004084E8 push eax
.text:004084E9 call sub_416560 ; 注册码处理
.text:004084EE mov ebp, eax ; C结构指针,C[0]指向通过验证的注册码特征码
.text:004084F0 add esp, 4
.text:004084F3 mov [esp+40h+var_28], ebp ; C指针放入v_28
.text:004084F7 mov [esp+40h+Memory], ebx
.text:004084FB mov [esp+40h+var_18], ebx
.text:004084FF cmp ebp, ebx ;C结构指针不为0,跳转,继续
.text:00408501 mov [esp+40h+var_4], ebx
.text:00408505 jnz short loc_40851C
.text:00408507 push -1
.text:00408509 push offset aTheSuppliedL_0 ; "The supplied license key is invalid. Yo"...
.text:0040850E lea ecx, [esp+48h+Memory]
.text:00408512 call sub_40CBC0
.text:00408517 jmp loc_40870C
.text:0040851C ; ---------------------------------------------------------------------------
.text:0040851C
.text:0040851C loc_40851C: ; CODE XREF: sub_4084B0+55j
.text:0040851C mov ecx, ebp
.text:0040851E call sub_4165C0 ; C与当前时候校验
.text:00408523 test al, al ;返回不为0,跳转,继续
.text:00408525 jz short loc_40853C
.text:00408527 push -1
.text:00408529 push offset aTheSuppliedTri ; "The supplied trial license key has expi"...
.text:0040852E lea ecx, [esp+48h+Memory]
.text:00408532 call sub_40CBC0
.text:00408537 jmp loc_4086F1
.text:0040853C ; ---------------------------------------------------------------------------
.text:0040853C
.text:0040853C loc_40853C: ; CODE XREF: sub_4084B0+75j
.text:0040853C mov ecx, ds:dword_45AEF0 ;固定值,时间低位
.text:00408542 mov eax, ds:dword_45AEF4 ;固定值,时间高位
.text:00408547 sub ecx, 1E28500h ; 366天(一年)
.text:0040854D sbb eax, ebx
.text:0040854F cmp eax, [ebp+1Ch] ; [45AEF4]与C[0x1C]比较
.text:00408552 jl short loc_408570 ; 小于继续
.text:00408554 jg short loc_40855B
.text:00408556 cmp ecx, [ebp+18h] ; [45AEF0]-0x1E28500与C[0x18]比较
.text:00408559 jb short loc_408570 ; 小于继续
.text:0040855B
.text:0040855B loc_40855B: ; CODE XREF: sub_4084B0+A4j
.text:0040855B push -1
.text:0040855D push offset aTheSuppliedL_1 ; "The supplied license key is not valid f"...
.text:00408562 lea ecx, [esp+48h+Memory]
.text:00408566 call sub_40CBC0
.text:0040856B jmp loc_4086F1
.text:00408570 ; ---------------------------------------------------------------------------
.text:00408570
.text:00408570 loc_408570: ; CODE XREF: sub_4084B0+A2j
.text:00408570 ; sub_4084B0+A9j
.text:00408570 mov esi, [ebp+0] ;C[0]
.text:00408573 mov edi, [edi+50h] ;特征码0
.text:00408576 mov ecx, esi
.text:00408578 mov eax, edi
.text:0040857A lea ebx, [ebx+0]
.text:00408580
.text:00408580 loc_408580: ; CODE XREF: sub_4084B0+EAj
.text:00408580 mov dl, [eax] ; 比较特征码
.text:00408582 cmp dl, [ecx]
.text:00408584 jnz short loc_4085A0
.text:00408586 cmp dl, bl ;判断结束符0
.text:00408588 jz short loc_40859C
.text:0040858A mov dl, [eax+1]
.text:0040858D cmp dl, [ecx+1]
.text:00408590 jnz short loc_4085A0
.text:00408592 add eax, 2
.text:00408595 add ecx, 2
.text:00408598 cmp dl, bl
.text:0040859A jnz short loc_408580
.text:0040859C
.text:0040859C loc_40859C: ; CODE XREF: sub_4084B0+D8j
.text:0040859C xor eax, eax ;相等,则eax置0
.text:0040859E jmp short loc_4085A5
.text:004085A0 ; ---------------------------------------------------------------------------
.text:004085A0
.text:004085A0 loc_4085A0: ; CODE XREF: sub_4084B0+D4j
.text:004085A0 ; sub_4084B0+E0j
.text:004085A0 sbb eax, eax
.text:004085A2 sbb eax, 0FFFFFFFFh;不等,则eax置1
.text:004085A5
.text:004085A5 loc_4085A5: ; CODE XREF: sub_4084B0+EEj
.text:004085A5 cmp eax, ebx
.text:004085A7 jz loc_4086ED ;相等(eax=0),跳出,不等,继续
.text:004085AD mov ebp, off_470DB8 ;特征码1
.text:004085B3 mov eax, offset aVncEnterpriseE ; "VNC Enterprise Edition for Windows"
.text:004085B8 mov [esp+40h+var_10], edi
.text:004085BC mov dword ptr [esp+40h+Args], eax
.text:004085C0 mov [esp+40h+var_20], eax
.text:004085C4 mov [esp+40h+var_14], esi
.text:004085C8 xor edi, edi
.text:004085CA lea ebx, [ebx+0]
.text:004085D0
.text:004085D0 loc_4085D0: ; CODE XREF: sub_4084B0+217j
.text:004085D0 mov esi, [esp+edi+40h+var_14]
.text:004085D4 mov ecx, ebp
.text:004085D6 mov eax, esi
.text:004085D8
.text:004085D8 loc_4085D8: ; CODE XREF: sub_4084B0+142j
.text:004085D8 mov dl, [eax] ; 比较特征码
.text:004085DA cmp dl, [ecx]
.text:004085DC jnz short loc_4085F8
.text:004085DE cmp dl, bl
.text:004085E0 jz short loc_4085F4
.text:004085E2 mov dl, [eax+1]
.text:004085E5 cmp dl, [ecx+1]
.text:004085E8 jnz short loc_4085F8
.text:004085EA add eax, 2
.text:004085ED add ecx, 2
.text:004085F0 cmp dl, bl
.text:004085F2 jnz short loc_4085D8
.text:004085F4
.text:004085F4 loc_4085F4: ; CODE XREF: sub_4084B0+130j
.text:004085F4 xor eax, eax
.text:004085F6 jmp short loc_4085FD
.text:004085F8 ; ---------------------------------------------------------------------------
.text:004085F8
.text:004085F8 loc_4085F8: ; CODE XREF: sub_4084B0+12Cj
.text:004085F8 ; sub_4084B0+138j
.text:004085F8 sbb eax, eax
.text:004085FA sbb eax, 0FFFFFFFFh
.text:004085FD
.text:004085FD loc_4085FD: ; CODE XREF: sub_4084B0+146j
.text:004085FD cmp eax, ebx
.text:004085FF jnz short loc_40860E ;相等(eax=0),继续,不等,跳到下个比较
.text:00408601 mov dword ptr [esp+edi+40h+Args], offset aVncPersonalEdi ; "VNC Personal Edition for Windows"
.text:00408609 jmp loc_4086C1 ;转到提示版本不同信息
.text:0040860E ; ---------------------------------------------------------------------------
.text:0040860E
.text:0040860E loc_40860E: ; CODE XREF: sub_4084B0+14Fj
.text:0040860E mov ecx, off_470DB4 ;特征码2
.text:00408614 mov eax, esi
.text:00408616
.text:00408616 loc_408616: ; CODE XREF: sub_4084B0+180j
.text:00408616 mov dl, [eax] ; 比较特征码
.text:00408618 cmp dl, [ecx]
.text:0040861A jnz short loc_408636
.text:0040861C cmp dl, bl
.text:0040861E jz short loc_408632
.text:00408620 mov dl, [eax+1]
.text:00408623 cmp dl, [ecx+1]
.text:00408626 jnz short loc_408636
.text:00408628 add eax, 2
.text:0040862B add ecx, 2
.text:0040862E cmp dl, bl
.text:00408630 jnz short loc_408616
.text:00408632
.text:00408632 loc_408632: ; CODE XREF: sub_4084B0+16Ej
.text:00408632 xor eax, eax
.text:00408634 jmp short loc_40863B
.text:00408636 ; ---------------------------------------------------------------------------
.text:00408636
.text:00408636 loc_408636: ; CODE XREF: sub_4084B0+16Aj
.text:00408636 ; sub_4084B0+176j
.text:00408636 sbb eax, eax
.text:00408638 sbb eax, 0FFFFFFFFh
.text:0040863B
.text:0040863B loc_40863B: ; CODE XREF: sub_4084B0+184j
.text:0040863B cmp eax, ebx
.text:0040863D jnz short loc_408649
.text:0040863F mov dword ptr [esp+edi+40h+Args], offset aVncEnterpris_0 ; "VNC Enterprise Edition for UNIX"
.text:00408647 jmp short loc_4086C1
.text:00408649 ; ---------------------------------------------------------------------------
.text:00408649
.text:00408649 loc_408649: ; CODE XREF: sub_4084B0+18Dj
.text:00408649 mov ecx, off_470DB0 ;特征码3
.text:0040864F mov eax, esi
.text:00408651
.text:00408651 loc_408651: ; CODE XREF: sub_4084B0+1BBj
.text:00408651 mov dl, [eax] ; 比较特征码
.text:00408653 cmp dl, [ecx]
.text:00408655 jnz short loc_408671
.text:00408657 cmp dl, bl
.text:00408659 jz short loc_40866D
.text:0040865B mov dl, [eax+1]
.text:0040865E cmp dl, [ecx+1]
.text:00408661 jnz short loc_408671
.text:00408663 add eax, 2
.text:00408666 add ecx, 2
.text:00408669 cmp dl, bl
.text:0040866B jnz short loc_408651
.text:0040866D
.text:0040866D loc_40866D: ; CODE XREF: sub_4084B0+1A9j
.text:0040866D xor eax, eax
.text:0040866F jmp short loc_408676
.text:00408671 ; ---------------------------------------------------------------------------
.text:00408671
.text:00408671 loc_408671: ; CODE XREF: sub_4084B0+1A5j
.text:00408671 ; sub_4084B0+1B1j
.text:00408671 sbb eax, eax
.text:00408673 sbb eax, 0FFFFFFFFh
.text:00408676
.text:00408676 loc_408676: ; CODE XREF: sub_4084B0+1BFj
.text:00408676 cmp eax, ebx
.text:00408678 jnz short loc_408684
.text:0040867A mov dword ptr [esp+edi+40h+Args], offset aVncEnterpris_1 ; "VNC Enterprise Edition for Mac OS X"
.text:00408682 jmp short loc_4086C1
.text:00408684 ; ---------------------------------------------------------------------------
.text:00408684
.text:00408684 loc_408684: ; CODE XREF: sub_4084B0+1C8j
.text:00408684 mov ecx, off_470DAC ;特征码4
.text:0040868A mov eax, esi
.text:0040868C lea esp, [esp+0]
.text:00408690
.text:00408690 loc_408690: ; CODE XREF: sub_4084B0+1FAj
.text:00408690 mov dl, [eax] ; 比较特征码
.text:00408692 cmp dl, [ecx]
.text:00408694 jnz short loc_4086B0
.text:00408696 cmp dl, bl
.text:00408698 jz short loc_4086AC
.text:0040869A mov dl, [eax+1]
.text:0040869D cmp dl, [ecx+1]
.text:004086A0 jnz short loc_4086B0
.text:004086A2 add eax, 2
.text:004086A5 add ecx, 2
.text:004086A8 cmp dl, bl
.text:004086AA jnz short loc_408690
.text:004086AC
.text:004086AC loc_4086AC: ; CODE XREF: sub_4084B0+1E8j
.text:004086AC xor eax, eax
.text:004086AE jmp short loc_4086B5
.text:004086B0 ; ---------------------------------------------------------------------------
.text:004086B0
.text:004086B0 loc_4086B0: ; CODE XREF: sub_4084B0+1E4j
.text:004086B0 ; sub_4084B0+1F0j
.text:004086B0 sbb eax, eax
.text:004086B2 sbb eax, -1
.text:004086B5
.text:004086B5 loc_4086B5: ; CODE XREF: sub_4084B0+1FEj
.text:004086B5 cmp eax, ebx
.text:004086B7 jnz short loc_4086C1
.text:004086B9 mov dword ptr [esp+edi+40h+Args], offset aVncEnterpris_2 ; "VNC Enterprise Edition (OEM)"
.text:004086C1
.text:004086C1 loc_4086C1: ; CODE XREF: sub_4084B0+159j
.text:004086C1 ; sub_4084B0+197j ...
.text:004086C1 add edi, 4
.text:004086C4 cmp edi, 8
.text:004086C7 jl loc_4085D0
.text:004086CD mov eax, [esp+40h+var_20]
.text:004086D1 mov ecx, dword ptr [esp+40h+Args]
.text:004086D5 push eax
.text:004086D6 push ecx ; Args
.text:004086D7 lea edx, [esp+48h+Memory]
.text:004086DB push offset aTheSuppliedL_2 ; "The supplied license key is only valid "...
.text:004086E0 push edx ; int
.text:004086E1 call sub_40CC50
.text:004086E6 mov ebp, [esp+50h+var_28]
.text:004086EA add esp, 10h
.text:004086ED
.text:004086ED loc_4086ED: ; CODE XREF: sub_4084B0+F7j
.text:004086ED mov edi, [esp+40h+var_2C]
.text:004086F1
.text:004086F1 loc_4086F1: ; CODE XREF: sub_4084B0+87j
.text:004086F1 ; sub_4084B0+BBj
.text:004086F1 mov eax, [ebp+4]
.text:004086F4 push eax ; Memory
.text:004086F5 call j_j__free
.text:004086FA mov ecx, [ebp+0]
.text:004086FD push ecx ; Memory
.text:004086FE call j_j__free
.text:00408703 push ebp ; Memory
.text:00408704 call j__free
.text:00408709 add esp, 0Ch
.text:0040870C
.text:0040870C loc_40870C: ; CODE XREF: sub_4084B0+67j
.text:0040870C mov eax, [esp+40h+Memory]
.text:00408710 cmp eax, ebx
.text:00408712 jz short loc_40872A
.text:00408714 mov edx, [edi+8]
.text:00408717 push ebx ; lpCaption
.text:00408718 push 10h ; Memory
.text:0040871A push eax ; int
.text:0040871B push edx ; hWnd
.text:0040871C call sub_420B60
.text:00408721 mov eax, [esp+50h+Memory]
.text:00408725 add esp, 10h
.text:00408728 cmp eax, ebx
.text:0040872A
.text:0040872A loc_40872A: ; CODE XREF: sub_4084B0+262j
.text:0040872A push eax ; Memory
.text:0040872B setz bl
.text:0040872E call j__free
.text:00408733 add esp, 4
.text:00408736 mov al, bl
.text:00408738 mov ecx, [esp+40h+var_C]
.text:0040873C mov large fs:0, ecx
.text:00408743 pop ecx
.text:00408744 pop edi
.text:00408745 pop esi
.text:00408746 pop ebp
.text:00408747 pop ebx
.text:00408748 add esp, 2Ch
.text:0040874B retn
.text:0040874B sub_4084B0 endp
主体部分的功能在于:
1.使用5组特征码与注册码特征码进行对比,以确定是注册码是什么版本的,如果版本符合,通过,否则,提示版本错误
2.对注册码有效期(注册码计算出的结构C中C[0x18],C[0x1C])进行验证
004165C0时间校验Call
.text:004165C0 ; =============== S U B R O U T I N E =======================================
.text:004165C0
.text:004165C0 ; 校验时间
.text:004165C0
.text:004165C0 sub_4165C0 proc near ; CODE XREF: sub_4084B0+6Ep
.text:004165C0 ; sub_40B150+9p ...
.text:004165C0 cmp byte ptr [ecx+20h], 0 ; C[0x20]=0,返回0
.text:004165C4 push ebp
.text:004165C5 jz short loc_4165FF
.text:004165C7 push ebx
.text:004165C8 mov ebx, [ecx+0Ch]
.text:004165CB push esi
.text:004165CC mov esi, [ecx+18h]
.text:004165CF push edi
.text:004165D0 mov edi, [ecx+1Ch]
.text:004165D3 push 0 ; Time
.text:004165D5 call __time64 ; 取当前时间(秒)
.text:004165DA mov ebp, eax
.text:004165DC mov eax, ebx
.text:004165DE imul eax, 15180h ; C[0xC]*0x15180(天数->秒)
.text:004165E4 mov ecx, edx
.text:004165E6 add esp, 4
.text:004165E9 cdq
.text:004165EA add eax, esi ; C[0x18]+C[0x0C]*0x1518
.text:004165EC adc edx, edi ; C[0x1C]+edx
.text:004165EE cmp ecx, edx ; 与当前时间值的高位比较,大于返回1,小于返回0
.text:004165F0 pop edi
.text:004165F1 pop esi
.text:004165F2 pop ebx
.text:004165F3 jl short loc_4165FF
.text:004165F5 jg short loc_4165FB
.text:004165F7 cmp ebp, eax ; 与当前时间值的低位比较,小于返回0
.text:004165F9 jb short loc_4165FF
.text:004165FB
.text:004165FB loc_4165FB: ; CODE XREF: sub_4165C0+35j
.text:004165FB mov al, 1
.text:004165FD pop ebp
.text:004165FE retn ; 0为通过
.text:004165FF ; ---------------------------------------------------------------------------
.text:004165FF
.text:004165FF loc_4165FF: ; CODE XREF: sub_4165C0+5j
.text:004165FF ; sub_4165C0+33j ...
.text:004165FF xor al, al
.text:00416601 pop ebp
.text:00416602 retn
.text:00416602 sub_4165C0 endp
这部分功能:
1.C[0x20]为0,返回0,通过
2.C[0x18],C[0x1C],C[0x0C]与当前时间值对比,小于返回1,不通过,大于返回0,通过
00416560注册码处理Call的主要部分
.text:00416350 ; =============== S U B R O U T I N E =======================================
.text:00416350
.text:00416350 ; 注册码处理
.text:00416350
.text:00416350 sub_416350 proc near ; CODE XREF: sub_416560+3Dp
.text:00416350
.text:00416350 var_60 = dword ptr -60h
.text:00416350 var_5C = dword ptr -5Ch
.text:00416350 Memory = dword ptr -58h
.text:00416350 var_34 = dword ptr -34h
.text:00416350 var_30 = dword ptr -30h
.text:00416350 var_C = dword ptr -0Ch
.text:00416350 var_4 = dword ptr -4
.text:00416350 arg_0 = dword ptr 4
.text:00416350 arg_4 = dword ptr 8
.text:00416350 arg_8 = dword ptr 0Ch
.text:00416350
.text:00416350 push -1
.text:00416352 push offset loc_452995
.text:00416357 mov eax, large fs:0
.text:0041635D push eax
.text:0041635E sub esp, 54h
.text:00416361 push ebx
.text:00416362 push ebp
.text:00416363 push esi
.text:00416364 push edi
.text:00416365 mov eax, dword_472404
.text:0041636A xor eax, esp
.text:0041636C push eax
.text:0041636D lea eax, [esp+74h+var_C]
.text:00416371 mov large fs:0, eax
.text:00416377 mov ebp, [esp+74h+arg_0]
.text:0041637B xor edi, edi
.text:0041637D mov [esp+74h+var_60], edi
.text:00416381 cmp byte ptr [esp+74h+arg_4], 0
.text:00416386 jz short loc_4163A6
.text:00416388 mov eax, [esp+74h+arg_8]
.text:0041638F mov ecx, off_470DA4
.text:00416395 push eax ; int
.text:00416396 push ecx ; int
.text:00416397 push ebp ; Memory
.text:00416398 lea ecx, [esp+80h+var_34]
.text:0041639C call sub_417120 ; 注册码校验2
.text:004163A1 lea ebx, [edi+1]
.text:004163A4 jmp short loc_4163BC
.text:004163A6 ; ---------------------------------------------------------------------------
.text:004163A6
.text:004163A6 loc_4163A6: ; CODE XREF: sub_416350+36j
.text:004163A6 mov edx, off_470DA4 ; 2945F7FEh, 0ABAA9F34h
.text:004163AC push edx ; Memory
.text:004163AD push ebp ; int
.text:004163AE lea ecx, [esp+7Ch+var_5C]
.text:004163B2 call sub_417000 ; 注册码校验
.text:004163B7 mov ebx, 2
.text:004163BC
.text:004163BC loc_4163BC: ; CODE XREF: sub_416350+54j
.text:004163BC test bl, 2
.text:004163BF mov esi, [eax+10h]
.text:004163C2 jz short loc_4163DE
.text:004163C4 mov eax, [esp+74h+Memory]
.text:004163C8 push eax ; Memory
.text:004163C9 and ebx, 0FFFFFFFDh
.text:004163CC call j_j__free
.text:004163D1 mov ecx, [esp+78h+var_5C]
.text:004163D5 push ecx ; Memory
.text:004163D6 call j_j__free
.text:004163DB add esp, 8
.text:004163DE
.text:004163DE loc_4163DE: ; CODE XREF: sub_416350+72j
.text:004163DE test bl, 1
.text:004163E1 mov [esp+74h+var_4], -1
.text:004163E9 jz short loc_416402
.text:004163EB mov edx, [esp+74h+var_30]
.text:004163EF push edx ; Memory
.text:004163F0 call j_j__free
.text:004163F5 mov eax, [esp+78h+var_34]
.text:004163F9 push eax ; Memory
.text:004163FA call j_j__free
.text:004163FF add esp, 8
.text:00416402
.text:00416402 loc_416402: ; CODE XREF: sub_416350+99j
.text:00416402 mov eax, esi ; 验证C[0x10]
.text:00416404 sub eax, 1
.text:00416407 jz loc_4164B5 ; C[0x10]=1跳,1和3使用依次按6个特征码进行运算
.text:0041640D sub eax, 1
.text:00416410 jz short loc_416431 ; C[0x10]=2跳,2使用用特征码4进行运算
.text:00416412 sub eax, 1
.text:00416415 jz loc_4164B5 ; C[0x10]=3跳
.text:0041641B
.text:0041641B loc_41641B: ; CODE XREF: sub_416350+160j
.text:0041641B ; sub_416350+1F4j
.text:0041641B xor eax, eax
.text:0041641D mov ecx, [esp+74h+var_C]
.text:00416421 mov large fs:0, ecx
.text:00416428 pop ecx
.text:00416429 pop edi
.text:0041642A pop esi
.text:0041642B pop ebp
.text:0041642C pop ebx
.text:0041642D add esp, 60h ; 返回0,校验错
.text:00416430 retn
.text:00416431 ; ---------------------------------------------------------------------------
.text:00416431
.text:00416431 loc_416431: ; CODE XREF: sub_416350+C0j
.text:00416431 push 28h ; Size
.text:00416433 call ??2@YAPAXI@Z ; operator new(uint)
.text:00416438 add esp, 4
.text:0041643B cmp byte ptr [esp+74h+arg_4], 0
.text:00416440 mov [esp+74h+arg_4], eax
.text:00416444 jz short loc_41646B
.text:00416446 cmp eax, edi
.text:00416448 mov [esp+74h+var_4], 3
.text:00416450 jz short loc_416488
.text:00416452 mov ecx, [esp+74h+arg_8]
.text:00416459 mov edx, off_470DB4
.text:0041645F push ecx ; int
.text:00416460 push edx ; int
.text:00416461 push ebp ; Memory
.text:00416462 mov ecx, eax
.text:00416464 call sub_417120 ; 注册码校验2
.text:00416469 jmp short loc_41648A
.text:0041646B ; ---------------------------------------------------------------------------
.text:0041646B
.text:0041646B loc_41646B: ; CODE XREF: sub_416350+F4j
.text:0041646B cmp eax, edi
.text:0041646D mov [esp+74h+var_4], 4
.text:00416475 jz short loc_416488
.text:00416477 mov ecx, off_470DB4
.text:0041647D push ecx ; Memory
.text:0041647E push ebp ; int
.text:0041647F mov ecx, eax
.text:00416481 call sub_417000 ; 注册码校验
.text:00416486 jmp short loc_41648A
.text:00416488 ; ---------------------------------------------------------------------------
.text:00416488
.text:00416488 loc_416488: ; CODE XREF: sub_416350+100j
.text:00416488 ; sub_416350+125j
.text:00416488 xor eax, eax
.text:0041648A
.text:0041648A loc_41648A: ; CODE XREF: sub_416350+119j
.text:0041648A ; sub_416350+136j
.text:0041648A mov esi, eax
.text:0041648C cmp byte ptr [esi+21h], 0
.text:00416490 jnz loc_416549
.text:00416496 mov edx, [esi+4]
.text:00416499 push edx ; Memory
.text:0041649A call j_j__free
.text:0041649F mov eax, [esi]
.text:004164A1 push eax ; Memory
.text:004164A2 call j_j__free
.text:004164A7 push esi ; Memory
.text:004164A8 call j__free
.text:004164AD add esp, 0Ch
.text:004164B0 jmp loc_41641B
.text:004164B5 ; ---------------------------------------------------------------------------
.text:004164B5
.text:004164B5 loc_4164B5: ; CODE XREF: sub_416350+B7j
.text:004164B5 ; sub_416350+C5j ...
.text:004164B5 push 28h ; Size
.text:004164B7 call ??2@YAPAXI@Z ; operator new(uint)
.text:004164BC add esp, 4
.text:004164BF cmp byte ptr [esp+74h+arg_4], 0
.text:004164C4 mov [esp+74h+var_60], eax
.text:004164C8 jz short loc_4164EF
.text:004164CA test eax, eax
.text:004164CC mov [esp+74h+var_4], 1
.text:004164D4 jz short loc_41650C
.text:004164D6 mov ecx, [esp+74h+arg_8]
.text:004164DD mov edx, dword_473F88[edi]
.text:004164E3 push ecx ; int
.text:004164E4 push edx ; int
.text:004164E5 push ebp ; Memory
.text:004164E6 mov ecx, eax
.text:004164E8 call sub_417120 ; 注册码校验2
.text:004164ED jmp short loc_41650E
.text:004164EF ; ---------------------------------------------------------------------------
.text:004164EF
.text:004164EF loc_4164EF: ; CODE XREF: sub_416350+178j
.text:004164EF test eax, eax
.text:004164F1 mov [esp+74h+var_4], 2
.text:004164F9 jz short loc_41650C
.text:004164FB mov ecx, dword_473F88[edi] ; 根据edi值取
.text:004164FB ; 共6组特征码
.text:004164FB ; 2945F7FEh, ABAA9F34h
.text:004164FB ; 4CC82057h, AEAB62AAh
.text:004164FB ; ED4FF7EFh, ABAD904Bh
.text:004164FB ; E540EAC2h, 81C5753Ch
.text:004164FB ; C1ACCCF0h, D0EA12ABh
.text:004164FB ; 1E02EF1h, 17101CEDh
.text:004164FB ;
.text:00416501 push ecx ; Memory
.text:00416502 push ebp ; int
.text:00416503 mov ecx, eax
.text:00416505 call sub_417000 ; 注册码校验
.text:0041650A jmp short loc_41650E
.text:0041650C ; ---------------------------------------------------------------------------
.text:0041650C
.text:0041650C loc_41650C: ; CODE XREF: sub_416350+184j
.text:0041650C ; sub_416350+1A9j
.text:0041650C xor eax, eax
.text:0041650E
.text:0041650E loc_41650E: ; CODE XREF: sub_416350+19Dj
.text:0041650E ; sub_416350+1BAj
.text:0041650E mov esi, eax
.text:00416510 cmp byte ptr [esi+21h], 0 ; 比较C[0x21](验证返回值),为0跳
.text:00416514 mov [esp+74h+var_4], -1
.text:0041651C jnz short loc_416549
.text:0041651E mov edx, [esi+4]
.text:00416521 push edx ; Memory
.text:00416522 call j_j__free
.text:00416527 mov eax, [esi]
.text:00416529 push eax ; Memory
.text:0041652A call j_j__free
.text:0041652F push esi ; Memory
.text:00416530 call j__free ; 取下一组运算
.text:00416535 add edi, 4
.text:00416538 add esp, 0Ch
.text:0041653B cmp edi, 18h
.text:0041653E jb loc_4164B5
.text:00416544 jmp loc_41641B
.text:00416549 ; ---------------------------------------------------------------------------
.text:00416549
.text:00416549 loc_416549: ; CODE XREF: sub_416350+140j
.text:00416549 ; sub_416350+1CCj
.text:00416549 mov eax, esi
.text:0041654B mov ecx, [esp+74h+var_C]
.text:0041654F mov large fs:0, ecx
.text:00416556 pop ecx
.text:00416557 pop edi
.text:00416558 pop esi
.text:00416559 pop ebp
.text:0041655A pop ebx
.text:0041655B add esp, 60h
.text:0041655E retn
.text:0041655E sub_416350 endp
这部分的功能在于:
1.根据注册码运算的返回结构C,并根据C[0x10]处的值确定注册码计算的方法,方法1和3使用6组特征码((最后一组在主体验证中无效……),2使用第5组特征码
2.注册码与特征码结合,运算、比较后,确定验证注册码使用了哪组特征码
00417000处注册码验证主要部分
.text:00417000 ; =============== S U B R O U T I N E =======================================
.text:00417000
.text:00417000 ; 注册码校验
.text:00417000 ; Attributes: bp-based frame
.text:00417000
.text:00417000 ; int __stdcall sub_417000(int, void *Memory)
.text:00417000 sub_417000 proc near ; CODE XREF: sub_40BA80+286p
.text:00417000 ; sub_40BA80+2CBp ...
.text:00417000
.text:00417000 Args = byte ptr -18h
.text:00417000 var_14 = dword ptr -14h
.text:00417000 var_10 = dword ptr -10h
.text:00417000 var_C = dword ptr -0Ch
.text:00417000 var_4 = dword ptr -4
.text:00417000 arg_0 = dword ptr 8
.text:00417000 Memory = dword ptr 0Ch
.text:00417000
.text:00417000 push ebp
.text:00417001 mov ebp, esp
.text:00417003 push -1
.text:00417005 push offset loc_452B33
.text:0041700A mov eax, large fs:0
.text:00417010 push eax
.text:00417011 sub esp, 0Ch
.text:00417014 push ebx
.text:00417015 push esi
.text:00417016 push edi
.text:00417017 mov eax, dword_472404
.text:0041701C xor eax, ebp
.text:0041701E push eax
.text:0041701F lea eax, [ebp+var_C]
.text:00417022 mov large fs:0, eax
.text:00417028 mov [ebp+var_10], esp
.text:0041702B mov ebx, ecx
.text:0041702D mov [ebp+var_14], ebx
.text:00417030 mov eax, [ebp+Memory]
.text:00417033 push -1
.text:00417035 push eax
.text:00417036 call sub_40C730 ; strcpy()
.text:0041703B mov [ebx], eax ; 字串指针放入[ebx]
.text:0041703D xor eax, eax
.text:0041703F mov [ebp+var_4], eax
.text:00417042 mov [ebx+4], eax
.text:00417045 mov [ebx+21h], al
.text:00417048 mov [ebp+Memory], eax
.text:0041704B mov ecx, [ebp+arg_0] ; 注册码
.text:0041704E push ecx
.text:0041704F lea edi, [eax+19h] ; 0x19
.text:00417052 mov byte ptr [ebp+var_4], 3
.text:00417056 call sub_416CB0 ; 去"-"
.text:0041705B add esp, 0Ch
.text:0041705E lea ecx, [ebp+Memory]
.text:00417061 mov [ebp+Memory], eax
.text:00417064 call sub_40C990 ; 转换为大写
.text:00417069 mov esi, [ebp+Memory]
.text:0041706C mov eax, esi
.text:0041706E lea edx, [eax+1]
.text:00417071
.text:00417071 loc_417071: ; CODE XREF: sub_417000+78j
.text:00417071 mov cl, [eax]
.text:00417073 add eax, 1
.text:00417076 test cl, cl
.text:00417078 jnz short loc_417071
.text:0041707A sub eax, edx ; 计算长度
.text:0041707C cmp eax, 19h ; 长度=25跳
.text:0041707F jz short loc_4170A1
.text:00417081 push offset aBadKeyLength ; "Bad key length"
.text:00417086 push offset dword_473FA0 ; int
.text:0041708B call sub_40C650
.text:00417090 mov edx, [ebp+Memory]
.text:00417093 add esp, 8
.text:00417096 push edx ; Memory
.text:00417097 call j_j__free
.text:0041709C add esp, 4
.text:0041709F jmp short loc_417108
.text:004170A1 ; ---------------------------------------------------------------------------
.text:004170A1
.text:004170A1 loc_4170A1: ; CODE XREF: sub_417000+7Fj
.text:004170A1 push -1
.text:004170A3 push esi
.text:004170A4 call sub_40C730 ; strcpy()
.text:004170A9 mov esi, eax
.text:004170AB add esp, 8
.text:004170AE mov [ebp+arg_0], esi
.text:004170B1 mov eax, [ebp+Memory]
.text:004170B4 push esi
.text:004170B5 push eax
.text:004170B6 mov byte ptr [ebp+var_4], 4
.text:004170BA call sub_416FB0 ; 注册码处理,字符按位置进行替换,形成一个新的25长字符串
.text:004170BF add esp, 8
.text:004170C2 push esi ; 计算后的字符串指针
.text:004170C3 mov ecx, ebx
.text:004170C5 call sub_416E50 ; 按位计算后组成注册信息
.text:004170CA push esi
.text:004170CB mov ecx, ebx
.text:004170CD call sub_416D60 ; 前13字符+特征码计算sha1值,经过处理后与后12字符相等
.text:004170D2 push esi ; Memory
.text:004170D3 mov [ebx+21h], al ; 返回值放入C[0x21],1为成功,0为失败
.text:004170D6 call j_j__free
.text:004170DB mov ecx, [ebp+Memory]
.text:004170DE push ecx ; Memory
.text:004170DF call j_j__free
.text:004170E4 add esp, 8
.text:004170E7 jmp short loc_417108
.text:004170E9 ; ---------------------------------------------------------------------------
.text:004170E9 mov edx, dword ptr [ebp+Args]
.text:004170EC push edx ; Args
.text:004170ED push offset aS ; "%s"
.text:004170F2 push offset dword_473FA0 ; int
.text:004170F7 call sub_4089A0
.text:004170FC add esp, 0Ch
.text:004170FF mov eax, offset loc_417105
.text:00417104 retn
.text:00417105 ; ---------------------------------------------------------------------------
.text:00417105
.text:00417105 loc_417105: ; DATA XREF: sub_417000+FFo
.text:00417105 mov ebx, [ebp+var_14]
.text:00417108
.text:00417108 loc_417108: ; CODE XREF: sub_417000+9Fj
.text:00417108 ; sub_417000+E7j
.text:00417108 mov eax, ebx
.text:0041710A mov ecx, [ebp+var_C]
.text:0041710D mov large fs:0, ecx
.text:00417114 pop ecx
.text:00417115 pop edi
.text:00417116 pop esi
.text:00417117 pop ebx
.text:00417118 mov esp, ebp
.text:0041711A pop ebp
.text:0041711B retn 8
.text:0041711B sub_417000 endp
这部分的功能在于:
1.验证注册码长度是否等于25,不等于,报错
2.验证注册码是否仅包含“2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ”(字串A)中的字符,超出范围,报错
2.注册码与“2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ”(字串A)进行运算、换位,得出一个新的25字节字符串(B)
2.利用新的25字节字符串(B)与字串A计算出结构C
3.利用新的25字符的串与特征码连接,做sha1运算,返回值写了C结构
00416FB0处call
.text:00416FB0 ; =============== S U B R O U T I N E =======================================
.text:00416FB0
.text:00416FB0
.text:00416FB0 sub_416FB0 proc near ; CODE XREF: sub_417000+BAp
.text:00416FB0 ; sub_417120+A7p
.text:00416FB0
.text:00416FB0 arg_0 = dword ptr 4
.text:00416FB0 arg_4 = dword ptr 8
.text:00416FB0
.text:00416FB0 push ebx
.text:00416FB1 mov ebx, [esp+4+arg_0]
.text:00416FB5 push esi
.text:00416FB6 push edi
.text:00416FB7 mov edi, [esp+0Ch+arg_4]
.text:00416FBB xor esi, esi ; n=0
.text:00416FBD lea ecx, [ecx+0]
.text:00416FC0
.text:00416FC0 loc_416FC0: ; CODE XREF: sub_416FB0+32j
.text:00416FC0 movzx edx, byte ptr [ebx+esi*2+1] ; 注册码2n+1位
.text:00416FC5 lea eax, [esi+edi+0Eh] ; 指向注册码第n+14位
.text:00416FC9 push eax
.text:00416FCA movzx eax, byte ptr [ebx+esi*2] ; 注册码2n位
.text:00416FCE lea ecx, [esi+edi] ; 批向注册码第n位
.text:00416FD1 push ecx
.text:00416FD2 push edx
.text:00416FD3 push eax
.text:00416FD4 call sub_4168B0 ; 处理
.text:00416FD9 add esi, 1
.text:00416FDC add esp, 10h
.text:00416FDF cmp esi, 0Bh ; n<11
.text:00416FE2 jl short loc_416FC0 ; 注册码2n+1位
.text:00416FE4 mov cx, [ebx+16h] ; 取注册码第22-23位
.text:00416FE8 mov [edi+0Bh], cx ; 替换计算后的第11-12位
.text:00416FEC mov dl, [ebx+18h] ; 取注册码第24位
.text:00416FEF mov [edi+0Dh], dl ; 替换计算后的第13位
.text:00416FF2 pop edi
.text:00416FF3 pop esi
.text:00416FF4 pop ebx
.text:00416FF5 retn
.text:00416FF5 sub_416FB0 endp
004168B0处的call
.text:004168B0 ; =============== S U B R O U T I N E =======================================
.text:004168B0
.text:004168B0 ; 转换字符串
.text:004168B0 ; (arg_0&0x55|arg_4&0xAA)->arg_8
.text:004168B0 ; (arg_0&0xAA|arg_4&0x55)->arg_c
.text:004168B0
.text:004168B0 sub_4168B0 proc near ; CODE XREF: sub_416040+20p
.text:004168B0 ; sub_416FB0+24p
.text:004168B0
.text:004168B0 arg_0 = dword ptr 4
.text:004168B0 arg_4 = dword ptr 8
.text:004168B0 arg_8 = dword ptr 0Ch
.text:004168B0 arg_C = dword ptr 10h
.text:004168B0
.text:004168B0 mov eax, [esp+arg_0]
.text:004168B4 push esi
.text:004168B5 push edi
.text:004168B6 push eax
.text:004168B7 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:004168BC mov ecx, [esp+0Ch+arg_4] ; 2n+1位
.text:004168C0 push ecx
.text:004168C1 mov esi, eax
.text:004168C3 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:004168C8 mov edx, eax
.text:004168CA mov ecx, esi
.text:004168CC and edx, 0AAh ; 2n+1位索引取偶数位
.text:004168D2 and ecx, 55h ; 2n位索引取奇数位
.text:004168D5 or edx, ecx ; 合成
.text:004168D7 add esp, 8
.text:004168DA and edx, 8000001Fh ; 取低5位,并校验高位
.text:004168E0 jns short loc_4168E7 ; 高位未置跳转
.text:004168E2 dec edx
.text:004168E3 or edx, 0FFFFFFE0h
.text:004168E6 inc edx
.text:004168E7
.text:004168E7 loc_4168E7: ; CODE XREF: sub_4168B0+30j
.text:004168E7 mov ecx, off_470DC0
.text:004168ED mov dl, [edx+ecx] ; 取合成数在字符串A中相应字符
.text:004168F0 mov edi, [esp+8+arg_8] ; 替换n处字符
.text:004168F4 and esi, 0AAh ; 2n位索引取偶数位
.text:004168FA and eax, 55h ; 2n+1位索引取奇数位
.text:004168FD or esi, eax
.text:004168FF and esi, 8000001Fh ; 合成后取低5位,并检测高位
.text:00416905 mov [edi], dl
.text:00416907 jns short loc_41690E
.text:00416909 dec esi
.text:0041690A or esi, 0FFFFFFE0h
.text:0041690D inc esi
.text:0041690E
.text:0041690E loc_41690E: ; CODE XREF: sub_4168B0+57j
.text:0041690E mov al, [esi+ecx]
.text:00416911 mov ecx, [esp+8+arg_C] ; 取合成数在字符串中相应字符替换n+14处字符
.text:00416915 pop edi
.text:00416916 mov [ecx], al
.text:00416918 pop esi
.text:00416919 retn
.text:00416919 sub_4168B0 endp
以上两部分是注册码与“2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ”(字符串A)运算出新的25字节长字符串B的过程
00416E50处的Call
.text:00416E50 ; =============== S U B R O U T I N E =======================================
.text:00416E50
.text:00416E50 ; 按位计算后组成注册信息
.text:00416E50
.text:00416E50 sub_416E50 proc near ; CODE XREF: sub_417000+C5p
.text:00416E50 ; sub_417120+E1p
.text:00416E50
.text:00416E50 arg_0 = dword ptr 4
.text:00416E50
.text:00416E50 push ebx
.text:00416E51 push ebp
.text:00416E52 push esi
.text:00416E53 mov esi, [esp+0Ch+arg_0] ; 第一次运算后的字符串
.text:00416E57 movzx eax, byte ptr [esi+3] ; 取第3个字符
.text:00416E5B push edi
.text:00416E5C push eax
.text:00416E5D mov edi, ecx ; 栈指针C
.text:00416E5F call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416E64 movzx ecx, byte ptr [esi+2] ; 取第2个字符
.text:00416E68 mov ebp, eax
.text:00416E6A push ecx
.text:00416E6B shl ebp, 5 ; 第3字符索引<<5
.text:00416E6E call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416E73 movzx edx, byte ptr [esi+1] ; 取第1个字符
.text:00416E77 mov ebx, eax
.text:00416E79 or ebx, ebp
.text:00416E7B push edx
.text:00416E7C shl ebx, 5
.text:00416E7F call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416E84 mov ebp, eax
.text:00416E86 movzx eax, byte ptr [esi] ; 取第0个字符
.text:00416E89 or ebp, ebx
.text:00416E8B push eax
.text:00416E8C shl ebp, 5
.text:00416E8F call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416E94 or eax, ebp ; 产生dw,从低到高每5位为第0,1,2,3字符在字符串中的索引
.text:00416E96 mov [edi+8], eax ; 放入C[0x8]
.text:00416E99 movzx ecx, byte ptr [esi+6] ; 取第6个字符
.text:00416E9D push ecx
.text:00416E9E call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416EA3 movzx edx, byte ptr [esi+5] ; 取第5个字符
.text:00416EA7 mov ebp, eax
.text:00416EA9 push edx
.text:00416EAA shl ebp, 5
.text:00416EAD call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416EB2 mov ebx, eax
.text:00416EB4 movzx eax, byte ptr [esi+4] ; 取第4个字符
.text:00416EB8 or ebx, ebp
.text:00416EBA push eax
.text:00416EBB shl ebx, 5
.text:00416EBE call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416EC3 or eax, ebx ; 产生dw,从低到高每5位为第4,5,6字符在字符串中的索引
.text:00416EC5 cdq ; eax高位值扩展入edx
.text:00416EC6 mov [edi+18h], eax ; 放入C[0x18]
.text:00416EC9 and eax, 4000h
.text:00416ECE xor ecx, ecx
.text:00416ED0 add esp, 1Ch
.text:00416ED3 or eax, ecx ; 判断eax第14位是否为0
.text:00416ED5 mov [edi+1Ch], edx ; 放入C[0x1C]
.text:00416ED8 jz short loc_416EDF
.text:00416EDA lea eax, [ecx+1] ; eax=1
.text:00416EDD jmp short loc_416EE1 ; al->C[0x20]
.text:00416EDF ; ---------------------------------------------------------------------------
.text:00416EDF
.text:00416EDF loc_416EDF: ; CODE XREF: sub_416E50+88j
.text:00416EDF xor eax, eax
.text:00416EE1
.text:00416EE1 loc_416EE1: ; CODE XREF: sub_416E50+8Dj
.text:00416EE1 mov [edi+20h], al ; al->C[0x20]
.text:00416EE4 call sub_416610 ; 取时间值,设置和判断470DC8和470DCC的值
.text:00416EE9 mov ecx, [edi+18h] ; 取C[0x18]
.text:00416EEC push 0
.text:00416EEE mov ebp, edx
.text:00416EF0 mov edx, [edi+1Ch] ; 取C[0x1C]
.text:00416EF3 push 15180h
.text:00416EF8 and ecx, 0FFFFBFFFh ; 取第14位以外各位
.text:00416EFE push edx ; C[0x1C]
.text:00416EFF push ecx ; C[0x18]
.text:00416F00 mov ebx, eax
.text:00416F02 call __allmul ; 0x15180*C[0x18]&0xffffbfff 0x15180为每天秒数
.text:00416F07 add ebx, eax ; [470DC8]+eax->C[0x18]
.text:00416F09 adc ebp, edx ; [470DCC]+edx->C[0x1C]
.text:00416F0B mov [edi+18h], ebx
.text:00416F0E mov [edi+1Ch], ebp
.text:00416F11 movzx eax, byte ptr [esi+7] ; 取第7字符
.text:00416F15 push eax
.text:00416F16 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F1B movzx ecx, byte ptr [esi+8] ; 取第8字符
.text:00416F1F mov ebp, eax
.text:00416F21 push ecx
.text:00416F22 shl ebp, 5
.text:00416F25 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F2A movzx edx, byte ptr [esi+9] ; 取第9字符
.text:00416F2E mov ebx, eax
.text:00416F30 or ebx, ebp
.text:00416F32 push edx
.text:00416F33 shl ebx, 5
.text:00416F36 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F3B mov ebp, eax
.text:00416F3D movzx eax, byte ptr [esi+0Ah] ; 取第10字符
.text:00416F41 or ebp, ebx
.text:00416F43 push eax
.text:00416F44 shl ebp, 5
.text:00416F47 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F4C movzx ecx, byte ptr [esi+0Bh] ; 取第11字符
.text:00416F50 mov ebx, eax
.text:00416F52 or ebx, ebp
.text:00416F54 push ecx
.text:00416F55 shl ebx, 5
.text:00416F58 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F5D movzx edx, byte ptr [esi+0Ch] ; 取第12字符
.text:00416F61 mov ebp, eax
.text:00416F63 or ebp, ebx
.text:00416F65 push edx
.text:00416F66 shl ebp, 5
.text:00416F69 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F6E or eax, ebp ; 产生dw,从低到高每5位为第7,8,9,10,11,12字符在字符串中的索引
.text:00416F70 mov [edi+0Ch], eax ; 放入C[0x0C]
.text:00416F73 movzx eax, byte ptr [esi+0Dh] ; 取第13字符
.text:00416F77 push eax
.text:00416F78 call sub_416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416F7D push -1
.text:00416F7F add esi, 19h ; esi+25
.text:00416F82 push esi
.text:00416F83 mov [edi+10h], eax ; 第13字符在字符串中索引放入C[0x10]
.text:00416F86 call sub_40C730 ; strcpy()
.text:00416F8B mov ecx, [edi+4]
.text:00416F8E push ecx ; Memory
.text:00416F8F mov esi, eax
.text:00416F91 call j_j__free
.text:00416F96 add esp, 28h
.text:00416F99 mov [edi+4], esi ; 字符串指针放入C[0x4]
.text:00416F9C pop edi
.text:00416F9D pop esi
.text:00416F9E pop ebp
.text:00416F9F pop ebx
.text:00416FA0 retn 4
.text:00416FA0 sub_416E50 endp
这部分是由25字节长字符串B运算产生结构C的过程
.text:00416840 ; =============== S U B R O U T I N E =======================================
.text:00416840
.text:00416840 ; 取在字符串中"2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ"位置
.text:00416840 ; Attributes: bp-based frame
.text:00416840
.text:00416840 sub_416840 proc near ; CODE XREF: sub_416220+67p
.text:00416840 ; sub_4168B0+7p ...
.text:00416840
.text:00416840 var_200 = byte ptr -200h
.text:00416840 var_100 = dword ptr -100h
.text:00416840 arg_0 = byte ptr 8
.text:00416840
.text:00416840 push ebp
.text:00416841 mov ebp, esp
.text:00416843 and esp, 0FFFFFFF8h
.text:00416846 movsx eax, [ebp+arg_0]
.text:0041684A sub esp, 200h
.text:00416850 push esi
.text:00416851 push edi
.text:00416852 push eax ; C
.text:00416853 call _toupper
.text:00416858 mov edx, off_470DC0
.text:0041685E add esp, 4
.text:00416861 mov cl, al
.text:00416863 xor eax, eax
.text:00416865
.text:00416865 loc_416865: ; CODE XREF: sub_416840+30j
.text:00416865 cmp [edx+eax], cl
.text:00416868 jz short loc_4168A7
.text:0041686A add eax, 1
.text:0041686D cmp eax, 20h
.text:00416870 jl short loc_416865
.text:00416872 movsx ecx, cl
.text:00416875 push ecx ; Args
.text:00416876 lea edx, [esp+20Ch+var_100]
.text:0041687D push offset aBadKeyCharC ; "bad key char: %c"
.text:00416882 push edx ; int
.text:00416883 call sub_40F3E0
.text:00416888 add esp, 0Ch
.text:0041688B mov esi, eax
.text:0041688D push offset dword_46A684
.text:00416892 lea eax, [esp+20Ch+var_200]
.text:00416896 mov ecx, 40h
.text:0041689B lea edi, [esp+20Ch+var_200]
.text:0041689F push eax
.text:004168A0 rep movsd
.text:004168A2 call __CxxThrowException@8 ; _CxxThrowException(x,x)
.text:004168A7
.text:004168A7 loc_4168A7: ; CODE XREF: sub_416840+28j
.text:004168A7 pop edi
.text:004168A8 pop esi
.text:004168A9 mov esp, ebp
.text:004168AB pop ebp
.text:004168AC retn
.text:004168AC sub_416840 endp
这部分的功能是查找字符C1在字符串A中索引,如找不到,报错
00416D60处的CAll
.text:00416D60 ; 前13字符+特征码计算sha1值,经过处理后与后12字符相等
.text:00416D60
.text:00416D60 sub_416D60 proc near ; CODE XREF: sub_417000+CDp
.text:00416D60 ; sub_417120+109p
.text:00416D60
.text:00416D60 var_C = dword ptr -0Ch
.text:00416D60 var_4 = dword ptr -4
.text:00416D60 arg_0 = dword ptr 4
.text:00416D60
.text:00416D60 push -1
.text:00416D62 push offset sub_452AE8
.text:00416D67 mov eax, large fs:0
.text:00416D6D push eax
.text:00416D6E push ebx
.text:00416D6F push esi
.text:00416D70 push edi
.text:00416D71 mov eax, dword_472404
.text:00416D76 xor eax, esp
.text:00416D78 push eax
.text:00416D79 lea eax, [esp+1Ch+var_C]
.text:00416D7D mov large fs:0, eax
.text:00416D83 mov ebx, ecx
.text:00416D85 mov esi, [esp+1Ch+arg_0] ; 第一次运算后字串
.text:00416D89 push -1
.text:00416D8B push esi
.text:00416D8C call sub_40C730 ; strcpy()
.text:00416D91 mov edi, eax ; 目的字串,初始内容与第一次运算后字串相同
.text:00416D93 mov [esp+24h+arg_0], edi ; 返回值地址改为目的字串
.text:00416D97 mov eax, [ebx+4] ; C[0x4]
.text:00416D9A mov ecx, [ebx] ; C
.text:00416D9C push eax
.text:00416D9D push ecx
.text:00416D9E push edi
.text:00416D9F mov [esp+30h+var_4], 0
.text:00416DA7 call sub_416720 ; 字符串处理(small-endian->big-endian,sha1运算,sha1摘要处理后写回字符串)
.text:00416DAC add esp, 14h
.text:00416DAF mov ecx, esi
.text:00416DB1 mov eax, edi
.text:00416DB3
.text:00416DB3 loc_416DB3: ; CODE XREF: sub_416D60+6Dj
.text:00416DB3 mov dl, [eax]
.text:00416DB5 cmp dl, [ecx]
.text:00416DB7 jnz short loc_416DD3
.text:00416DB9 test dl, dl
.text:00416DBB jz short loc_416DCF
.text:00416DBD mov dl, [eax+1]
.text:00416DC0 cmp dl, [ecx+1]
.text:00416DC3 jnz short loc_416DD3
.text:00416DC5 add eax, 2
.text:00416DC8 add ecx, 2
.text:00416DCB test dl, dl
.text:00416DCD jnz short loc_416DB3 ; 比较第一次运算和sha1运算后的字符串
.text:00416DCF
.text:00416DCF loc_416DCF: ; CODE XREF: sub_416D60+5Bj
.text:00416DCF xor eax, eax
.text:00416DD1 jmp short loc_416DD8
.text:00416DD3 ; ---------------------------------------------------------------------------
.text:00416DD3
.text:00416DD3 loc_416DD3: ; CODE XREF: sub_416D60+57j
.text:00416DD3 ; sub_416D60+63j
.text:00416DD3 sbb eax, eax
.text:00416DD5 sbb eax, -1
.text:00416DD8
.text:00416DD8 loc_416DD8: ; CODE XREF: sub_416D60+71j
.text:00416DD8 test eax, eax
.text:00416DDA jz short loc_416DE3
.text:00416DDC push offset aDigestMismatch ; "Digest mismatch"
.text:00416DE1 jmp short loc_416E1A
.text:00416DE3 ; ---------------------------------------------------------------------------
.text:00416DE3
.text:00416DE3 loc_416DE3: ; CODE XREF: sub_416D60+7Aj
.text:00416DE3 mov eax, [ebx+10h]
.text:00416DE6 cmp eax, 1 ; 比较C[0x10]处,不为1,2,3返回0,为返回1,eax为返回码
.text:00416DE9 jnz short loc_416E0B
.text:00416DEB
.text:00416DEB loc_416DEB: ; CODE XREF: sub_416D60+AEj
.text:00416DEB ; sub_416D60+B3j
.text:00416DEB push edi ; Memory
.text:00416DEC call j_j__free
.text:00416DF1 add esp, 4
.text:00416DF4 mov al, 1
.text:00416DF6 mov ecx, [esp+1Ch+var_C]
.text:00416DFA mov large fs:0, ecx
.text:00416E01 pop ecx
.text:00416E02 pop edi
.text:00416E03 pop esi
.text:00416E04 pop ebx
.text:00416E05 add esp, 0Ch
.text:00416E08 retn 4
.text:00416E0B ; ---------------------------------------------------------------------------
.text:00416E0B
.text:00416E0B loc_416E0B: ; CODE XREF: sub_416D60+89j
.text:00416E0B cmp eax, 2
.text:00416E0E jz short loc_416DEB
.text:00416E10 cmp eax, 3
.text:00416E13 jz short loc_416DEB
.text:00416E15 push offset aInvalidLicen_0 ; "Invalid license version"
.text:00416E1A
.text:00416E1A loc_416E1A: ; CODE XREF: sub_416D60+81j
.text:00416E1A push offset dword_473FA0 ; int
.text:00416E1F call sub_40C650
.text:00416E24 add esp, 8
.text:00416E27 push edi ; Memory
.text:00416E28 call j_j__free
.text:00416E2D add esp, 4
.text:00416E30 xor al, al
.text:00416E32 mov ecx, [esp+1Ch+var_C]
.text:00416E36 mov large fs:0, ecx
.text:00416E3D pop ecx
.text:00416E3E pop edi
.text:00416E3F pop esi
.text:00416E40 pop ebx
.text:00416E41 add esp, 0Ch
.text:00416E44 retn 4
.text:00416E44 sub_416D60 endp
00416720处的Call
.text:00416720 ; =============== S U B R O U T I N E =======================================
.text:00416720
.text:00416720 ; 由字符串A1,A2,A3指向拼接后,进行SHA1运算,运算后前0xB位转成定符写回字串A尾部
.text:00416720
.text:00416720 sub_416720 proc near ; CODE XREF: sub_416220+58p
.text:00416720 ; sub_416D60+47p
.text:00416720
.text:00416720 var_2C = byte ptr -2Ch
.text:00416720 var_28 = dword ptr -28h
.text:00416720 var_24 = byte ptr -24h
.text:00416720 var_10 = dword ptr -10h
.text:00416720 var_C = dword ptr -0Ch
.text:00416720 var_4 = dword ptr -4
.text:00416720 arg_0 = dword ptr 4
.text:00416720 arg_4 = dword ptr 8
.text:00416720 arg_8 = dword ptr 0Ch
.text:00416720
.text:00416720 push -1
.text:00416722 push offset sub_4529E8
.text:00416727 mov eax, large fs:0
.text:0041672D push eax
.text:0041672E sub esp, 20h
.text:00416731 mov eax, dword_472404
.text:00416736 xor eax, esp
.text:00416738 mov [esp+2Ch+var_10], eax
.text:0041673C push ebx
.text:0041673D push ebp
.text:0041673E push esi
.text:0041673F push edi
.text:00416740 mov eax, dword_472404
.text:00416745 xor eax, esp
.text:00416747 push eax
.text:00416748 lea eax, [esp+40h+var_C]
.text:0041674C mov large fs:0, eax
.text:00416752 mov eax, [esp+40h+arg_4] ; A3
.text:00416756 mov ebp, [esp+40h+arg_0] ; A1
.text:0041675A mov edi, [esp+40h+arg_8] ; A2
.text:0041675E mov [esp+40h+var_28], eax
.text:00416762 lea edx, [eax+1]
.text:00416765
.text:00416765 loc_416765: ; CODE XREF: sub_416720+4Cj
.text:00416765 mov cl, [eax]
.text:00416767 add eax, 1
.text:0041676A test cl, cl
.text:0041676C jnz short loc_416765
.text:0041676E sub eax, edx ; 计算A3长度
.text:00416770 test edi, edi
.text:00416772 mov ebx, eax
.text:00416774 jz short loc_41678F ; 判断edi,为0跳
.text:00416776 mov eax, edi
.text:00416778 lea edx, [eax+1]
.text:0041677B jmp short loc_416780
.text:0041677B ; ---------------------------------------------------------------------------
.text:0041677D align 10h
.text:00416780
.text:00416780 loc_416780: ; CODE XREF: sub_416720+5Bj
.text:00416780 ; sub_416720+67j
.text:00416780 mov cl, [eax]
.text:00416782 add eax, 1
.text:00416785 test cl, cl
.text:00416787 jnz short loc_416780
.text:00416789 sub eax, edx ; 计算A2长度
.text:0041678B mov esi, eax
.text:0041678D jmp short loc_416791
.text:0041678F ; ---------------------------------------------------------------------------
.text:0041678F
.text:0041678F loc_41678F: ; CODE XREF: sub_416720+54j
.text:0041678F xor esi, esi
.text:00416791
.text:00416791 loc_416791: ; CODE XREF: sub_416720+6Dj
.text:00416791 lea ecx, [esp+40h+var_2C]
.text:00416795 call sub_42BF30 ; new sha1结构(size,h0,h1,h2,h3,h4)
.text:0041679A mov eax, 0Eh ; 取前0xE(14)位
.text:0041679F push ebp ; A
.text:004167A0 push eax
.text:004167A1 lea ecx, [esp+48h+var_2C]
.text:004167A5 mov [esp+48h+var_4], 0
.text:004167AD call sub_42BF50 ; memcpy
.text:004167B2 push edi ; A2
.text:004167B3 push esi ; A2长度
.text:004167B4 lea ecx, [esp+48h+var_2C]
.text:004167B8 call sub_42BF50 ; memcpy
.text:004167BD mov eax, [esp+40h+var_28]
.text:004167C1 push eax ; A3
.text:004167C2 push ebx ; A3长度
.text:004167C3 lea ecx, [esp+48h+var_2C]
.text:004167C7 call sub_42BF50 ; memcpy
.text:004167CC lea ecx, [esp+40h+var_24] ; 缓冲区
.text:004167D0 push ecx
.text:004167D1 lea ecx, [esp+44h+var_2C] ; 总长度
.text:004167D5 call sub_42BF10 ; A+A2+A3进行sha1处理
.text:004167DA mov ecx, off_470DC0 ; A
.text:004167E0 xor eax, eax ; eax初始化
.text:004167E2
.text:004167E2 loc_4167E2: ; CODE XREF: sub_416720+E1j
.text:004167E2 movzx edx, [esp+eax+40h+var_24] ; 从缓冲区中取sha1摘要
.text:004167E7 and edx, 8000001Fh ; 取低5位和最高位
.text:004167ED jns short loc_4167F4 ; 高位不为0,直接运算
.text:004167EF dec edx
.text:004167F0 or edx, 0FFFFFFE0h
.text:004167F3 inc edx
.text:004167F4
.text:004167F4 loc_4167F4: ; CODE XREF: sub_416720+CDj
.text:004167F4 mov dl, [edx+ecx] ; 取在字符串A中索引
.text:004167F7 mov [eax+ebp+0Eh], dl ; 写入第一次计算后的字符串,从0xE位起
.text:004167FB add eax, 1 ; eax++
.text:004167FE cmp eax, 0Bh ; eax<0xB
.text:00416801 jl short loc_4167E2
.text:00416803 lea ecx, [esp+40h+var_2C]
.text:00416807 mov [esp+40h+var_4], -1
.text:0041680F call sub_42BF00 ; 释放内存
.text:00416814 mov ecx, [esp+40h+var_C]
.text:00416818 mov large fs:0, ecx
.text:0041681F pop ecx
.text:00416820 pop edi
.text:00416821 pop esi
.text:00416822 pop ebp
.text:00416823 pop ebx
.text:00416824 mov ecx, [esp+2Ch+var_10]
.text:00416828 xor ecx, esp
.text:0041682A call sub_43B3A6 ; 还原seh
.text:0041682F add esp, 2Ch
.text:00416832 retn
.text:00416832 sub_416720 endp
以上两部分是利用新的25字节长字符串B的前13位与特征码连接,做sha1运算,并把摘要的前10个字节,&1F后,做为索引,在“2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ”字符串A中,取出相应字符替换B中16-25位,再与B的原始值进行比较,不等返回0,相等,再检查C[0x10]是否为1、2、3,符合返回1,不符合返回0。
--------------------------------------------------------------------------------
【算法总结】
其实算法不难
1.注册码是由25字符组成
2.注册码必须为“2ABC3DEF4GHJ5KLM6NPQ7RST8UVW9XYZ”(A)中字符,大小写不限
3.注册码2n字节与2n+1字节(0<=n<0xB)在A中的索引(I1,I2),并由两个索引的奇数位和偶数位组合成新的索引i1和i2,i1=(I1 & 0xAA)|(I2 & 0x55),i2=(I1 & 0x55)|(I2 & 0xAA),并根据i1,i2,在A中取出相应字符,填充入新字符B中的n和n+0xE位,顺序完成B的0-21位。最后注册码22-24位(0开始),填入B的11-13位(0开始),形成B
4.产生结构C,C[0]为特征码指针,C[4]为注册码25字节后字符串指针,C[8]为B前4字节(0-3)在A中索引的组合(从低到高每5位),C[0xC]为B7-12字节在A中的索引的组合,C[0x10]为B13字节在A中索引。B4-6字节在A中的索引的组合D取14位放入C[0x20],其他位(0-13)乘0x15180(第天秒数)后,低位加上[470DC8]放入C[0x18],高位加上[470DCC]放入C[0x20]。[470DC8]为某一时间点的高位,[470DCC]为某一时间点的低位。
5.B前13字节,C[4]指向字符串,C[0]指向字符串组合成字符串E,对E进行sha1运算,并把摘要的前12字节顺序写回B的后12字节,形成B1,B与B1进行对比,相同则验证C[0x10]为1,2,3之一,通过置C[0x21]为1,并反回C结构,否则返回0
6.5验证通过则根据C[0x20]值是否为1,使用C[0x18],C[0x1C]以及C[0x1C]与当时时间进行较验,不通过,报过期;通过后则以C[0x18]和C[0x1C]与特定值([45AEF0][45AEF4])进行校验,不通过,报错误版本,通过则返回结构C。5验证不通过则使用下一组特征码重复1-5过程,特征码共6组,代表不同的版本。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2009年06月08日 16:43:57
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!