【文章标题】: XXXX Graphics Suite X5 算法分析(一) Serial code
【文章作者】: Daniel
【作者邮箱】: vvcracker@gmail.com
【操作系统】: Windows 7
【生产日期】: 2010
【软件名称】: Graphics XXXXX XX SP3.v15.2.0.686
【软件介绍】: 一款著名的绘图软件
【加壳方式】: 无
【保护方式】: 注册码
【编写语言】: Microsoft Visual C++ 10.0
【使用工具】: OD + PEID + IDA Pro
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请各位大牛小牛原谅!
【讨论说明】
本文只讨论核心验证算法,由于涉及到函数处理较多,我只会将最重要的处理过程作说明,其他不作说明。
列出md5,blowfish算法只列出调用地方,算法的运作也不作说明。
验证入口:
0248344F |. 51 push ecx
02483450 |. 8D0D 62344802 lea ecx, dword ptr ds:[2483462]
02483456 |. 83C1 01 add ecx, 1
02483459 |. 51 push ecx [ecx+4] Serial码
0248345A |. E8 D1600100 call 02499530
进入02499530来到主验证过程,列出主要处理,
024834A4 . FF75 0C push dword ptr ss:[ebp+C] ; /maxlen
024834A7 . 8B45 90 mov eax, dword ptr ss:[ebp-70] ; |
024834AA . FF70 04 push dword ptr ds:[eax+4] ; |s2
024834AD . FF75 08 push dword ptr ss:[ebp+8] ; |s1 验证是否有DR15
024834B0 . FF15 58F56502 call dword ptr ds:[<&MSVCR90._strnicmp>] ; \_strnicmp
024834F1 . 50 push eax
024834F2 . 8B4D 90 mov ecx, dword ptr ss:[ebp-70]
024834F5 . E8 74FEFFFF call 0248336E 验证输入Serial code前7个字符是否符合条件
02483516 . 50 push eax
02483517 . 8B4D 90 mov ecx, dword ptr ss:[ebp-70]
0248351A . E8 FAFDFFFF call 02483319 验证输入Serial code后21个字符是否符合条件
0248354F . FF75 EC push dword ptr ss:[ebp-14] 长度
02483552 . 8B45 90 mov eax, dword ptr ss:[ebp-70]
02483555 . FF70 04 push dword ptr ds:[eax+4] [eax+4] 字符串
02483558 . 8B4D A4 mov ecx, dword ptr ss:[ebp-5C] 转换结果[ ecx + 4 ]
0248355B . E8 74F40000 call 024929D4 将Serial code后21个字符转换为15个
进入024929D4
02492A16 |. 8B5D 08 mov ebx, dword ptr ss:[ebp+8]
02492A19 |. 6A 07 push 7
02492A1B |. 53 push ebx
02492A1C |. 57 push edi
02492A1D |. FF76 04 push dword ptr ds:[esi+4] 先复制前7个字节
02492A20 |. FF15 14F76502 call dword ptr ds:[<&MSVCR90.memcpy_s>] ; MSVCR90.memcpy_s
02492A26 |. 83C4 20 add esp, 20
02492A29 |. 8D47 FA lea eax, dword ptr ds:[edi-6]
02492A2C |. 8945 FC mov dword ptr ss:[ebp-4], eax
02492A2F |. 8D45 FC lea eax, dword ptr ss:[ebp-4]
02492A32 |. 50 push eax
02492A33 |. 8B46 04 mov eax, dword ptr ds:[esi+4]
02492A36 |. 83C0 07 add eax, 7
02492A39 |. 50 push eax eax转换后的数组地址B
02492A3A |. 8B45 0C mov eax, dword ptr ss:[ebp+C]
02492A3D |. 83C0 F9 add eax, -7
02492A40 |. 50 push eax
02492A41 |. 83C3 07 add ebx, 7 长度
02492A44 |. 53 push ebx ebx要转换的数组地址A
02492A45 |. E8 9F100000 call 02493AE9 将21个字符转换为15个字符
02492A4A |. 33C0 xor eax, eax
02492A4C |. 3846 08 cmp byte ptr ds:[esi+8], al
02492A4F |. 5B pop ebx
02492A50 |. 0F95C0 setne al
02492A53 |. 8D0485 140000>lea eax, dword ptr ds:[eax*4+14]
02492A5A |. 8946 0C mov dword ptr ds:[esi+C], eax
02492A5D |. 3BF8 cmp edi, eax
02492A5F |. 76 1A jbe short 02492A7B
02492A61 |. 8D4F FF lea ecx, dword ptr ds:[edi-1]
02492A64 |. 3BC8 cmp ecx, eax
02492A66 |. 72 13 jb short 02492A7B
02492A68 |. 8B56 04 mov edx, dword ptr ds:[esi+4] 转换后的结果要求第15个字符为0,算法第一处验证
02492A6B |> 803C0A 00 /cmp byte ptr ds:[edx+ecx], 0
02492A6F |. 75 07 |jnz short 02492A78
02492A71 |. 49 |dec ecx
02492A72 |. 3BC8 |cmp ecx, eax
02492A74 |.^ 73 F5 \jnb short 02492A6B
02492A76 |. EB 03 jmp short 02492A7B
02492A78 |> 897E 0C mov dword ptr ds:[esi+C], edi 此值要求为0
看02493AE9的处理过程,主要是移位操作,从要转换的数组A中,获取的每个值先转换为5位数值,然后填充转换后的数组B中,
先填充每个字节的高位,接下来的值填充低位,每个字节填充完毕后,才增加索引,如此循环,直到用完要转换的数组A的21个字符。
02493AE9 /$ 55 push ebp
02493AEA |. 8BEC mov ebp, esp
02493AEC |. 51 push ecx
02493AED |. 8B45 0C mov eax, dword ptr ss:[ebp+C]
02493AF0 |. 53 push ebx
02493AF1 |. 6BC0 05 imul eax, eax, 5 与5相乘
02493AF4 |. 56 push esi
02493AF5 |. 57 push edi
02493AF6 |. 8B7D 10 mov edi, dword ptr ss:[ebp+10]
02493AF9 |. 6A 07 push 7
02493AFB |. 5B pop ebx
02493AFC |. 03C3 add eax, ebx
02493AFE |. 33F6 xor esi, esi
02493B00 |. C1E8 03 shr eax, 3 除以8,eax为转换数组的长度 = 0xE
02493B03 |. C645 FF 01 mov byte ptr ss:[ebp-1], 1
02493B07 |. 3BFE cmp edi, esi edi为要转换数组的地址,简称B
02493B09 |. 0F84 D9000000 je 02493BE8
02493B0F |. 8B4D 14 mov ecx, dword ptr ss:[ebp+14]
02493B12 |. 8B09 mov ecx, dword ptr ds:[ecx]
02493B14 |. 3BC1 cmp eax, ecx
02493B16 |. 76 09 jbe short 02493B21
02493B18 |. C645 FF 00 mov byte ptr ss:[ebp-1], 0
02493B1C |. E9 C7000000 jmp 02493BE8
02493B21 |> 51 push ecx ; /n
02493B22 |. 56 push esi ; |c
02493B23 |. 57 push edi ; |s
02493B24 |. E8 853C0000 call <jmp.&MSVCR90.memset> ; \memset
02493B29 |. 33D2 xor edx, edx
02493B2B |. 83C4 0C add esp, 0C
02493B2E |. 8975 10 mov dword ptr ss:[ebp+10], esi
02493B31 |. 3955 0C cmp dword ptr ss:[ebp+C], edx
02493B34 |. 0F86 A2000000 jbe 02493BDC
02493B3A |> 8B45 08 /mov eax, dword ptr ss:[ebp+8] eax转换数组开始地址称为A
02493B3D |. 8B4D 10 |mov ecx, dword ptr ss:[ebp+10] ecx索引
02493B40 |. 8A0C01 |mov cl, byte ptr ds:[ecx+eax] cl获取数组的值
02493B43 |. 8AC1 |mov al, cl
02493B45 |. 2C 32 |sub al, 32 以下是判断该值属于哪个范围,然后减去相应的值
02493B47 |. 3AC3 |cmp al, bl 经过观察,相减后,范围为0-0x1f
02493B49 |. 77 05 |ja short 02493B50
02493B4B |. 80E9 1A |sub cl, 1A
02493B4E |. EB 42 |jmp short 02493B92
02493B50 |> 8AC1 |mov al, cl
02493B52 |. 2C 41 |sub al, 41
02493B54 |. 3AC3 |cmp al, bl
02493B56 |. 76 3C |jbe short 02493B94
02493B58 |. 8AC1 |mov al, cl
02493B5A |. 2C 4A |sub al, 4A ; 分支 (案例 4A..A4)
02493B5C |. 3C 04 |cmp al, 4
02493B5E |. 77 05 |ja short 02493B65
02493B60 |. 80E9 42 |sub cl, 42 ; 案例 4A,4B,4C,4D,4E --> 分支 02493B5A
02493B63 |. EB 2D |jmp short 02493B92
02493B65 |> 8AC1 |mov al, cl
02493B67 |. 2C 50 |sub al, 50
02493B69 |. 3C 0A |cmp al, 0A
02493B6B |. 77 05 |ja short 02493B72
02493B6D |. 80E9 43 |sub cl, 43 ; 案例 9A,9B,9C,9D,9E,9F,A0,A1,A2,A3,A4 --> 分支 02493B5A
02493B70 |. EB 20 |jmp short 02493B92
02493B72 |> 8AC1 |mov al, cl ; 分支 02493B5A 默认案例
02493B74 |. 2C 61 |sub al, 61
02493B76 |. 3AC3 |cmp al, bl
02493B78 |. 76 1A |jbe short 02493B94
02493B7A |. 8AC1 |mov al, cl
02493B7C |. 2C 6A |sub al, 6A ; 分支 (案例 6A..E4)
02493B7E |. 3C 04 |cmp al, 4
02493B80 |. 77 05 |ja short 02493B87
02493B82 |. 80E9 62 |sub cl, 62 ; 案例 6A,6B,6C,6D,6E --> 分支 02493B7C
02493B85 |. EB 0B |jmp short 02493B92
02493B87 |> 8AC1 |mov al, cl
02493B89 |. 2C 70 |sub al, 70
02493B8B |. 3C 0A |cmp al, 0A
02493B8D |. 77 49 |ja short 02493BD8
02493B8F |. 80E9 63 |sub cl, 63 ; 案例 DA,DB,DC,DD,DE,DF,E0,E1,E2,E3,E4 --> 分支 02493B7C
02493B92 |> 8AC1 |mov al, cl
02493B94 |> 83FA 03 |cmp edx, 3 edx比较重要,代表当前已使用位数的数值,判断是否大于3
02493B97 |. 77 12 |ja short 02493BAB
02493B99 |. 83C2 FD |add edx, -3
02493B9C |. 23D3 |and edx, ebx 计算当前值剩余位数
02493B9E |. 75 06 |jnz short 02493BA6
02493BA0 |. 08043E |or byte ptr ds:[esi+edi], al 直接赋值
02493BA3 |. 46 |inc esi 增加B数组索引
02493BA4 |. EB 21 |jmp short 02493BC7
02493BA6 |> 6A 08 |push 8
02493BA8 |. 59 |pop ecx
02493BA9 |. EB 15 |jmp short 02493BC0
02493BAB |> 83C2 FD |add edx, -3
02493BAE |. 23D3 |and edx, ebx 计算当前值剩余位数
02493BB0 |. 8AD8 |mov bl, al
02493BB2 |. 8ACA |mov cl, dl
02493BB4 |. D2EB |shr bl, cl 当前值向右移位
02493BB6 |. 6A 08 |push 8
02493BB8 |. 59 |pop ecx ecx为字节的位数8
02493BB9 |. 6A 07 |push 7
02493BBB |. 081C3E |or byte ptr ds:[esi+edi], bl 赋值B数组
02493BBE |. 46 |inc esi B数组索引加1
02493BBF |. 5B |pop ebx
02493BC0 |> 2BCA |sub ecx, edx 要移位的数值 = 每个字节的位数 - 当前已使用的位数
02493BC2 |. D2E0 |shl al, cl 当前值移位
02493BC4 |. 08043E |or byte ptr ds:[esi+edi], al 赋值B数组
02493BC7 |> FF45 10 |inc dword ptr ss:[ebp+10] 增加数组A的索引
02493BCA |. 8B45 10 |mov eax, dword ptr ss:[ebp+10]
02493BCD |. 3B45 0C |cmp eax, dword ptr ss:[ebp+C]
02493BD0 |.^ 0F82 64FFFFFF \jb 02493B3A
02493BD6 |. EB 04 jmp short 02493BDC
02493BD8 |> C645 FF 00 mov byte ptr ss:[ebp-1], 0
02493BDC |> 845D 0C test byte ptr ss:[ebp+C], bl
02493BDF |. 74 01 je short 02493BE2
这处比较难理解,要细心调试,我只是点明关键部分,关键还是要自己调试。
回到主验证过程
02483583 . 8B45 90 mov eax, dword ptr ss:[ebp-70]
02483586 . FF70 28 push dword ptr ds:[eax+28]
02483589 . 8B45 90 mov eax, dword ptr ss:[ebp-70]
0248358C . FF70 24 push dword ptr ds:[eax+24]
0248358F . 8B4D E0 mov ecx, dword ptr ss:[ebp-20]
02483592 . E8 2A050100 call 02493AC1
02483597 . 8B45 90 mov eax, dword ptr ss:[ebp-70]
0248359A . FF70 1C push dword ptr ds:[eax+1C]
0248359D . 8B45 90 mov eax, dword ptr ss:[ebp-70]
024835A0 . FF70 14 push dword ptr ds:[eax+14]
024835A3 . 8B4D E0 mov ecx, dword ptr ss:[ebp-20]
024835A6 . E8 D8F50000 call 02492B83
024835AB . 8B45 90 mov eax, dword ptr ss:[ebp-70]
024835AE . FF70 20 push dword ptr ds:[eax+20]
024835B1 . 8B45 90 mov eax, dword ptr ss:[ebp-70]
024835B4 . FF70 18 push dword ptr ds:[eax+18]
024835B7 . 8B4D E0 mov ecx, dword ptr ss:[ebp-20]
024835BA . E8 04FBFFFF call 024830C3
024835BF . FF75 10 push dword ptr ss:[ebp+10]
024835C2 . 8B4D E0 mov ecx, dword ptr ss:[ebp-20]
024835C5 . E8 27040100 call 024939F1 对024929D4产生的结果进行blowfish解密
02493AC1,02492B83,024830C3获取固定字符,经过以上处理后分别在ecx+0x10,ecx+0x14,ecx+0x24保存结果
进入到024939F1,看主要处理过程
02493A12 . 8D4D EC lea ecx, dword ptr ss:[ebp-14]
02493A15 . 51 push ecx ecx为key
02493A16 . 8BCE mov ecx, esi
02493A18 . FF50 08 call dword ptr ds:[eax+8] 产生blowfish key
02493A1B . 6A 10 push 10
02493A1D . 8D45 EC lea eax, dword ptr ss:[ebp-14]
02493A20 . 50 push eax 用key初始化
02493A21 . E8 35C2FCFF call 0245FC5B blowfish init
02493A26 . 33C0 xor eax, eax
02493A28 . 3846 08 cmp byte ptr ds:[esi+8], al
02493A2B . 0F95C0 setne al
02493A2E . 8D0485 140000>lea eax, dword ptr ds:[eax*4+14]
02493A35 . 83E8 07 sub eax, 7
02493A38 . 50 push eax
02493A39 . 8B46 04 mov eax, dword ptr ds:[esi+4]
02493A3C . 83C0 07 add eax, 7
02493A3F . 50 push eax 从第7个字节开始解密,一共解8个字节
02493A40 . E8 D1C2FCFF call 0245FD16 blowfish decrypt
进入02493A18的md5 hash过程,列出主要过程
02493508 . 6A 07 push 7
0249350A . FF76 04 push dword ptr ds:[esi+4]
0249350D . 57 push edi
0249350E . 8B3D 14F76502 mov edi, dword ptr ds:[<&MSVCR90.memcpy_s>]
02493514 . 50 push eax 复制输入Serial Code前7个字符,eax为md5字符数组起始地址
02493515 . FFD7 call edi
02493517 . FF76 28 push dword ptr ds:[esi+28]
0249351A . 8B45 20 mov eax, dword ptr ss:[ebp+20]
0249351D . FF76 24 push dword ptr ds:[esi+24]
02493520 . 83C0 F9 add eax, -7
02493523 . 50 push eax
02493524 . 8945 2C mov dword ptr ss:[ebp+2C], eax
02493527 . 8B45 18 mov eax, dword ptr ss:[ebp+18]
0249352A . 83C0 07 add eax, 7
0249352D . 50 push eax
0249352E . FFD7 call edi 复制系列号的值,此处固定值
02493530 . 8B46 28 mov eax, dword ptr ds:[esi+28]
02493533 . 2945 2C sub dword ptr ss:[ebp+2C], eax
02493536 . 8B4D 18 mov ecx, dword ptr ss:[ebp+18]
02493539 . 6A 02 push 2
0249353B . 83C0 07 add eax, 7
0249353E . 68 40397202 push 02723940
02493543 . FF75 2C push dword ptr ss:[ebp+2C]
02493546 . 8945 24 mov dword ptr ss:[ebp+24], eax
02493549 . 03C1 add eax, ecx
0249354B . 50 push eax
0249354C . FFD7 call edi 复制字符串“v2”
0249356D . 50 push eax
0249356E . FF76 10 push dword ptr ds:[esi+10] 复制esi+10的字符串,跟024835BA处想同
02493571 . 50 push eax
02493572 . FF75 28 push dword ptr ss:[ebp+28]
02493575 . FFD7 call edi
02493577 . 83C4 10 add esp, 10
0249357A . 6A 04 push 4 ; /Arg3 = 00000004
0249357C . FF76 18 push dword ptr ds:[esi+18] ; |Arg2
0249357F . FF75 28 push dword ptr ss:[ebp+28] ; |Arg1
02493582 . E8 72C6FCFF call 0245FBF9 此处经过一些变换,固定变换
02493587 . FF76 18 push dword ptr ds:[esi+18]
0249358A . 8B4D 18 mov ecx, dword ptr ss:[ebp+18]
0249358D . FF75 28 push dword ptr ss:[ebp+28]
02493590 . 8B45 24 mov eax, dword ptr ss:[ebp+24]
02493593 . FF75 2C push dword ptr ss:[ebp+2C]
02493596 . 03C1 add eax, ecx
02493598 . 50 push eax
02493599 . FFD7 call edi 复制到md5字符数组
024935CD . 8B46 1C mov eax, dword ptr ds:[esi+1C] 复制esi+1C的字符串,跟024835BA处想同
024935D0 . 50 push eax
024935D1 . FF76 14 push dword ptr ds:[esi+14] 原始值处
024935D4 . 50 push eax
024935D5 . FF75 28 push dword ptr ss:[ebp+28]
024935D8 . FFD7 call edi ; MSVCR90.memcpy_s
024935DA . 83C4 10 add esp, 10
024935DD . 6A 05 push 5 ; /Arg3 = 00000005
024935DF . FF76 1C push dword ptr ds:[esi+1C] ; |Arg2
024935E2 . FF75 28 push dword ptr ss:[ebp+28] ; |Arg1
024935E5 . E8 0FC6FCFF call 0245FBF9 此处经过一些变换,固定变换
024935EA . FF76 1C push dword ptr ds:[esi+1C]
024935ED . 8B4D 18 mov ecx, dword ptr ss:[ebp+18]
024935F0 . FF75 28 push dword ptr ss:[ebp+28]
024935F3 . 8B45 24 mov eax, dword ptr ss:[ebp+24]
024935F6 . FF75 2C push dword ptr ss:[ebp+2C]
024935F9 . 03C1 add eax, ecx
024935FB . 50 push eax
024935FC . FFD7 call edi 复制到md5字符数组
02493615 . FF75 04 push dword ptr ss:[ebp+4] hash保存地址
02493618 . FF75 20 push dword ptr ss:[ebp+20] 长度
0249361B . FF75 18 push dword ptr ss:[ebp+18] 要hash数组
0249361E . E8 131EFEFF call 02475436 md5
这个过程主要md5 hash出来一个key给blowfish init用,回到上层。
然后Blowfish Init,Blowfish decrypt还原8个字符,这里不作详细说明。
回到主验证过程,
024835CA . FF75 10 push dword ptr ss:[ebp+10]
024835CD . 8B4D E0 mov ecx, dword ptr ss:[ebp-20]
024835D0 . E8 83030100 call 02493958 验证
进入02493958
02493989 |. 53 push ebx
0249398A |. 8B1D 14F76502 mov ebx, dword ptr ds:[<&MSVCR90.memcpy_s>] ; MSVCR90.memcpy_s
02493990 |. 56 push esi
02493991 |. FF77 04 push dword ptr ds:[edi+4]
02493994 |. 56 push esi
02493995 |. 55 push ebp 复制解密后的数据
02493996 |. FFD3 call ebx
02493998 |. 83C4 10 add esp, 10
0249399B |. FF7424 18 push dword ptr ss:[esp+18]
0249399F |. 8BCF mov ecx, edi
024939A1 |. E8 EEFCFFFF call 02493694
024939A6 |. 6A 07 push 7
024939A8 |. 58 pop eax
024939A9 |. 3BF0 cmp esi, eax
024939AB |. 76 17 jbe short 024939C4
024939AD |. 8B4F 04 mov ecx, dword ptr ds:[edi+4] 以下对比产生的值是否一致,从第8个字符开始,算法第二处验证
024939B0 |> 8A1401 /mov dl, byte ptr ds:[ecx+eax] 经02493694处理后的数据
024939B3 |. 3A1428 |cmp dl, byte ptr ds:[eax+ebp] Blowfish解密后的数据
024939B6 |. 75 07 |jnz short 024939BF
024939B8 |. 40 |inc eax
024939B9 |. 3BC6 |cmp eax, esi
024939BB |.^ 72 F3 \jb short 024939B0
024939BD |. EB 05 jmp short 024939C4
024939BF |> C64424 13 00 mov byte ptr ss:[esp+13], 0
看02493694的主要过程有02475481,
024936BF . 8D4D 50 lea ecx, dword ptr ss:[ebp+50]
024936C2 . 51 push ecx
024936C3 . 8BCE mov ecx, esi
024936C5 . FF50 08 call dword ptr ds:[eax+8] 计算key值,与02493A18处相同
024936C8 . 6A 10 push 10
024936DA . 6A 08 push 8
024936DC . 0F95C0 setne al
024936DF . 6A 00 push 0
024936E1 . 8D0485 140000>lea eax, dword ptr ds:[eax*4+14]
024936E8 . 8BF8 mov edi, eax
024936EA . 8B46 04 mov eax, dword ptr ds:[esi+4]
024936ED . 83C0 0C add eax, 0C
024936F0 . 50 push eax 清空解密后的数据后8个字节
024936F1 . E8 B8400000 call <jmp.&MSVCR90.memset> ; \memset
024936F6 . 83C4 18 add esp, 18
024936F9 . 8D45 60 lea eax, dword ptr ss:[ebp+60]
024936FC . 50 push eax eax保存02475481处理后的结果
024936FD . 8D45 50 lea eax, dword ptr ss:[ebp+50]
02493700 . 50 push eax
02493701 . 57 push edi edi数据长度0x14
02493702 . FF76 04 push dword ptr ds:[esi+4] esi数据起始地址
02493705 . E8 771DFEFF call 02475481 ; \CorelD_1.02475481
024938E2 . 50 push eax
024938E3 . 53 push ebx ebx保存结果
024938E4 . 8D45 60 lea eax, dword ptr ss:[ebp+60]
024938E7 . 50 push eax eax是02475481返回的hash数据
024938E8 . 8BCE mov ecx, esi
024938EA . E8 71FDFFFF call 02493660
02493902 . 53 push ebx
02493903 . 83C0 0C add eax, 0C
02493906 . 57 push edi
02493907 . 50 push eax
02493908 . FF15 BCF46502 call dword ptr ds:[<&MSVCR90.memmove_s>] copy经过02493660处理的结果 ,然后返回上层对比结果
先进入02475481,看细致处理过程
024754B7 |. 6A 10 push 10 ; /n = 10 (16.)
024754B9 |. 6A 36 push 36 ; |c = 36 ('6')
024754BB |. 56 push esi ; |s
024754BC |. E8 ED220200 call <jmp.&MSVCR90.memset> ; \memset
024754C1 |. 8D47 01 lea eax, dword ptr ds:[edi+1] 对16个字符赋值
024754C4 |. 50 push eax ; /n
024754C5 |. 8D5E 10 lea ebx, dword ptr ds:[esi+10] ; |
024754C8 |. 6A 00 push 0 ; |c = 00
024754CA |. 53 push ebx ; |s
024754CB |. E8 DE220200 call <jmp.&MSVCR90.memset> ; \memset
024754D0 |. 8B4D 10 mov ecx, dword ptr ss:[ebp+10]
024754D3 |. 83C4 18 add esp, 18
024754D6 |. 8BC6 mov eax, esi
024754D8 |. 2BCE sub ecx, esi
024754DA |. C745 E4 10000>mov dword ptr ss:[ebp-1C], 10
024754E1 |> 8A1401 /mov dl, byte ptr ds:[ecx+eax] 024754BB处esi跟key值异或
024754E4 |. 3010 |xor byte ptr ds:[eax], dl
024754E6 |. 40 |inc eax
024754E7 |. FF4D E4 |dec dword ptr ss:[ebp-1C]
024754EA |.^ 75 F5 \jnz short 024754E1
024754EC |. 57 push edi
024754ED |. FF75 E0 push dword ptr ss:[ebp-20]
024754F0 |. 57 push edi
024754F1 |. 53 push ebx 复制处理后的14个字节
024754F2 |. FF15 14F76502 call dword ptr ds:[<&MSVCR90.memcpy_s>] ; MSVCR90.memcpy_s
024754F8 |. 83C4 10 add esp, 10
024754FB |. 8D45 EC lea eax, dword ptr ss:[ebp-14]
024754FE |. 50 push eax
024754FF |. 83C7 10 add edi, 10
02475502 |. 57 push edi
02475503 |. 56 push esi
02475504 |. E8 2DFFFFFF call 02475436 md5 hash
0247551E |. 6A 10 push 10 与024754B7到02475504过程处理一样
02475520 |. 5F pop edi
02475521 |. 57 push edi ; /n => 10 (16.)
02475522 |. 6A 5C push 5C ; |c = 5C ('\')
02475524 |. 56 push esi ; |s
02475525 |. E8 84220200 call <jmp.&MSVCR90.memset> ; \memset
0247552A |. 8B4D 10 mov ecx, dword ptr ss:[ebp+10]
0247552D |. 83C4 0C add esp, 0C
02475530 |. 8BC6 mov eax, esi
02475532 |. 2BCE sub ecx, esi
02475534 |. 8BD7 mov edx, edi
02475536 |> 8A1C01 /mov bl, byte ptr ds:[ecx+eax]
02475539 |. 3018 |xor byte ptr ds:[eax], bl
0247553B |. 40 |inc eax
0247553C |. 4A |dec edx
0247553D |.^ 75 F7 \jnz short 02475536
0247553F |. 57 push edi
02475540 |. 8D45 EC lea eax, dword ptr ss:[ebp-14]
02475543 |. 50 push eax
02475544 |. 8D46 10 lea eax, dword ptr ds:[esi+10] 复制第一处md5 hash的值
02475547 |. 57 push edi
02475548 |. 50 push eax
02475549 |. FF15 BCF46502 call dword ptr ds:[<&MSVCR90.memmove_s>] ; MSVCR90.memmove_s
0247554F |. 83C4 10 add esp, 10
02475552 |. FF75 DC push dword ptr ss:[ebp-24] ; /Arg3
02475555 |. 6A 20 push 20 ; |Arg2 = 00000020
02475557 |. 56 push esi ; |Arg1
02475558 |. E8 D9FEFFFF call 02475436 md5
再进入02493660,这里主要将hash后的结果,前8位,与偶数的位异或,得到一个8字节的数组
02493678 |> /8A1C4F /mov bl, byte ptr ds:[edi+ecx*2] 取索引*2的值
0249367B |. |321C06 |xor bl, byte ptr ds:[esi+eax] 取当前索引的值,并异或
0249367E |. |41 |inc ecx
0249367F |. |8818 |mov byte ptr ds:[eax], bl 赋值
02493681 |. |40 |inc eax
02493682 |. |3BCA |cmp ecx, edx 循环8次
02493684 |.^\72 F2 \jb short 02493678
最后返回到024939AD对比结果。
【加密思路】
1.对输入的Serial code后21个字符数组转换为14个字节数组,14个字节数组简称A,且最后一位要求为0,具体算法看02493AE9的分析。
2.输入的Serial code前7个字符调用02492CF8,产生BlowFish的Key,再调用BlowFish Init;
3.Serial code前7个字符与A组成新的数组B,20个字节,对B调用BlowFish Decrypt,还原第8个字节起的8个字节,产生C;
4.数组D复制C数组,然后最后8个字节清零,然后调用02475481,产生一个hash,然后再调用02493660,将hash变为一个8字节
的数组,赋值到数组D的最后8个字节。
5.数组D与数组C比较,要求值一致。
【解密思路】
1.用字符串"DR15" + 随机生成8位字节组成12位的数组A,再加上8个值为零的字节组成20个字节数组B;
2.用B模拟调用02475481,产生一个hash,然后再模拟调用02493660,将hash变为一个8字节的数组,然后将此数组与A合并组成C;
3.取C的前7个字节模拟调用02492CF8,产生BlowFish的Key,再调用BlowFish Init;
4.对C第8个字节起的8个字节,调用BlowFish Encrypt,加密8个字节;
5.对C第8个字节起的13个字节,加上一个值为零的字节,组成14个字节,用到105位的数据,要还原21个字符,每一次取5位的数
据,按当前值的范围还原出原来的字符(还原规则看02493AE9),最后组成Serial code。
【结语】
这篇文章,只是列出关键的处理过程,只是向大家说明一个加密思路,细致的跟踪留给感兴趣的朋友们。
【版权声明】
本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2011 年 11月 16日 by Daniel
- 标 题:某著名绘图软件 XXXX Graphics Suite X5 算法分析 + 注册机
- 作 者:hewittlee
- 时 间:2011-11-16 09:59:43
- 链 接:http://bbs.pediy.com/showthread.php?t=142857