[原创]source insight 3.50.0076算法分析+kengen
【文章标题】source insight 3.50.0076分析
【文章作者】lacoucou
【软件名称】source insight version 3.50.0076 - Feb 19, 2015
【软件大小】6?MB 左右
【原版下载】http://www.sourceinsight.com/down35.html
【保护方式】序列号
【软件简介】主要就是看代码了
【作者声明】本文仅供研究学习,本人对因这篇文章而导致的一切后果,不承担任何法律责任。本文中的不足之处请各位多多指教。
【分析过程】
1.用错误字符串找到关键函数。过程就不说了。不过这次用ODv2.0搜索的感觉挺好用!!
关键函数:
00448E94 /$ 55 PUSH EBP ; 注册 00448E95 |. 8BEC MOV EBP,ESP 00448E97 |. 83EC 0C SUB ESP,0C 00448E9A |. C745 FC 7C5A5 MOV DWORD PTR SS:[LOCAL.1],OFFSET 005E5A 00448EA1 |. 8365 F8 00 AND DWORD PTR SS:[LOCAL.2],00000000 00448EA5 |. EB 07 JMP SHORT 00448EAE 00448EA7 |> 8B45 F8 /MOV EAX,DWORD PTR SS:[LOCAL.2] 00448EAA |. 40 |INC EAX 00448EAB |. 8945 F8 |MOV DWORD PTR SS:[LOCAL.2],EAX 00448EAE |> 837D F8 04 |CMP DWORD PTR SS:[LOCAL.2],4 00448EB2 |. 0F8D 5B010000 |JGE 00449013 00448EB8 |. 8025 7C5A5E00 |AND BYTE PTR DS:[5E5A7C],00 00448EBF |. 8D45 FC |LEA EAX,[LOCAL.1] 00448EC2 |. 50 |PUSH EAX ; /Arg3 => OFFSET LOCAL.1 00448EC3 |. 68 64010000 |PUSH 164 ; |Arg2 = 164 00448EC8 |. 68 F0D15300 |PUSH OFFSET 0053D1F0 ; |Arg1 = Insight3.53D1F0 00448ECD |. E8 9097FBFF |CALL 00402662 ; \Insight3.00402662 00448ED2 |. 8945 F4 |MOV DWORD PTR SS:[LOCAL.3],EAX 00448ED5 |. 837D F4 02 |CMP DWORD PTR SS:[LOCAL.3],2 00448ED9 |. 74 11 |JE SHORT 00448EEC 00448EDB |. 837D F4 01 |CMP DWORD PTR SS:[LOCAL.3],1 00448EDF |. 75 27 |JNE SHORT 00448F08 00448EE1 |. 0FB605 7C5A5E |MOVZX EAX,BYTE PTR DS:[5E5A7C] 00448EE8 |. 85C0 |TEST EAX,EAX 00448EEA |. 75 1C |JNZ SHORT 00448F08 00448EEC |> 68 78EC5300 |PUSH OFFSET 0053EC78 ; /Format = "You must enter a valid serial number to continue. Do you want to try again?" 00448EF1 |. E8 8AEEFBFF |CALL 00407D80 ; \Insight3.00407D80 00448EF6 |. 59 |POP ECX 00448EF7 |. 85C0 |TEST EAX,EAX 00448EF9 |. 75 07 |JNZ SHORT 00448F02 00448EFB |. 33C0 |XOR EAX,EAX 00448EFD |. E9 13010000 |JMP 00449015 00448F02 |> 8365 F8 00 |AND DWORD PTR SS:[LOCAL.2],00000000 00448F06 |.^ EB 9F |JMP SHORT 00448EA7 00448F08 |> 837D F4 15 |CMP DWORD PTR SS:[LOCAL.3],15 00448F0C |. 75 20 |JNE SHORT 00448F2E 00448F0E |. 68 C8EC5300 |PUSH OFFSET 0053ECC8 ; /Format = "Your Internet browser will now open and navigate to the Source Dynamics web site." 00448F13 |. E8 78F0FBFF |CALL 00407F90 ; \Insight3.00407F90 00448F18 |. 59 |POP ECX 00448F19 |. 6A 01 |PUSH 1 ; /Arg2 = 1 00448F1B |. 68 1CED5300 |PUSH OFFSET 0053ED1C ; |Arg1 = ASCII "http://www.sourceinsight.com/buyit.htm" 00448F20 |. E8 99020000 |CALL 004491BE ; \Insight3.004491BE 00448F25 |. 8365 F8 00 |AND DWORD PTR SS:[LOCAL.2],00000000 00448F29 |.^ E9 79FFFFFF |JMP 00448EA7 00448F2E |> 837D F4 14 |CMP DWORD PTR SS:[LOCAL.3],14 00448F32 |. 75 51 |JNE SHORT 00448F85 00448F34 |. 8025 7C5A5E00 |AND BYTE PTR DS:[5E5A7C],00 00448F3B |. 837D 08 00 |CMP DWORD PTR SS:[ARG.1],0 00448F3F |. 74 18 |JE SHORT 00448F59 00448F41 |. 68 44ED5300 |PUSH OFFSET 0053ED44 ; /Format = "You have indicated that you want to use a Trial License, which is good for 30 days. Is that correct?" 00448F46 |. E8 35EEFBFF |CALL 00407D80 ; \Insight3.00407D80 00448F4B |. 59 |POP ECX 00448F4C |. 85C0 |TEST EAX,EAX 00448F4E |. 75 09 |JNZ SHORT 00448F59 00448F50 |. 8365 F8 00 |AND DWORD PTR SS:[LOCAL.2],00000000 00448F54 |.^ E9 4EFFFFFF |JMP 00448EA7 00448F59 |> 68 7C5A5E00 |PUSH OFFSET 005E5A7C ; /Arg3 = Insight3.5E5A7C 00448F5E |. 68 50D05B00 |PUSH OFFSET 005BD050 ; |Arg2 = ASCII "SerialNumber" 00448F63 |. FF35 BC925C00 |PUSH DWORD PTR DS:[5C92BC] ; |Arg1 = 0 00448F69 |. E8 07AEFEFF |CALL 00433D75 ; \Insight3.00433D75 00448F6E |. C705 7C5D5E00 |MOV DWORD PTR DS:[5E5D7C],1 00448F78 |. E8 7BB9FFFF |CALL 004448F8 ; [Insight3.004448F8 00448F7D |. 6A 01 |PUSH 1 00448F7F |. 58 |POP EAX 00448F80 |. E9 90000000 |JMP 00449015 00448F85 |> 68 7C5A5E00 |PUSH OFFSET 005E5A7C ; /Arg1 = Insight3.5E5A7C 00448F8A |. E8 B33BFFFF |CALL 0043CB42 ; \Insight3.0043CB42 00448F8F |. 68 7C5A5E00 |PUSH OFFSET 005E5A7C ; /Arg1 = Insight3.5E5A7C 00448F94 |. E8 05570D00 |CALL 0051E69E ; \Insight3.0051E69E 00448F99 |. 59 |POP ECX 00448F9A |. 68 7C5A5E00 |PUSH OFFSET 005E5A7C ; /Arg1 = Insight3.5E5A7C 00448F9F |. E8 59030000 |CALL 004492FD ; \Insight3.004492FD 00448FA4 |. 85C0 |TEST EAX,EAX ; eax必须为1 00448FA6 |. 74 50 |JZ SHORT 00448FF8 00448FA8 |. 68 7C5A5E00 |PUSH OFFSET 005E5A7C ; /Arg3 = Insight3.5E5A7C 00448FAD |. 68 50D05B00 |PUSH OFFSET 005BD050 ; |Arg2 = ASCII "SerialNumber" 00448FB2 |. FF35 BC925C00 |PUSH DWORD PTR DS:[5C92BC] ; |Arg1 = 0 00448FB8 |. E8 B8ADFEFF |CALL 00433D75 ; \Insight3.00433D75 00448FBD |. 85C0 |TEST EAX,EAX 00448FBF |. 75 1B |JNZ SHORT 00448FDC 00448FC1 |. 68 ACED5300 |PUSH OFFSET 0053EDAC ; /Format = "You need permission to modify the HKEY_LOCAL_MACHINE registry hive. Please run Source Insight again while logged in as an Administrator or equivalent user." 00448FC6 |. E8 93EEFBFF |CALL 00407E5E ; \Insight3.00407E5E 00448FCB |. 59 |POP ECX 00448FCC |. 68 E8030000 |PUSH 3E8 ; /Time = 1000. ms 00448FD1 |. FF15 E4925200 |CALL DWORD PTR DS:[<&KERNEL32.Sleep>] ; \KERNEL32.Sleep 00448FD7 |.^ E9 CBFEFFFF |JMP 00448EA7 00448FDC |> 8325 645A5E00 |AND DWORD PTR DS:[5E5A64],00000000 00448FE3 |. E8 10B9FFFF |CALL 004448F8 ; [Insight3.004448F8 00448FE8 |. 68 4CEE5300 |PUSH OFFSET 0053EE4C ; /Format = "Thank you for registering Source Insight!" 00448FED |. E8 9EEFFBFF |CALL 00407F90 ; \Insight3.00407F90 00448FF2 |. 59 |POP ECX 00448FF3 |. 6A 01 |PUSH 1 00448FF5 |. 58 |POP EAX 00448FF6 |. EB 1D |JMP SHORT 00449015 00448FF8 |> 68 78EE5300 |PUSH OFFSET 0053EE78 ; /Format = "You typed an invalid serial number." 00448FFD |. E8 5CEEFBFF |CALL 00407E5E ; \Insight3.00407E5E 00449002 |. 59 |POP ECX 00449003 |. 68 E8030000 |PUSH 3E8 ; /Time = 1000. ms 00449008 |. FF15 E4925200 |CALL DWORD PTR DS:[<&KERNEL32.Sleep>] ; \KERNEL32.Sleep 0044900E |.^ E9 94FEFFFF \JMP 00448EA7 00449013 |> 33C0 XOR EAX,EAX 00449015 |> C9 LEAVE 00449016 \. C2 0400 RETN 4
这个函数OD已经注释的很明白了,就不说了。
验证注册码的函数是 sub_004492FD
地址 HEX 数据 指令 注释 004492FD /$ 55 PUSH EBP ; 验证算法? 004492FE |. 8BEC MOV EBP,ESP 00449300 |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; /Arg1 => [ARG.1] 00449303 |. E8 11FFFFFF CALL IsEquel_ES3US ; \Insight3.IsEquel_ES3US, 验证第一段是否是ES3US 00449308 |. 85C0 TEST EAX,EAX 0044930A |. 74 0A JZ SHORT 00449316 0044930C |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; /Arg1 => [ARG.1] 0044930F |. E8 E2000000 CALL 004493F6 ; \Insight3.004493F6, 可能是混淆算法 00449314 |. EB 08 JMP SHORT 0044931E 00449316 |> FF75 08 PUSH DWORD PTR SS:[ARG.1] ; /Arg1 => [ARG.1] 00449319 |. E8 04000000 CALL 00449322 ; \Insight3.00449322, 真正验证注册码的算法 0044931E |> 5D POP EBP 0044931F \. C2 0400 RETN 4
这个函数是一个简单的双分支结构。
第一个函数用来判断注册码前5个字节是否是ES3US,是的话返回1,不是返回0
返回1进入第二个函数:sub_004493F6
返回0进入第三个函数:sub_00449322
先来说说sub_004493F6这个巨坑的函数:
地址 HEX 数据 指令 注释 004493F6 /$ 55 PUSH EBP ; Insight3.004493F6(guessed Arg1 004493F7 |. 8BEC MOV EBP,ESP 004493F9 |. 81EC 08010000 SUB ESP,108 004493FF |. 68 60EF5300 PUSH OFFSET 0053EF60 ; /Arg1 = ASCII "ES3US" 00449404 |. E8 D73B0D00 CALL strlen ; \Insight3.strlen 00449409 |. 59 POP ECX 0044940A |. 50 PUSH EAX ; /Arg3 0044940B |. 68 68EF5300 PUSH OFFSET 0053EF68 ; |Arg2 = ASCII "ES3US" 00449410 |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg1 => [ARG.1] 00449413 |. E8 2EB2FCFF CALL memcmp ; \Insight3.memcmp 00449418 |. 85C0 TEST EAX,EAX 0044941A |. 75 04 JNZ SHORT 00449420 0044941C |. 33C0 XOR EAX,EAX 0044941E |. EB 53 JMP SHORT 00449473 00449420 |> 8D45 FC LEA EAX,[LOCAL.1] 00449423 |. 50 PUSH EAX ; /Arg3 => OFFSET LOCAL.1, 1 00449424 |. 8D85 F8FEFFFF LEA EAX,[LOCAL.66] ; | 0044942A |. 50 PUSH EAX ; |Arg2 => OFFSET LOCAL.66, 0 0044942B |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg1 => [ARG.1] 0044942E |. E8 11FEFFFF CALL PraseSerialNumber ; \Insight3.PraseSerialNumber, 检查注册码是否是三段式类似es3us-xxxxxx-yyyyy xxxxxx段必须为六位 将这段拷到参数2的缓冲区 yyyyy段必须是5位 将这个字符串转为数字放入参数3中 00449433 |. 85C0 TEST EAX,EAX 00449435 |. 74 04 JZ SHORT 0044943B 00449437 |. 33C0 XOR EAX,EAX 00449439 |. EB 38 JMP SHORT 00449473 0044943B |> FFB5 F8FEFFFF PUSH DWORD PTR SS:[LOCAL.6 ; /Arg2 => [LOCAL.66] 00449441 |. 8D85 F8FEFFFF LEA EAX,[LOCAL.66] ; | 00449447 |. 50 PUSH EAX ; |Arg1 => OFFSET LOCAL.66 00449448 |. E8 72FAFDFF CALL 00428EBF ; \Insight3.00428EBF 0044944D |. 85C0 TEST EAX,EAX ; 不能为0 0044944F |. 74 04 JZ SHORT 00449455 00449451 |. 33C0 XOR EAX,EAX 00449453 |. EB 1E JMP SHORT 00449473 00449455 |> 8D85 F8FEFFFF LEA EAX,[LOCAL.66] 0044945B |. 50 PUSH EAX ; /Arg1 => OFFSET LOCAL.66 0044945C |. E8 C0B00A00 CALL 004F4521 ; \Insight3.004F4521 00449461 |. 8945 F8 MOV DWORD PTR SS:[LOCAL.2] 00449464 |. 8B45 FC MOV EAX,DWORD PTR SS:[LOCA 00449467 |. 3B45 F8 CMP EAX,DWORD PTR SS:[LOCA 0044946A |. 74 04 JE SHORT 00449470 0044946C |. 33C0 XOR EAX,EAX 0044946E |. EB 03 JMP SHORT 00449473 00449470 |> 6A 01 PUSH 1 00449472 |. 58 POP EAX 00449473 |> C9 LEAVE 00449474 \. C2 0400 RETN 4
这个函数主要流程。
1.先判断注册码的前五个字节是不是"ES3US" 不是就返回0 是就继续
2.接下来这个被我命名为PraseSerialNumber 参数有三个
参数1.我们的注册码 【in】
参数2.一个字符串缓冲区 【out】
参数3.整形缓冲区 [out]
根据这个函数的内容,我猜测注册码大概是ES3US-XXXXXX-YYYYY这样的形式。用‘-’把注册码分成三段,第一段是固定的形式,第二段是一个6位的字符串,第三段是一个5为的字符串。满足这样的格式,就会返回1,并且把中间的六位拷贝到参数2的缓冲区,把后五位利用atoi函数转换成整形并把值放在参数3里边。
贴下代码:
CPU Disasm
地址 HEX 数据 指令 注释
00449244 PraseSerialNumber /$ 55 PUSH EBP ; Insight3.PraseSerialNumber(guessed Arg1,Arg2,Arg3
00449245 |. 8BEC MOV EBP,ESP
00449247 |. 83EC 10 SUB ESP,10
0044924A |. 56 PUSH ESI
0044924B |. 6A 2D PUSH 2D ; /Arg2 = 2D
0044924D |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg1 => [ARG.1]
00449250 |. E8 9B430D00 CALL strchr ; \Insight3.strchr, char *strchr(char* _Str,int _Ch)
00449255 |. 59 POP ECX
00449256 |. 59 POP ECX
00449257 |. 8945 FC MOV DWORD PTR SS:[LOCAL.1]
0044925A |. 837D FC 00 CMP DWORD PTR SS:[LOCAL.1] ; 比较是否有-
0044925E |. 75 07 JNE SHORT 00449267
00449260 |. 33C0 XOR EAX,EAX
00449262 |. E9 91000000 JMP 004492F8
00449267 |> 8B75 FC MOV ESI,DWORD PTR SS:[LOCA
0044926A |. 2B75 08 SUB ESI,DWORD PTR SS:[ARG. ; 计算第一个‘-’之前字符串长度
0044926D |. 68 50815A00 PUSH OFFSET 005A8150 ; /Arg1 = ASCII "SI3US"
00449272 |. E8 693D0D00 CALL strlen ; \Insight3.strlen
00449277 |. 59 POP ECX
00449278 |. 3BF0 CMP ESI,EAX ; 比较第一串是否等于 si3us
0044927A |. 74 04 JE SHORT 00449280
0044927C |. 33C0 XOR EAX,EAX
0044927E |. EB 78 JMP SHORT 004492F8
00449280 |> 8B45 FC MOV EAX,DWORD PTR SS:[LOCA
00449283 |. 40 INC EAX ; 跳过-
00449284 |. 8945 FC MOV DWORD PTR SS:[LOCAL.1]
00449287 |. 8B45 FC MOV EAX,DWORD PTR SS:[LOCA
0044928A |. 8945 F4 MOV DWORD PTR SS:[LOCAL.3]
0044928D |. 6A 2D PUSH 2D ; /Arg2 = 2D
0044928F |. FF75 FC PUSH DWORD PTR SS:[LOCAL.1 ; |Arg1 => [LOCAL.1]
00449292 |. E8 59430D00 CALL strchr ; \Insight3.strchr, 找第二个‘-’
00449297 |. 59 POP ECX
00449298 |. 59 POP ECX
00449299 |. 8945 F0 MOV DWORD PTR SS:[LOCAL.4]
0044929C |. 837D F0 00 CMP DWORD PTR SS:[LOCAL.4]
004492A0 |. 75 04 JNE SHORT 004492A6
004492A2 |. 33C0 XOR EAX,EAX
004492A4 |. EB 52 JMP SHORT 004492F8
004492A6 |> 8B45 F0 MOV EAX,DWORD PTR SS:[LOCA
004492A9 |. 8020 00 AND BYTE PTR DS:[EAX],00 ; 清除2d('-')
004492AC |. 8B45 F0 MOV EAX,DWORD PTR SS:[LOCA ; es3us-xxx1-xxx2
004492AF |. 2B45 F4 SUB EAX,DWORD PTR SS:[LOCA
004492B2 |. 83F8 06 CMP EAX,6 ; 比较xxx1的长度是否是6位
004492B5 |. 74 04 JE SHORT 004492BB
004492B7 |. 33C0 XOR EAX,EAX
004492B9 |. EB 3D JMP SHORT 004492F8
004492BB |> FF75 F4 PUSH DWORD PTR SS:[LOCAL.3
004492BE |. FF75 0C PUSH DWORD PTR SS:[ARG.2]
004492C1 |. E8 0A3E0D00 CALL strcpy ; strcpy(arg.2,xxx1) 把中间一段拷到参数2的缓冲区
004492C6 |. 59 POP ECX
004492C7 |. 59 POP ECX
004492C8 |. 8B45 F0 MOV EAX,DWORD PTR SS:[LOCA
004492CB |. 40 INC EAX
004492CC |. 8945 F8 MOV DWORD PTR SS:[LOCAL.2]
004492CF |. FF75 F8 PUSH DWORD PTR SS:[LOCAL.2 ; /Arg1 => [LOCAL.2]
004492D2 |. E8 093D0D00 CALL strlen ; \Insight3.strlen
004492D7 |. 59 POP ECX
004492D8 |. 83F8 05 CMP EAX,5 ; 看xxx2段是否是五位
004492DB |. 74 04 JE SHORT 004492E1
004492DD |. 33C0 XOR EAX,EAX
004492DF |. EB 17 JMP SHORT 004492F8
004492E1 |> FF75 F8 PUSH DWORD PTR SS:[LOCAL.2 ; /Arg1 => [LOCAL.2]
004492E4 |. E8 E9420D00 CALL atoi ; \Insight3.atoi
004492E9 |. 59 POP ECX
004492EA |. 8B4D 10 MOV ECX,DWORD PTR SS:[ARG.
004492ED |. 8901 MOV DWORD PTR DS:[ECX],EAX
004492EF |. 8B45 F0 MOV EAX,DWORD PTR SS:[LOCA
004492F2 |. C600 2D MOV BYTE PTR DS:[EAX],2D
004492F5 |. 6A 01 PUSH 1
004492F7 |. 58 POP EAX
004492F8 |> 5E POP ESI
004492F9 |. C9 LEAVE
004492FA \. C2 0C00 RETN 0C
当然这个算法逗比的地方就在下边,如果注册码满足ES3US-XXXXXX-YYYYY的话,这里就直接跳走了。
3.不过还是看下下边的两个函数。
Sub_00428EBF 这个让人摸不着头脑。IDA出来是下边这样参数1是注册码中间一段字符串的前4位转int 参数2是中间那段
BOOL __stdcall sub_428EBF(int a1, unsigned __int8 a2)
{
while ( *(_BYTE *)a1 == a2 && *(_BYTE *)a1 )
++a1;
return *(_BYTE *)a1 == 0;
}下一个的函数:
CPU Disasm 地址 HEX 数据 指令 注释 004F4521 /$ 55 PUSH EBP ; Insight3.004F4521(guessed Arg1 004F4522 |. 8BEC MOV EBP,ESP 004F4524 |. 83EC 10 SUB ESP,10 004F4527 |. 56 PUSH ESI 004F4528 |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; /Arg1 => [ARG.1] 004F452B |. E8 A2900200 CALL atoi ; \Insight3.atoi 004F4530 |. 59 POP ECX 004F4531 |. 8945 F4 MOV DWORD PTR SS:[LOCAL.3],EAX 004F4534 |. C745 F0 7F000 MOV DWORD PTR SS:[LOCAL.4],7F 004F453B |. 8B45 F4 MOV EAX,DWORD PTR SS:[LOCAL.3] 004F453E |. 8945 FC MOV DWORD PTR SS:[LOCAL.1],EAX 004F4541 |. 8B45 08 MOV EAX,DWORD PTR SS:[ARG.1] 004F4544 |. 8945 F8 MOV DWORD PTR SS:[LOCAL.2],EAX 004F4547 |. EB 07 JMP SHORT 004F4550 004F4549 |> 8B45 F8 /MOV EAX,DWORD PTR SS:[LOCAL.2] 004F454C |. 40 |INC EAX 004F454D |. 8945 F8 |MOV DWORD PTR SS:[LOCAL.2],EAX 004F4550 |> 8B45 F8 |MOV EAX,DWORD PTR SS:[LOCAL.2] 004F4553 |. 0FB600 |MOVZX EAX,BYTE PTR DS:[EAX] 004F4556 |. 85C0 |TEST EAX,EAX 004F4558 |. 74 24 |JZ SHORT 004F457E 004F455A |. 8B4D FC |MOV ECX,DWORD PTR SS:[LOCAL.1] 004F455D |. C1E1 04 |SHL ECX,4 004F4560 |. 8B45 F8 |MOV EAX,DWORD PTR SS:[LOCAL.2] 004F4563 |. 0FB630 |MOVZX ESI,BYTE PTR DS:[EAX] 004F4566 |. 8B45 F8 |MOV EAX,DWORD PTR SS:[LOCAL.2] 004F4569 |. 0FB600 |MOVZX EAX,BYTE PTR DS:[EAX] 004F456C |. 99 |CDQ 004F456D |. F77D F0 |IDIV DWORD PTR SS:[LOCAL.4] 004F4570 |. 030C95 80815A |ADD ECX,DWORD PTR DS:[EDX*4+5A81 004F4577 |. 03F1 |ADD ESI,ECX 004F4579 |. 8975 FC |MOV DWORD PTR SS:[LOCAL.1],ESI 004F457C |.^ EB CB \JMP SHORT 004F4549 004F457E |> 8B45 FC MOV EAX,DWORD PTR SS:[LOCAL.1] 004F4581 |. 33D2 XOR EDX,EDX 004F4583 |. B9 A0860100 MOV ECX,186A0 004F4588 |. F7F1 DIV ECX 004F458A |. 8BC2 MOV EAX,EDX 004F458C |. 5E POP ESI 004F458D |. C9 LEAVE 004F458E \. C2 0400 RETN 4
还原成C代码:
//注册码样式 es3us-123456-777777 根据中间一段的字符串生成第三段的数值 返回1才行
int CSource_insight_kengenDlg::CalaSeg3(char *pSeg2)
{
int nSeg2 = atoi(pSeg2);
char *pSz=pSeg2;
DWORD* dwAry=(DWORD*)data; //data是一个全局int数组总共127个元素在虚拟地址5a8180处 文件1a8180处
while(*pSz!=0)
{
nSeg2=dwAry[*pSz%127]+16*nSeg2+*pSz;
pSz++;
}
return nSeg2 % 0x186A0u;
}函数的最后就是比较PraseSerialNumber的第三个参数和CalaSeg3返回的结果是否相等。相等返回1就成功了。
不过这个函数逻辑比较奇葩不知到怎么才能产生这种结果。
如果注册码是ES3US-XXXXXX-YYYYY的话PraseSerialNumber返回之后就结束了。
把注册码改成ES3US-XXXXXX-YYYYYY(6个Y)就要CalaSeg3返回的结果为1才能成功,是在不知道怎么拼凑,就先放放吧。
下边再说真正验证注册码的函数。
sub_00449322
CPU Disasm 地址 HEX 数据 指令 注释 00449322 /$ 55 PUSH EBP ; Insight3.00449322(guessed Arg1 00449323 |. 8BEC MOV EBP,ESP 00449325 |. 81EC 10010000 SUB ESP,110 0044932B |. 68 50815A00 PUSH OFFSET 005A8150 ; /Arg1 = ASCII "SI3US" 00449330 |. E8 AB3C0D00 CALL strlen ; \Insight3.strlen 00449335 |. 59 POP ECX 00449336 |. 50 PUSH EAX ; /Arg3 00449337 |. 68 50815A00 PUSH OFFSET 005A8150 ; |Arg2 = ASCII "SI3US" 0044933C |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg1 => [ARG.1] 0044933F |. E8 02B3FCFF CALL memcmp ; \Insight3.memcmp 00449344 |. 85C0 TEST EAX,EAX 00449346 |. 75 07 JNZ SHORT 0044934F 00449348 |. 33C0 XOR EAX,EAX 0044934A |. E9 A3000000 JMP 004493F2 0044934F |> 8D45 FC LEA EAX,[LOCAL.1] 00449352 |. 50 PUSH EAX ; /Arg3 => OFFSET LOCAL.1 00449353 |. 8D85 F8FEFFFF LEA EAX,[LOCAL.66] ; | 00449359 |. 50 PUSH EAX ; |Arg2 => OFFSET LOCAL.66 0044935A |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; |Arg1 => [ARG.1] 0044935D |. E8 E2FEFFFF CALL PraseSerialNumber ; \Insight3.PraseSerialNumber 00449362 |. 85C0 TEST EAX,EAX 00449364 |. 75 07 JNZ SHORT 0044936D 00449366 |. 33C0 XOR EAX,EAX 00449368 |. E9 85000000 JMP 004493F2 0044936D |> FFB5 F8FEFFFF PUSH DWORD PTR SS:[LOCAL.66] ; /Arg2 => [LOCAL.66] 00449373 |. 8D85 F8FEFFFF LEA EAX,[LOCAL.66] ; | 00449379 |. 50 PUSH EAX ; |Arg1 => OFFSET LOCAL.66 0044937A |. E8 40FBFDFF CALL 00428EBF ; \Insight3.00428EBF 0044937F |. 85C0 TEST EAX,EAX 00449381 |. 74 04 JZ SHORT 00449387 00449383 |. 33C0 XOR EAX,EAX 00449385 |. EB 6B JMP SHORT 004493F2 00449387 |> 8D85 F8FEFFFF LEA EAX,[LOCAL.66] 0044938D |. 50 PUSH EAX ; /Arg1 => OFFSET LOCAL.66 0044938E |. E8 3F420D00 CALL atoi ; \Insight3.atoi 00449393 |. 59 POP ECX 00449394 |. 8985 F0FEFFFF MOV DWORD PTR SS:[LOCAL.68],EAX 0044939A |. 83A5 F4FEFFFF AND DWORD PTR SS:[LOCAL.67],00000000 004493A1 |. EB 0D JMP SHORT 004493B0 004493A3 |> 8B85 F4FEFFFF /MOV EAX,DWORD PTR SS:[EBP-10C] 004493A9 |. 40 |INC EAX 004493AA |. 8985 F4FEFFFF |MOV DWORD PTR SS:[EBP-10C],EAX 004493B0 |> 83BD F4FEFFFF |CMP DWORD PTR SS:[EBP-10C],1E ; 30 004493B7 |. 73 1B |JAE SHORT 004493D4 004493B9 |. 8B85 F4FEFFFF |MOV EAX,DWORD PTR SS:[EBP-10C] ; i=[ebp-10c] 004493BF |. 8B8D F0FEFFFF |MOV ECX,DWORD PTR SS:[EBP-110] 004493C5 |. 3B0C85 28C653 |CMP ECX,DWORD PTR DS:[EAX*4+53C628] ; ASCII "90" 004493CC |.^ 75 04 |JNE SHORT 004493D2 004493CE |. 33C0 |XOR EAX,EAX 004493D0 |. EB 20 |JMP SHORT 004493F2 004493D2 |>^ EB CF \JMP SHORT 004493A3 ; 检查中间一段是否在全局数组中 004493D4 |> 8D85 F8FEFFFF LEA EAX,[EBP-108] 004493DA |. 50 PUSH EAX ; /Arg1 004493DB |. E8 B1B10A00 CALL 004F4591 ; \Insight3.004F4591 004493E0 |. 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 004493E3 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 004493E6 |. 3B45 F8 CMP EAX,DWORD PTR SS:[EBP-8] 004493E9 |. 74 04 JE SHORT 004493EF 004493EB |. 33C0 XOR EAX,EAX 004493ED |. EB 03 JMP SHORT 004493F2 004493EF |> 6A 01 PUSH 1 004493F1 |. 58 POP EAX 004493F2 |> C9 LEAVE 004493F3 \. C2 0400 RETN 4
个人感觉这个就正常多了:
1.首先判断注册码前边是不是"SI3US"。
2.然后调用PraseSerialNumber
根据这个函数的内容,我猜测注册码大概是ES3US-XXXXXX-YYYYY这样的形式。用‘-’把注册码分成三段,第一段是固定的形式,第二段是一个6位的字符串,第三段是一个5为的字符串。满足这样的格式,就会返回1,并且把中间的六位拷贝到参数2的缓冲区,把后五位利用atoi函数转换成整形并把值放在参数3里边。
3.接着检查XXXXX是不是111111 222222 123456这样的字符串对照算法中的循环部分。
4.Sub_004F4591是跟据XXXXXX算出一个值。
CPU Disasm 地址 HEX 数据 指令 注释 004F4591 /$ 55 PUSH EBP ; Insight3.004F4591(guessed Arg1 004F4592 |. 8BEC MOV EBP,ESP 004F4594 |. 83EC 10 SUB ESP,10 004F4597 |. FF75 08 PUSH DWORD PTR SS:[ARG.1] ; /Arg1 => [ARG.1] 004F459A |. E8 33900200 CALL atoi ; \Insight3.atoi 004F459F |. 59 POP ECX 004F45A0 |. 8945 F0 MOV DWORD PTR SS:[LOCAL.4],EAX 004F45A3 |. 8B45 F0 MOV EAX,DWORD PTR SS:[LOCAL.4] 004F45A6 |. 8945 FC MOV DWORD PTR SS:[LOCAL.1],EAX 004F45A9 |. 8365 F4 00 AND DWORD PTR SS:[LOCAL.3],00000000 004F45AD |. 8B45 08 MOV EAX,DWORD PTR SS:[ARG.1] 004F45B0 |. 8945 F8 MOV DWORD PTR SS:[LOCAL.2],EAX 004F45B3 |. EB 07 JMP SHORT 004F45BC 004F45B5 |> 8B45 F8 /MOV EAX,DWORD PTR SS:[LOCAL.2] 004F45B8 |. 40 |INC EAX 004F45B9 |. 8945 F8 |MOV DWORD PTR SS:[LOCAL.2],EAX 004F45BC |> 8B45 F8 |MOV EAX,DWORD PTR SS:[LOCAL.2] 004F45BF |. 0FB600 |MOVZX EAX,BYTE PTR DS:[EAX] 004F45C2 |. 85C0 |TEST EAX,EAX 004F45C4 |. 74 2C |JZ SHORT 004F45F2 004F45C6 |. 8B45 F8 |MOV EAX,DWORD PTR SS:[LOCAL.2] 004F45C9 |. 0FB600 |MOVZX EAX,BYTE PTR DS:[EAX] 004F45CC |. 8B4D F4 |MOV ECX,DWORD PTR SS:[LOCAL.3] 004F45CF |. 33048D 58815A |XOR EAX,DWORD PTR DS:[ECX*4+5A8158] 004F45D6 |. 8B4D FC |MOV ECX,DWORD PTR SS:[LOCAL.1] 004F45D9 |. 8D0488 |LEA EAX,[ECX*4+EAX] 004F45DC |. 8945 FC |MOV DWORD PTR SS:[LOCAL.1],EAX 004F45DF |. 8B45 F4 |MOV EAX,DWORD PTR SS:[LOCAL.3] 004F45E2 |. 40 |INC EAX 004F45E3 |. 8945 F4 |MOV DWORD PTR SS:[LOCAL.3],EAX 004F45E6 |. 837D F4 0A |CMP DWORD PTR SS:[LOCAL.3],0A 004F45EA |.^ 75 04 |JNE SHORT 004F45F0 004F45EC |. 8365 F4 00 |AND DWORD PTR SS:[LOCAL.3],00000000 004F45F0 |>^ EB C3 \JMP SHORT 004F45B5 004F45F2 |> 8B45 FC MOV EAX,DWORD PTR SS:[LOCAL.1] 004F45F5 |. 33D2 XOR EDX,EDX 004F45F7 |. B9 A0860100 MOV ECX,186A0 004F45FC |. F7F1 DIV ECX 004F45FE |. 8BC2 MOV EAX,EDX 004F4600 |. C9 LEAVE 004F4601 \. C2 0400 RETN 4
还原出来的等价代码。
int CalcSegRight(char *pSeg2)
{
//数组在5a8158处 程序中是全局数组
int ary[10]={0x96,0x95,0x10,0x23,0x07,0x15,0x08,0x03,0x10,0x11};
int nSeg2 = atoi(pSeg2);
char *pSz=pSeg2;
int i=0;
while(*pSz!=0)
{
nSeg2=(ary[i]^*pSz)+4*nSeg2;
i++;
if (i==10)
{
i=0;
}
pSz++;
}
return nSeg2 % 0x186A0u;
}最后比较CalcSegRight计算的结果是否等于YYYYY转成整形后的数值,等于就返回1,不等于就返回0.
注册码验证成功就会把注册码保存在:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SourceDynamics\Source Insight\3.0\Install]
中。
注册机算法;
利用随机数生成中间的一段,然后调用CalcSegRight计算出第三段。
void CSource_insight_kengenDlg::Right()
{
int ary[6]={0x96,0x95,0x10,0x23,0x07,0x15};
char szBuf[128]={0};
//第二段随机生成
DWORD dwSeg2=GetTickCount()*rand() %0xF4240;
sprintf(szBuf,"%06u",dwSeg2);
int nSeg3=CalcSegRight(szBuf);
memset(szBuf,0,sizeof(szBuf));
wsprintf(szBuf,"SI3US-%06u-%05d",dwSeg2,nSeg3);
SetDlgItemText(IDC_EDIT_SER,szBuf);
}
int CSource_insight_kengenDlg::CalcSegRight(char *pSeg2)
{
//数组在5a8158处
int ary[10]={0x96,0x95,0x10,0x23,0x07,0x15,0x08,0x03,0x10,0x11};
int nSeg2 = atoi(pSeg2);
char *pSz=pSeg2;
int i=0;
while(*pSz!=0)
{
nSeg2=(ary[i]^*pSz)+4*nSeg2;
i++;
if (i==10)
{
i=0;
}
pSz++;
}
return nSeg2 % 0x186A0u;
}下边把源代码放上来:
Source_insight_kengen.zip
