Articles

WinImage 7.0.7000 序列号算法

该软件没有用到复杂的加密算法,只是简单的四则运算。

WinImage使用的序列号算法应该是自创的,所以算法比较简单。 只是对用户名进行了简单的四则运算,每一个用户名应该可以有10种不同的序列号可用,下面是对用户名进行运算的代码。

初始化时,ECX = 0,[EBP – 4] = 0x47694C

0044883C /MOV EAX,ECX ; eax = 0
0044883E |PUSH 0E
00448840 |CDQ ; edx = 0
00448841 |POP EBX ; ebx = 0x0E
00448842 |IDIV EBX ; edx = eax % ebx
00448844 |TEST EDX,EDX ; eax = eax / ebx
00448846 |JNZ SHORT winimage.0044884B
00448848 |PUSH 27
0044884A |POP ESI ; esi = 0x27
0044884B |LEA EAX,DWORD PTR DS:[ECX+3] ; eax = ecx + 3
0044884E |MOVZX EDX,BYTE PTR DS:[EDI+EAX] ; edx = user_name[ecx]
00448852 |IMUL EDX,ESI ; edx = edx * esi
00448855 |ADD DWORD PTR SS:[EBP-4],EDX ; [EBP-4] += edx
00448858 |PUSH 0E
0044885A |CDQ ; edx = 0
0044885B |POP EBX ; ebx = 0x0E
0044885C |IDIV EBX ; edx = eax % ebx
0044885E |TEST EDX,EDX ; eax = eax / ebx
00448860 |JE SHORT winimage.00448867
00448862 |LEA ESI,DWORD PTR DS:[ESI+ESI*2] ; esi = esi * 3
00448865 |JMP SHORT winimage.0044886A
00448867 |IMUL ESI,ESI,7 ; esi = esi * 7
0044886A |INC ECX
0044886B |CMP ECX,DWORD PTR SS:[EBP-8] ; [ebp-8] = strlen(user_name)
0044886E \JL SHORT winimage.0044883C

经过上述运算,如果user_name = “lionel”的话,那么运算后[ebp-4] = 0x579453 程序在这里还有一处判断,就是[ebp-4] != 0xB8DCDD26,但我不清楚什么用户名能算出来这种结果。下面对刚算出来的结果进一步计算,总共有10步,但每一步的算法都是一样的。这里我们把刚刚算出来的结果记作val0 = 0x579453

0044887F PUSH DWORD PTR SS:[EBP+C] ; /val0
00448882 MOV ESI,DWORD PTR SS:[EBP+8] ; |
00448885 LEA EAX,DWORD PTR SS:[EBP-10] ; |
00448888 PUSH winimage.0045A2D0 ; |Format = "%lX"
0044888D PUSH EAX ; |buf
0044888E CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; \wsprintfA
00448894 MOV AL,BYTE PTR SS:[EBP-10]
00448897 ADD ESP,0C
0044889A TEST AL,AL
0044889C JE SHORT winimage.004488BB
0044889E LEA ECX,DWORD PTR SS:[EBP-10]
004488A1 SUB ECX,ESI
004488A3 /CMP AL,38 ; if(al == '8')
004488A5 |JNZ SHORT winimage.004488AB ; al += 0x0A;
004488A7 |ADD AL,0A
004488A9 |JMP SHORT winimage.004488B1
004488AB |CMP AL,42 ; else if(al == 0x42)
004488AD |JNZ SHORT winimage.004488B1 ; al -= 0x0A;
004488AF |ADD AL,0F6
004488B1 |MOV BYTE PTR DS:[ESI],AL
004488B3 |INC ESI
004488B4 |MOV AL,BYTE PTR DS:[ECX+ESI]
004488B7 |TEST AL,AL
004488B9 \JNZ SHORT winimage.004488A3

其实上面的运算就是把 val0中的 8替换成B,把 B换成 8,然后与输入的序列号进 行比较;如果不相等,那么val1 = val0 + 0x14051948,再进行上面的替换,然后 比较;如果还不相等,那么val2 = val1 + 0x17061954,再进行上面的替换,然后 比较;算上第一次,总共是比较了10次,这10次中,每次加上的常量分别是:

0x00000000 0x14051948 0x17061954 0x10051981 0x40111995
0x20611997 0x12091999 0x16062004 0x21042002 0x13062004

大家可以看出,后面 4位竟然都是年份!我觉得这很可能是对前几个版本序列号的 兼容,或者说着几个年份对Gilles Vollant公司有什么特别的意义。