ExeIcon 3.6

算法一般,利用程序本身可以得到计算值,但是注册码比较的思路值得借鉴,又是拐弯抹角的又是虚晃一枪的,而且是一次又一次出现,不仅考验耐心,也考验“毅力”,差点儿崩溃。
最近脱壳很郁闷,以此文鼓励自己,纪念在看雪论坛上的百篇之作。

1.断点:
ASPack 2.001 -> Alexey Solodovnikov
Borland C++ 1999

不输入用户名提示:
00416F24     BA A8335300     mov edx,dump.005333A8       ; ASCII "Please input your Full Name!"

用户名长度要大于3:
00416EF2     E8 7D04FFFF     call dump.00407374
00416EF7     83F8 03         cmp eax,3                          ; yhm lenth

注册码长度要为24位或者40位:
0041739B     E8 D4FFFEFF     call dump.00407374
004173A0     83F8 18         cmp eax,18
004173A3     0F85 84000000   jnz dump.0041742D
0041742D     8D45 08         lea eax,dword ptr ss:[ebp+8]

00417430     E8 3FFFFEFF     call dump.00407374
00417435     83F8 28         cmp eax,28
00417438     0F85 E1010000   jnz dump.0041761F

这样就先挑0041739B作为入手断点。

2.注册码长度为24位的算法过程:
004173D7     8B45 D4         mov eax,dword ptr ss:[ebp-2C]
004173DA     40              inc eax                                  ; 初始值1,递增
004173DB     B9 05000000     mov ecx,5
004173E0     99              cdq
004173E1     F7F9            idiv ecx
004173E3     85D2            test edx,edx                             ; 余数
004173E5     74 3D           je short dump.00417424
004173E7     8B45 D4         mov eax,dword ptr ss:[ebp-2C]
004173EA     8A90 D0CF5400   mov dl,byte ptr ds:[eax+54CFD0]          ; 0
004173F0     8B4D D4         mov ecx,dword ptr ss:[ebp-2C]
004173F3     32540D 94       xor dl,byte ptr ss:[ebp+ecx-6C]          ; 与内置的字符串XOR
004173F7     0FBEC2          movsx eax,dl
004173FA     50              push eax
004173FB     E8 6020FFFF     call dump.00409460
00417400     59              pop ecx                                  ; 字符
00417401     69C0 F00A0000   imul eax,eax,0AF0                        ; ×0AF0
00417407     B9 1A000000     mov ecx,1A
0041740C     99              cdq
0041740D     F7F9            idiv ecx                                 ; /1A
0041740F     83C2 41         add edx,41                               ; +41
00417412     8B45 D4         mov eax,dword ptr ss:[ebp-2C]
00417415     0FBE4C05 AC     movsx ecx,byte ptr ss:[ebp+eax-54]       ; zcm第1位
0041741A     3BD1            cmp edx,ecx                              ; 
0041741C     74 06           je short dump.00417424
0041741E     C645 DB 00      mov byte ptr ss:[ebp-25],0
00417422     EB 09           jmp short dump.0041742D
00417424     FF45 D4         inc dword ptr ss:[ebp-2C]
00417427     837D D4 14      cmp dword ptr ss:[ebp-2C],14
0041742B   ^ 7C AA           jl short dump.004173D7

内置字符串:
0012F828  31 7A 31 68 2B 32 61 30 6E 2D 30 67 38 79 2A 39 61 31 6E 7C    1z1h+2a0n-0g8y*9a1n|

顺取内置字符串(如果位数是5的倍数,则略过,再取下一位),×AF0/1A,余数+41,得到的值为注册码的1位,然后与顺取的注册码比较,相等就继续,不等就退出。

依次得到注册码:YMYA-QEGE-GIUU-MEYE
添加到24位:YMYA-QEGE-GIUU-MEYE-9999
但是程序不再对后面的几位计算比较,提示注册码还是错误的。

