Power***3.2的初步分析

前几天下载了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了,而且也已经注册给我了。

 

 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值