前几天下载了VS2005,拖完之后才发现它的扩展名为.daa,用winrar无法打开,Google了一下才知道可以用Power***进行解压,于是就下了一个3.2版本,
但是安装包内没有注册机,于是我就没有注册码,导致它每次在启动时都会有一个恼人NAG,所以决定要干掉它。
令人兴奋的是它没有加壳,这省了不少麻烦,现在可以直接抄家伙恐吓它,若不从!嘿嘿.....
很明显它是不会从的,那就只能按章办事了,用OD加载,打上IsDebugPresent,忽略所有异常,F9,现在弹出程序的主界面,选 "输入注册码"菜单项, 然后输入:
用户名:thinkSJ 序列号:78999 45666 12333 65444 98777
它已经为我们定好了序列号的格式,这对破解它还是很有好处的,感谢作者。然后返回OD下断:bpx GetWindowTextA,再点OK于是乎被断下,代码如下:
0045E565 /$ 55 push ebp
0045E566 |. 8BEC mov ebp,esp
0045E568 |. 56 push esi
0045E569 |. 57 push edi
0045E56A |. 8B7D 08 mov edi,dword ptr ss:[ebp+8] ; 取出第一个参数
0045E56D |. FF75 0C push dword ptr ss:[ebp+C] ; 第二个参数入栈
0045E570 |. 8BCF mov ecx,edi
0045E572 |. E8 73FFFFFF call PowerISO.0045E4EA
0045E577 |. 833F 00 cmp dword ptr ds:[edi],0
0045E57A |. 8BF0 mov esi,eax ; 窗口句柄
0045E57C |. 74 28 je short PowerISO.0045E5A6 ; 标志位为0则返回
0045E57E |. 56 push esi ; /hWnd
0045E57F |. FF15 D444470>call dword ptr ds:[<&USER32.GetWindowTextL>; /GetWindowTextLengthA
0045E585 |. 8D48 01 lea ecx,dword ptr ds:[eax+1] ; 得到用户名或密码长度
0045E588 |. 51 push ecx
0045E589 |. 8B4D 10 mov ecx,dword ptr ss:[ebp+10]
0045E58C |. 50 push eax
0045E58D |. E8 EB72FFFF call PowerISO.0045587D ; 用于分配内存
0045E592 |. 50 push eax ; |Buffer
0045E593 |. 56 push esi ; |hWnd
0045E594 |. FF15 5445470>call dword ptr ds:[<&USER32.GetWindowTextA>; /GetWindowTextA
0045E59A |. 8B4D 10 mov ecx,dword ptr ss:[ebp+10] ; 取得用户名或密码
0045E59D |. 6A FF push -1
0045E59F |. E8 B172FFFF call PowerISO.00455855 ; 进入
0045E5A4 |. EB 0B jmp short PowerISO.0045E5B1
0045E5A6 |> 8B45 10 mov eax,dword ptr ss:[ebp+10]
0045E5A9 |. FF30 push dword ptr ds:[eax] ; /Arg2
0045E5AB |. 56 push esi ; |Arg1
0045E5AC |. E8 27FAFFFF call PowerISO.0045DFD8 ; /PowerISO.0045DFD8
0045E5B1 |> 5F pop edi
0045E5B2 |. 5E pop esi
0045E5B3 |. 5D pop ebp
0045E5B4 /. C2 0C00 retn 0C
这应该是一个子程序,所以根据栈回溯到上层调用:
0012F508 |0041D6E8 返回到 PowerISO.0041D6E8 来自 PowerISO.0045E565
0012F50C |0012F53C
于是来到了0041E6E8处,从这里可以看得出来它会以不同参数对上面的子程序进行调用:
0041D6D0 . 53 push ebx
0041D6D1 . 56 push esi
0041D6D2 . 8BF1 mov esi,ecx
0041D6D4 . 57 push edi
0041D6D5 . 8B7C24 10 mov edi,dword ptr ss:[esp+10]
0041D6D9 . 8D5E 5C lea ebx,dword ptr ds:[esi+5C] ; ===>[0012ffabc]==>thinkSJ
0041D6DC . 53 push ebx ; /Arg3
0041D6DD . 68 3A040000 push 43A ; |Arg2 = 0000043A
0041D6E2 . 57 push edi ; |Arg1
0041D6E3 . E8 7D0E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D6E8 . 6A 20 push 20
0041D6EA . 53 push ebx
0041D6EB . 57 push edi
0041D6EC . E8 D90F0400 call PowerISO.0045E6CA
0041D6F1 . 8D46 60 lea eax,dword ptr ds:[esi+60] ; ===>0012f434==>78999
0041D6F4 . 50 push eax ; /Arg3
0041D6F5 . 68 3B040000 push 43B ; |Arg2 = 0000043B
0041D6FA . 57 push edi ; |Arg1
0041D6FB . E8 650E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D700 . 8D4E 64 lea ecx,dword ptr ds:[esi+64] ; ===>0012f438==>45666
0041D703 . 51 push ecx ; /Arg3
0041D704 . 68 3C040000 push 43C ; |Arg2 = 0000043C
0041D709 . 57 push edi ; |Arg1
0041D70A . E8 560E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D70F . 8D56 68 lea edx,dword ptr ds:[esi+68] ; ===>0012f43c==>12333
0041D712 . 52 push edx ; /Arg3
0041D713 . 68 3D040000 push 43D ; |Arg2 = 0000043D
0041D718 . 57 push edi ; |Arg1
0041D719 . E8 470E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D71E . 8D46 6C lea eax,dword ptr ds:[esi+6C] ; ===>0012f440==>65444
0041D721 . 50 push eax ; /Arg3
0041D722 . 68 3E040000 push 43E ; |Arg2 = 0000043E
0041D727 . 57 push edi ; |Arg1
0041D728 . E8 380E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D72D . 83C6 70 add esi,70 ; ===>0012f444==>98777
0041D730 . 56 push esi ; /Arg3
0041D731 . 68 3F040000 push 43F ; |Arg2 = 0000043F
0041D736 . 57 push edi ; |Arg1
0041D737 . E8 290E0400 call PowerISO.0045E565 ; /PowerISO.0045E565
0041D73C . 5F pop edi
0041D73D . 5E pop esi
0041D73E . 5B pop ebx
0041D73F . C2 0400 retn 4
0041D742 90 nop
好了,在0041D6D0处下断,然后重新加载,在同样操作,断在了第一条指令处,单走几步进入0041D6E3处便出现了上面的上面的那段代码,
再进入0045E59F处:
00455855 /$ 56 push esi
00455856 |. 8BF1 mov esi,ecx
00455858 |. E8 37FBFFFF call PowerISO.00455394
0045585D |. 8B4424 08 mov eax,dword ptr ss:[esp+8] ; 取出第一个参数-1
00455861 |. 83F8 FF cmp eax,-1
00455864 |. 75 08 jnz short PowerISO.0045586E ; 不等于-1则跳
00455866 |. FF36 push dword ptr ds:[esi] ; /String
00455868 |. FF15 E442470>call dword ptr ds:[<&KERNEL32.lstr>; /lstrlenA
0045586E |> 8B0E mov ecx,dword ptr ds:[esi] ; 指向密码段或用户名
00455870 |. 8941 F8 mov dword ptr ds:[ecx-8],eax ; 保存长度,密码指针-8处
00455873 |. 8B0E mov ecx,dword ptr ds:[esi]
00455875 |. 5E pop esi
00455876 |. 802401 00 and byte ptr ds:[ecx+eax],0 ; 每一段结束处加0
0045587A /. C2 0400 retn 4
这个有一个特点就是子程序特别多,完全符合结构化程序设计的理念,带着我在内存中转来转去的,有几次差点跟飞了,这么得有点耐心才行,
似乎它并没有采用什么知名的算法,而是用的疲劳战术,嗨,跟它拼了!!
在0041D6E3处再进入来到:
0045E6CA /$ B8 CC274700 mov eax,PowerISO.004727CC
0045E6CF |. E8 F08FFEFF call PowerISO.004476C4 ; 建立异常堆栈
0045E6D4 |. 83EC 20 sub esp,20
0045E6D7 |. 56 push esi
0045E6D8 |. 57 push edi
0045E6D9 |. 8B7D 08 mov edi,dword ptr ss:[ebp+8] ; 指向一个标志位
0045E6DC |. 33F6 xor esi,esi
0045E6DE |. 3937 cmp dword ptr ds:[edi],esi
0045E6E0 |. 74 68 je short PowerISO.0045E74A
0045E6E2 |. 8B45 0C mov eax,dword ptr ss:[ebp+C] ; 指向用户名的指针
0045E6E5 |. 8B00 mov eax,dword ptr ds:[eax] ; 取用户名
0045E6E7 |. 8B40 F8 mov eax,dword ptr ds:[eax-8] ; 取出长度
0045E6EA |. 3B45 10 cmp eax,dword ptr ss:[ebp+10] ; 是否小于等于32位
0045E6ED |. 7E 5B jle short PowerISO.0045E74A
0045E6EF |. FF75 10 push dword ptr ss:[ebp+10] ; /<%d>
0045E6F2 |. 8D45 D4 lea eax,dword ptr ss:[ebp-2C] ; |
0045E6F5 |. 68 F4294900 push PowerISO.004929F4 ; |Format = "%d"
0045E6FA |. 50 push eax ; |s
0045E6FB |. FF15 C044470>call dword ptr ds:[<&USER32.wsprin>; /wsprintfA
如果用户名小于等于32位则会发送 EM_LIMITTEXT消息到文本框,然后返回。
从0041D6F1处可以看得出来,ESI是一个数组的首地址,有6个成员,第一个指向了用户名,其它的每个都指向了密码的一个部分:
0012FABC |00E56EE8 ASCII "thinkSJ"
0012FAC0 |00E576B8 ASCII "78999"
0012FAC4 |00E57578 ASCII "45666"
0012FAC8 |00E57708 ASCII "12333"
0012FACC |00E57758 ASCII "65444"
0012FAD0 |00E577A8 ASCII "98777"
从0041D6F1处可以看得出来密码每一部分的关系,从0041D73F返回后来到了00458A6B处:
00458A65 . FF90 8400000>call dword ptr ds:[eax+84] ; 得到用户名和密码
00458A6B . C745 08 0100>mov dword ptr ss:[ebp+8],1 ; 将第一个参数置为1
00458A72 . EB 27 jmp short PowerISO.00458A9B ; 返回1
00458A74 . B8 988A4500 mov eax,PowerISO.00458A98
00458A79 . C3 retn
再次返回后来到了0041D8D5处:
0041D8C8 . C74424 2C 00>mov dword ptr ss:[esp+2C],0
0041D8D0 . E8 41B10300 call PowerISO.00458A16 ; 得到用户名和密码
0041D8D5 . 8B46 5C mov eax,dword ptr ds:[esi+5C] ; 取出用户名
0041D8D8 . 8D7E 5C lea edi,dword ptr ds:[esi+5C] ; 用户名指针
0041D8DB . 68 C0574900 push PowerISO.004957C0 ; /Arg2 = 004957C0
0041D8E0 . 50 push eax ; |Arg1
0041D8E1 . E8 688A0200 call PowerISO.0044634E ; /PowerISO.0044634E
0041D8E6 . 83C4 08 add esp,8 ; 用来判断用户名是否为空
0041D8E9 . 85C0 test eax,eax
0041D8EB . 75 12 jnz short PowerISO.0041D8FF ; 用户名不能为空
0041D8ED . 50 push eax ; /Arg3
0041D8EE . 6A 40 push 40 ; |Arg2 = 00000040
0041D8F0 . 68 C0A74800 push PowerISO.0048A7C0 ; |Arg1 = 0048A7C0 ASCII "Please input the username."
0041D8F5 . E8 B70A0400 call PowerISO.0045E3B1 ; /PowerISO.0045E3B1
0041D8FA . E9 00010000 jmp PowerISO.0041D9FF
0041D8FF > 8B0F mov ecx,dword ptr ds:[edi] ; 取出用户名
0041D901 . 8379 F8 20 cmp dword ptr ds:[ecx-8],20 ; if(strlen(UserName) <=32)
0041D905 . 7E 13 jle short PowerISO.0041D91A ; 长度不能大于等于32位
0041D907 . 6A 00 push 0 ; /Arg3 = 00000000
0041D909 . 6A 40 push 40 ; |Arg2 = 00000040
0041D90B . 68 98A74800 push PowerISO.0048A798 ; |Arg1 = 0048A798 ASCII "The username length can not exceed 16."
0041D910 . E8 9C0A0400 call PowerISO.0045E3B1 ; /PowerISO.0045E3B1
0041D915 . E9 E5000000 jmp PowerISO.0041D9FF
0041D91A > 8D56 64 lea edx,dword ptr ds:[esi+64] ; ==>45666
0041D91D . 8D46 60 lea eax,dword ptr ds:[esi+60] ; ==>78999
0041D920 . 52 push edx ; 指向45666
0041D921 . 8D4C24 20 lea ecx,dword ptr ss:[esp+20]
0041D925 . 50 push eax ; 指向78999
0041D926 . 51 push ecx
0041D927 . E8 EE7C0300 call PowerISO.0045561A ; 00E577A8==>7899945666
0041D92C . 8D56 68 lea edx,dword ptr ds:[esi+68]
0041D92F . C64424 28 01 mov byte ptr ss:[esp+28],1
0041D934 . 52 push edx
0041D935 . 50 push eax
0041D936 . 8D4424 20 lea eax,dword ptr ss:[esp+20]
0041D93A . 50 push eax
0041D93B . E8 DA7C0300 call PowerISO.0045561A ; 00E577F8==>789994566612333
0041D940 . 8D4E 6C lea ecx,dword ptr ds:[esi+6C]
0041D943 . 8D5424 14 lea edx,dword ptr ss:[esp+14]
0041D947 . 51 push ecx
0041D948 . 50 push eax
0041D949 . 52 push edx
0041D94A . C64424 34 02 mov byte ptr ss:[esp+34],2
0041D94F . E8 C67C0300 call PowerISO.0045561A ; 00E57847==>78999456661233365444
0041D954 . 8D4E 70 lea ecx,dword ptr ds:[esi+70]
0041D957 . 8D5424 10 lea edx,dword ptr ss:[esp+10]
0041D95B . 51 push ecx
0041D95C . 50 push eax
0041D95D . 52 push edx
0041D95E . C64424 34 03 mov byte ptr ss:[esp+34],3
0041D963 . E8 B27C0300 call PowerISO.0045561A ; 00E57898==>7899945666123336544498777
0041D968 . 50 push eax ; eax ==>00E57898
0041D969 . 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
哈哈,,,已经能看到错误提示的字符串,想必是胜利离我们不远了,然而这一段全都是CALL XXXXXXXX的形式,又得脱一层皮了,将代码往
下翻一段就会看见:
0041D9DA /75 46 jnz short PowerISO.0041DA22
0041D9DC . |50 push eax ; /Arg3
0041D9DD . |6A 40 push 40 ; |Arg2 = 00000040
0041D9DF . |68 6CA74800 push PowerISO.0048A76C ; |Arg1 = 0048A76C ASCII "The username or serial number is invalid."
0041D9E4 . |E8 C8090400 call PowerISO.0045E3B1 ; /PowerISO.0045E3B1
0041D9E9 > |57 push edi
0041D9EA . |E8 A4770200 call PowerISO.00445193
以及这里:
0041DA22 > /57 push edi
0041DA23 . E8 6B770200 call PowerISO.00445193
0041DA28 . 55 push ebp
0041DA29 . E8 65770200 call PowerISO.00445193
0041DA2E . 83C4 08 add esp,8
0041DA31 . 6A 00 push 0 ; /Arg3 = 00000000
0041DA33 . 6A 40 push 40 ; |Arg2 = 00000040
0041DA35 . 68 48A74800 push PowerISO.0048A748 ; |Arg1 = 0048A748 ASCII "Thank you for your registration."
0041DA3A . E8 72090400 call PowerISO.0045E3B1 ; /PowerISO.0045E3B1
0041DA3F . E8 EC0A0000 call PowerISO.0041E530
种种迹象表明这里就是结束了,所有的罪恶都将在这里终结,很自然我们会将目光投向0041D9D0处的CALL:
0041D9AA . E8 3C7A0300 call PowerISO.004553EB
0041D9AF . 57 push edi ; 指向用户名
0041D9B0 . E8 ABC30100 call PowerISO.00439D60
0041D9B5 . 8BF8 mov edi,eax
0041D9B7 . 8D4424 10 lea eax,dword ptr ss:[esp+10]
0041D9BB . 50 push eax ; 指向密码
0041D9BC . E8 9FC30100 call PowerISO.00439D60
0041D9C1 . 83C4 08 add esp,8
0041D9C4 . 8BE8 mov ebp,eax
0041D9C6 . 85FF test edi,edi
0041D9C8 . 74 28 je short PowerISO.0041D9F2 ; 用户名为空则跳向错误
0041D9CA . 85ED test ebp,ebp
0041D9CC . 74 1B je short PowerISO.0041D9E9 ; 密码为空则跳向错误
0041D9CE . 55 push ebp
0041D9CF . 57 push edi
0041D9D0 . E8 6B0F0000 call PowerISO.0041E940 ;这里是核心
0041D9D5 . 83C4 08 add esp,8
0041D9D8 . 85C0 test eax,eax
看来这个CALL应该是最关键的,如果我们将0041D9DA处patch掉就能看到那令人心动的一幕:Thank you for your registration.但重启软件
就会发现NAG仍然存在,状态仍然是Unregistered.这一切都说明了什么?它有重启验证部分,那么它必然会有注册表或文件操作,
现在就进入那个核心的CALL:
0041E940 /$ 83EC 20 sub esp,20
0041E943 |. 56 push esi
0041E944 |. 57 push edi
0041E945 |. 8B7C24 2C mov edi,dword ptr ss:[esp+2C]
0041E949 |. 57 push edi
0041E94A |. E8 41FFFFFF call PowerISO.0041E890 ; 004F6064==>thinkSJ
0041E94F |. 8BF0 mov esi,eax ; PowerISO.004F6064
0041E951 |. 83C4 04 add esp,4
0041E954 |. 85F6 test esi,esi
0041E956 |. 75 06 jnz short PowerISO.0041E95E ; 不为0则跳
0041E958 |. 5F pop edi
0041E959 |. 5E pop esi
0041E95A |. 83C4 20 add esp,20
0041E95D |. C3 retn
0041E95E |> 8B4424 30 mov eax,dword ptr ss:[esp+30] ; 密码
0041E962 |. 6A 22 push 22
0041E964 |. 8D4C24 0C lea ecx,dword ptr ss:[esp+C]
0041E968 |. 50 push eax
0041E969 |. 51 push ecx
0041E96A |. E8 01930100 call PowerISO.00437C70 ; 0012EEB8==>C2 85 96 15 69 86 98 95 5D 03 ED AB E9 8A 9E 1A
0041E96F |. 8D5424 14 lea edx,dword ptr ss:[esp+14]
0041E973 |. 52 push edx
0041E974 |. 56 push esi ;用户名入栈
0041E975 |. E8 36FEFFFF call PowerISO.0041E7B0 ;又一个重点
0041E97A |. 83C4 14 add esp,14
0041E97D |. 85C0 test eax,eax
0041E97F 75 06 jnz short PowerISO.0041E987 ; 此处改为jmp,让值能保存进注册表
0041E981 |. 5F pop edi
0041E982 |. 5E pop esi
0041E983 |. 83C4 20 add esp,20
0041E986 |. C3 retn
0041E987 |> 8D4424 08 lea eax,dword ptr ss:[esp+8]
0041E98B |. 50 push eax ; 序列号加密结果
0041E98C |. 57 push edi ; 用户名
0041E98D |. E8 EEFCFFFF call PowerISO.0041E680 ; 将用户名+0012EEB8处写入注册表
0041E992 |. 83C4 08 add esp,8
0041E995 |. B8 01000000 mov eax,1
0041E99A |. 5F pop edi
0041E99B |. 5E pop esi
0041E99C |. 83C4 20 add esp,20
0041E99F /. C3 retn
所有判断都在这里进行,在0041E97D处会判断前一个调用的返回,如果不为0的话,就会来到0041E987处,这里CALL的功能主要是将注册写入
注册表,也就是说注册算法已经完成,当将0041E97F处改为JMP,那么不管注册信息正确与否,它都会被写入注册表,而且键的名字是USER:
0041E680 /$ 81EC 8800000>sub esp,88
0041E686 |. 8B9424 8C000>mov edx,dword ptr ss:[esp+8C]
0041E68D |. 53 push ebx
0041E68E |. 56 push esi
0041E68F |. 57 push edi
0041E690 |. 8BFA mov edi,edx
0041E692 |. 83C9 FF or ecx,FFFFFFFF
0041E695 |. 33C0 xor eax,eax
0041E697 |. 8D5C24 16 lea ebx,dword ptr ss:[esp+16]
0041E69B |. F2:AE repne scas byte ptr es:[edi]
0041E69D |. F7D1 not ecx
0041E69F |. 49 dec ecx ;取得用户名的长度
0041E6A0 |. 8BFA mov edi,edx
0041E6A2 |. 884C24 15 mov byte ptr ss:[esp+15],cl
0041E6A6 |. 83C9 FF or ecx,FFFFFFFF
0041E6A9 |. F2:AE repne scas byte ptr es:[edi]
0041E6AB |. F7D1 not ecx
0041E6AD |. 2BF9 sub edi,ecx
0041E6AF |. C64424 14 00 mov byte ptr ss:[esp+14],0
0041E6B4 |. 8BC1 mov eax,ecx
0041E6B6 |. 8BF7 mov esi,edi
0041E6B8 |. 8BFB mov edi,ebx
0041E6BA |. C1E9 02 shr ecx,2
0041E6BD |. F3:A5 rep movs dword ptr es:[edi],dword ptr>
0041E6BF |. 8BC8 mov ecx,eax
0041E6C1 |. 33C0 xor eax,eax
0041E6C3 |. 83E1 03 and ecx,3
0041E6C6 |. F3:A4 rep movs byte ptr es:[edi],byte ptr d>
0041E6C8 |. 8BFA mov edi,edx
0041E6CA |. 83C9 FF or ecx,FFFFFFFF
0041E6CD |. F2:AE repne scas byte ptr es:[edi]
0041E6CF |. 8B9424 9C000>mov edx,dword ptr ss:[esp+9C]
0041E6D6 |. F7D1 not ecx
0041E6D8 |. 49 dec ecx
0041E6D9 |. 8B02 mov eax,dword ptr ds:[edx]
0041E6DB |. 8BF1 mov esi,ecx
0041E6DD |. 83C6 02 add esi,2
0041E6E0 |. 8D4C34 14 lea ecx,dword ptr ss:[esp+esi+14]
0041E6E4 |. 894434 14 mov dword ptr ss:[esp+esi+14],eax
0041E6E8 |. 8B42 04 mov eax,dword ptr ds:[edx+4]
0041E6EB |. 8941 04 mov dword ptr ds:[ecx+4],eax
0041E6EE |. 8B42 08 mov eax,dword ptr ds:[edx+8]
0041E6F1 |. 8B52 0C mov edx,dword ptr ds:[edx+C]
0041E6F4 |. 8941 08 mov dword ptr ds:[ecx+8],eax
0041E6F7 |. 8D4424 10 lea eax,dword ptr ss:[esp+10]
0041E6FB |. 8951 0C mov dword ptr ds:[ecx+C],edx
0041E6FE |. 8D4C24 0C lea ecx,dword ptr ss:[esp+C]
0041E702 |. 50 push eax ; /pDisposition
0041E703 |. 51 push ecx ; |pHandle
0041E704 |. 6A 00 push 0 ; |pSecurity = NULL
0041E706 |. 68 06000200 push 20006 ; |Access = KEY_WRITE
0041E70B |. 6A 00 push 0 ; |Options = REG_OPTION_NON_VOLATILE
0041E70D |. 68 C0574900 push PowerISO.004957C0 ; |Class = ""
0041E712 |. 6A 00 push 0 ; |Reserved = 0
0041E714 |. 68 54A94800 push PowerISO.0048A954 ; |Subkey = "Software/PowerISO/"
0041E719 |. 68 01000080 push 80000001 ; |hKey = HKEY_CURRENT_USER
0041E71E |. FF15 1040470>call dword ptr ds:[<&ADVAPI32.RegCrea>; /RegCreateKeyExA
0041E724 |. 85C0 test eax,eax
0041E726 |. 75 27 jnz short PowerISO.0041E74F
0041E728 |. 83C6 10 add esi,10
0041E72B |. 8D5424 14 lea edx,dword ptr ss:[esp+14]
0041E72F |. 56 push esi ; /BufSize
0041E730 |. 52 push edx ; |Buffer
0041E731 |. 6A 03 push 3 ; |ValueType = REG_BINARY
0041E733 |. 50 push eax ; |Reserved
0041E734 |. 8B4424 1C mov eax,dword ptr ss:[esp+1C] ; |
0041E738 |. 68 4CA94800 push PowerISO.0048A94C ; |ValueName = "USER"
0041E73D |. 50 push eax ; |hKey
0041E73E |. FF15 0440470>call dword ptr ds:[<&ADVAPI32.RegSetV>; /RegSetValueExA
0041E744 |. 8B4C24 0C mov ecx,dword ptr ss:[esp+C]
0041E748 |. 51 push ecx ; /hKey
0041E749 |. FF15 1840470>call dword ptr ds:[<&ADVAPI32.RegClos>; /RegCloseKey
0041E74F |> 5F pop edi
0041E750 |. 5E pop esi
0041E751 |. 5B pop ebx
0041E752 |. 81C4 8800000>add esp,88
0041E758 /. C3 retn
改为JMP后运行但还是会看到NAG,但已经是注册状态了。
从这个大致流程便可以看得出来0041E975处的CALL又成瞩目的焦点,所以得进入一探虚实:
0041E7B0 /$ 83EC 40 sub esp,40
0041E7B3 |. 8B4424 44 mov eax,dword ptr ss:[esp+44] ; 用户名
0041E7B7 |. 56 push esi
0041E7B8 |. 8B7424 4C mov esi,dword ptr ss:[esp+4C]
0041E7BC |. 6A 1E push 1E
0041E7BE |. 8B08 mov ecx,dword ptr ds:[eax] ; thin
0041E7C0 |. 894C24 08 mov dword ptr ss:[esp+8],ecx ; 保存
0041E7C4 |. 8B50 04 mov edx,dword ptr ds:[eax+4] ; kSJ
0041E7C7 |. 895424 0C mov dword ptr ss:[esp+C],edx ; 保存
0041E7CB |. 8B48 08 mov ecx,dword ptr ds:[eax+8] ; thin
0041E7CE |. 894C24 10 mov dword ptr ss:[esp+10],ecx ; 保存
0041E7D2 |. 8B50 0C mov edx,dword ptr ds:[eax+C] ; kSJ
0041E7D5 |. 8BC6 mov eax,esi
0041E7D7 |. 895424 14 mov dword ptr ss:[esp+14],edx ; 保存
0041E7DB |. 8B08 mov ecx,dword ptr ds:[eax] ; ==159685C2
0041E7DD |. 894C24 18 mov dword ptr ss:[esp+18],ecx
0041E7E1 |. 8B50 04 mov edx,dword ptr ds:[eax+4] ; ==95988669
0041E7E4 |. 895424 1C mov dword ptr ss:[esp+1C],edx
0041E7E8 |. 8B48 08 mov ecx,dword ptr ds:[eax+8] ; ==ABED035D
0041E7EB |. 894C24 20 mov dword ptr ss:[esp+20],ecx
0041E7EF |. 8B50 0C mov edx,dword ptr ds:[eax+C] ; ==1A9E8AE9
0041E7F2 |. 8D4424 08 lea eax,dword ptr ss:[esp+8] ; ==thinkSJ
0041E7F6 |. 50 push eax
0041E7F7 |. 895424 28 mov dword ptr ss:[esp+28],edx
0041E7FB |. E8 60FFFFFF call PowerISO.0041E760 ; 重点
0041E800 |. 66:8B4E 0E mov cx,word ptr ds:[esi+E] ; cx = 1A9E ax = 5FE9只有相等才可以
0041E804 |. 25 FF7F0000 and eax,7FFF ; EAX & 7FFF
0041E809 |. 66:81E1 FF7F and cx,7FFF ; cx & 7FFF
0041E80E |. 83C4 08 add esp,8 ; 清栈
0041E811 |. 33D2 xor edx,edx
0041E813 |. 66:3BC1 cmp ax,cx ; 比较
0041E816 |. 0F94C2 sete dl ; dl = ((ax == cx) ? 1 : 0)
0041E819 |. 8BC2 mov eax,edx ; 返回0
0041E81B |. 5E pop esi
0041E81C |. 83C4 40 add esp,40
0041E81F /. C3 retn
在0041E7F6处会将用户名入栈,然后CALL 0041E760,再然后就测试返回值以确定究竟该返回多少,依据就是CX 和 AX的值,CX是在0041E800
处得到的,所以我们得重点看看AX生成过程,所以0041E7FB处的CALL还得进入:
0041E760 /$ 8B4424 08 mov eax,dword ptr ss:[esp+8] ; 用户名长度 * 2 = 1E
0041E764 |. 33C9 xor ecx,ecx ; ecx = 0
0041E766 |. 8BD0 mov edx,eax ; edx = 1E
0041E768 |. 48 dec eax ; eax-- = 1D
0041E769 |. 85D2 test edx,edx
0041E76B |. 74 2C je short PowerISO.0041E799 ; 等于零则跳
0041E76D |. 56 push esi ; 保存ESI的值,这个很重要
0041E76E |. 8D70 01 lea esi,dword ptr ds:[eax+1] ; 大循环次数 esi = 1E
0041E771 |. 8B4424 08 mov eax,dword ptr ss:[esp+8] ; 用户名 char name[] = "thinkSJ"
0041E775 |> 33D2 /xor edx,edx ; edx = 0; int nIndex = 0
0041E777 |. 8A30 |mov dh,byte ptr ds:[eax] ; 按位取用户名 char dh = name[nIndex]
0041E779 |. 33CA |xor ecx,edx ; ecx = ecx ^ edx
0041E77B |. 40 |inc eax ; nIndex++
0041E77C |. BA 08000000 |mov edx,8 ; 循环8次 edx = 8 用户名每一位都会处理8次
0041E781 |> F6C5 80 |/test ch,80 ; if((ch & 80) != 0)
0041E784 |. 74 0A ||je short PowerISO.0041E790 ; jmp 0041E790
0041E786 |. 03C9 ||add ecx,ecx ; ecx = ecx + ecx
0041E788 |. 81F1 2110000>||xor ecx,1021 ; ecx = ecx ^ 1021
0041E78E |. EB 02 ||jmp short PowerISO.0041E792
0041E790 |> D1E1 ||shl ecx,1 ; ecx = ecx << 1
0041E792 |> 4A ||dec edx ; 循环次数 edx--
0041E793 |.^ 75 EC |/jnz short PowerISO.0041E781 ; 继续处理,直到循环次数为0
0041E795 |. 4E |dec esi ; 大循环减1,继续处理下一个字符 esi--
0041E796 |.^ 75 DD /jnz short PowerISO.0041E775 ; 用户名会被处理2遍,每个被处理8次
0041E798 |. 5E pop esi ; ecx = CEBFE95F 弹出ESI
0041E799 |> 8AC1 mov al,cl ; al = 5F
0041E79B |. 33D2 xor edx,edx ; edx = 0
0041E79D |. 25 FF000000 and eax,0FF ; eax = eax & FF = 5F
0041E7A2 |. 8AD5 mov dl,ch ; dl = E9
0041E7A4 |. C1E0 08 shl eax,8 ; eax = eax << 8 = 5F00
0041E7A7 |. 03C2 add eax,edx ; eax = eax + edx = 5FE9
0041E7A9 /. C3 retn ; 这里将用户名进行运算,并取低两位再进行运算得到一个值
情况已经很明了了,对于thinkSJ这个用户名来说,它得到的结果是5FE9,而78999 45666 12333 65444 98777得到的结果就是1A9E,
这都是固定的了,较为遗憾的是没有看到序列号的加密过程。我已经用伪代码实现了它的用户名加密算法,在这种情况下想要逆推出一个
加密码结果为1A9E的用户名是不困难的。0041E813处的比较也是关键所在,
好了,现在再启动一次看看,已经没有NAG了,而且也已经注册给我了。