3.柳暗花明又一村:
于是反复跟踪发现有一个赋值,如果注册码为24位的话,都是0,这个0决定了跳转方向。
它就是:
004173CE     C645 DB 00      mov byte ptr ss:[ebp-25],0                         ; 赋值=0,12F86F
0041761F     8A45 DB         mov al,byte ptr ss:[ebp-25]                        ; 12F86F
00416FA0     8882 86040000   mov byte ptr ds:[edx+486],al                       ; 00EC29F2
00416FBD     80B9 86040000 0>cmp byte ptr ds:[ecx+486],0                        ; 00EC29F2

00416FC4    /0F84 75020000   je dump.0041723F                                   ; 关键跳转

因此修改注册码为40位的:
8765432112345678876543211234567887654321

4.注册码为40位的算法过程:
这次内置字符串仍然是:
0041743E     BE 8B335300     mov esi,dump.0053338B              ; ASCII "1z1h+2a0n-0g8y*9a1n|"

4.1先判断注册码第2位是不是25,即%:
0041746F     0FBE8D 69FFFFFF movsx ecx,byte ptr ss:[ebp-97]                     ; ZCM第2位
00417476     83F9 25         cmp ecx,25
00417479     75 09           jnz short dump.00417484
0041747B     C685 69FFFFFF 2>mov byte ptr ss:[ebp-97],23
00417482     EB 23           jmp short dump.004174A7

4.2然后开始运算:
004174C3     C645 DB 01          mov byte ptr ss:[ebp-25],1                ; 这个赋值太重要了
004174C7     C745 D0 02000000    mov dword ptr ss:[ebp-30],2               ; 2,指针
004174CE     8B55 D0             mov edx,dword ptr ss:[ebp-30]
004174D1     0FBE8C15 50FFFFFF   movsx ecx,byte ptr ss:[ebp+edx-B0]        ; 字符串第[指针+1]位
004174D9     8B45 D0             mov eax,dword ptr ss:[ebp-30]             ; 指针
004174DC     0FBE9405 67FFFFFF   movsx edx,byte ptr ss:[ebp+eax-99]        ; 注册码第[指针]位
004174E4     03CA                add ecx,edx                               ; +
004174E6     8B45 D0             mov eax,dword ptr ss:[ebp-30]
004174E9     0FBE9405 68FFFFFF   movsx edx,byte ptr ss:[ebp+eax-98]        ; 注册码第[指针+1]位
004174F1     33CA                xor ecx,edx                               ; XOR
004174F3     8B45 D0             mov eax,dword ptr ss:[ebp-30]
004174F6     0FBE9405 50FFFFFF   movsx edx,byte ptr ss:[ebp+eax-B0]        ; 字符串第[指针+1]位
004174FE     33CA                xor ecx,edx                               ; XOR
00417500     51                  push ecx
00417501     E8 5A1FFFFF         call dump.00409460
00417506     59                  pop ecx
00417507     B9 1A000000         mov ecx,1A
0041750C     99                  cdq
0041750D     F7F9                idiv ecx                                  ; /1A
0041750F     83C2 41             add edx,41                                ; +41
00417512     8B45 D0             mov eax,dword ptr ss:[ebp-30]
00417515     0FBE8405 71FFFFFF   movsx eax,byte ptr ss:[ebp+eax-8F]        ; 第[指针+10]位注册码
0041751D     3BD0                cmp edx,eax
0041751F     74 06               je short dump.00417527
00417521     C645 DB 00          mov byte ptr ss:[ebp-25],0
00417525     EB 09               jmp short dump.00417530
00417527     FF45 D0             inc dword ptr ss:[ebp-30]
0041752A     837D D0 0A          cmp dword ptr ss:[ebp-30],0A              ; A-2=8
0041752E   ^ 7C 9E               jl short dump.004174CE

初始值2,作为取字符串与注册码的指针,递增。
(第[指针+1]位字符串+第[指针]位注册码)XOR 第[指针+1]位注册码 XOR 第[指针+1]位字符串,
值/1A的余数+41=第[指针+10]位注册码。

得到的值:46 4E 58 5A 52 56 4B 4E,即: FNXZRVKN
注册码为:8%654321123 FNXZRVKN 543211234567887654321      

4.3 再一轮的计算:
0041754D     8B55 CC             mov edx,dword ptr ss:[ebp-34]
00417550     0FBE8415 51FFFFFF   movsx eax,byte ptr ss:[ebp+edx-AF]        ; zcm第[指针]位
00417558     B9 06000000         mov ecx,6
0041755D     99                  cdq
0041755E     F7F9                idiv ecx                                  ; /6
00417560     8BCA                mov ecx,edx                               ; 余数
00417562     8B45 CC             mov eax,dword ptr ss:[ebp-34]
00417565     0FBE9405 52FFFFFF   movsx edx,byte ptr ss:[ebp+eax-AE]        ; 注册码第[指针+1]位
0041756D     D3E2                shl edx,cl                                ; ×2~余数
0041756F     8B45 CC             mov eax,dword ptr ss:[ebp-34]
00417572     0FBE8C05 53FFFFFF   movsx ecx,byte ptr ss:[ebp+eax-AD]        ; 注册码第[指针+2]位
0041757A     0BD1                or edx,ecx                                ; or
0041757C     52                  push edx
0041757D     E8 DE1EFFFF         call dump.00409460
00417582     59                  pop ecx
00417583     B9 1A000000         mov ecx,1A
00417588     99                  cdq
00417589     F7F9                idiv ecx                                  ; /1A
0041758B     80C2 61             add dl,61                                 ; +61
0041758E     8B45 CC             mov eax,dword ptr ss:[ebp-34]
00417591     889405 24FFFFFF     mov byte ptr ss:[ebp+eax-DC],dl           ; 值保存
00417598     FF45 CC             inc dword ptr ss:[ebp-34]
0041759B     837D CC 28          cmp dword ptr ss:[ebp-34],28              ; 从18到28
0041759F   ^ 7C AC               jl short dump.0041754D
004175A1     C685 4CFFFFFF 5A    mov byte ptr ss:[ebp-B4],5A               ; 添一个5A
004175A8     C685 4DFFFFFF 59    mov byte ptr ss:[ebp-B3],59               ; 再添一个59

这次指针还是2,然后递增。
注册码第[指针+1]位×2~(注册码第[指针]位/6的余数) OR  注册码第[指针+2]位,
值/1A的余数61,保存。
运算18到28,共10位=16位(D)
注册码练码:8%654321123FNXZRVKN543211234567887654321 
值:0012F7D0  6E 62 7A 6D 72 6C 6B 70 79 6F 79 6D 6F 69 6A 63 nbzmrlkpyoymoijc
循环结束后又添了2个到后面:5A 59
计算值:0012F7D0  6E 62 7A 6D 72 6C 6B 70 79 6F 79 6D 6F 69 6A 63 5A 59 nbzmrlkpyoymoijcZY

4.4 然后对计算值再计算后比较:
004175C2     8B55 C8            mov edx,dword ptr ss:[ebp-38]
004175C5     0FBE8415 24FFFFFF  movsx eax,byte ptr ss:[ebp+edx-DC]        ; 顺取计算值?
004175CD     C1E0 04            shl eax,4
004175D0     8B55 C8            mov edx,dword ptr ss:[ebp-38]
004175D3     0FBE8C15 25FFFFFF  movsx ecx,byte ptr ss:[ebp+edx-DB]
004175DB     D1F9               sar ecx,1
004175DD     33C1               xor eax,ecx
004175DF     50                 push eax
004175E0     E8 7B1EFFFF        call dump.00409460
004175E5     59                 pop ecx
004175E6     B9 1A000000        mov ecx,1A
004175EB     99                 cdq
004175EC     F7F9               idiv ecx                                  ; /1A
004175EE     83C2 41            add edx,41                                ; +41
004175F1     8B45 C8            mov eax,dword ptr ss:[ebp-38]
004175F4     0FBE8405 68FFFFFF  movsx eax,byte ptr ss:[ebp+eax-98]        ; 注册码第25位
004175FC     3BD0               cmp edx,eax
004175FE     74 06              je short dump.00417606
00417600     C645 DB 00         mov byte ptr ss:[ebp-25],0
00417604     EB 09              jmp short dump.0041760F
00417606     FF45 C8            inc dword ptr ss:[ebp-38]
00417609     837D C8 28         cmp dword ptr ss:[ebp-38],28              ; 比较16次
0041760D   ^ 7C B3              jl short dump.004175C2

(计算值[第n位]×2~4) XOR (计算值[第n+1位]/2),
值/1A+41=注册码[第32+n位]。

即:44 46 53 42 55 4E 49 47 4A 59 49 5A 51 4C 52 46
DFSBUNIGJYIZQLRF

4.5然后比较注册码第11位是不是59=Y:
0041760F     0FBE95 72FFFFFF    movsx edx,byte ptr ss:[ebp-8E]            ; 注册码第11位
00417616     83FA 59            cmp edx,59                                ; 是不是59?
郁闷,这个这么重要最后才比较,前面白算了。

5.思路有了,反推注册码:
从头到尾只有2个是固定的,那就是第2位&第11位注册码,分别为:% Y
修改练码:8%65432112Y45678876543211234567887654321
第一轮运算可以得到第12位到第20位注册码:
46 4E 58 5A 52 56 4B 4E=FNXZRVKN

练码变为:8%65432112YFNXZRVKN543211234567887654321
第2轮运算得到第25位到第40位:
44 46 53 42 55 4E 4C 4B 5A 4B 49 5A 51 4C 52 46=DFSBUNLKZKIZQLRF

得到注册码:
8%65432112YFNXZRVKN54321DFSBUNLKZKIZQLRF

好了,这下关键跳转可以朝正确方向:
00416FBD     80B9 86040000 00   cmp byte ptr ds:[ecx+486],0               ; 00EC29F2
00416FC4     0F84 75020000      je dump.0041723F                          ; 关键跳转

6.虚晃一枪:
然后又比较第24位注册码:
00417018     0FBE50 17          movsx edx,byte ptr ds:[eax+17]            ; 注册码第24位
0041701C     83FA 30            cmp edx,30                                ; 是不是小于0?
0041701F     7C 16              jl short dump.00417037

0041702E     0FBE50 17          movsx edx,byte ptr ds:[eax+17]            ; 注册码第24位
00417032     83FA 39            cmp edx,39                                ; 是不是大于9?
00417035     7E 0F              jle short dump.00417046
吓出一身冷汗,还好,有惊无险。

然后写入注册表:
HKCU\Software\XTZY\ExeIcon\NO  SUCCESS  "8%65432112YFNXZRVKN54321DFSBUNLKZKIZQLRF"  
HKCU\Software\XTZY\ExeIcon\Name  SUCCESS  "cyto"  

7.后记:
刚开始比较注册码长度,可以24位,也可以40位,可是怎么跟都没能发现24位可以注册成功,被作者蒙了一把。
后来发现有个赋值,注册码输入24位的怎么都没改变,只有40位才看到赋值不一样。
接下来以为一路顺风了,思路很清楚了,可是等计算好后,它才冷不丁的比较已经计算过的注册码是否没错。只好再来一次。这种算法思路也不错,多搞几次,我可能就会崩溃。
等关键跳转朝正确方向走的时候,又来个比较,还好有惊无险,只是出了一声冷汗而已。
至此搞定。

2006.04.24