破除Hide The IP的网络验证
文/图 Layper
玩了那么久的**,还没有认真的尝试网络验证**。一直都觉得网络**很麻烦,搞定Hide The IP这款软件给了我很大的信心,只要方法得当,**此类软件也是非常简单的。下面大家就看我是怎么*****它的。
准备工具:OD、PEiD、EasyPHP、dede等。
使用dede生成MAP文件
首先用PEiD侦壳,非常好,竟然没有加壳,免去了脱壳的麻烦,如图1所示。这款软件是用Delphi 7.0编写的。我们用**Delphi的利器dede来“看看”它。
图1
用dede载入Hide The IP后,dede开始处理程序,处理完成之后,会跳出“转储成功”消息框,按“确定”按钮就会出现如图2所示的提示框,点击“yes”。因为这个功能是帮助我们扩展分析Delphi程序的单元和类及其他,获取更多的信息对我们是大有益处的,所以要选择“yes”。同样,后面的“识别标准VCL过程”也是选择“yes”,这也是非常重要的,如图3所示。
图2
图3
dede是专门为逆向Delphi(除.net程序外)而设计的,对Delphi程序的符号、函数识别率很高(dede这个功能只有IDA能与之一较天下)。本文dede是用来辅助OD的,如果一开始就用OD来**,你会发觉困难多了。
dede经过较长时间分析后,终于出现了如图4所示的结果,点击“Done”之后,接下来就是用dede为OD分析做准备了:导出“map”文件,如图5所示。map文件能够帮助我们创建包含有用的识别信息,包括事件处理和控件参考。在OD中,我们使用插件“GODUP”即可导入,如此在OD中进行分析就不会困难了。
图4
图5
使用OD分析软件
这款软件是有时间限制的,输入假的注册信息后,会出现如图6所示的错误提示,在OD中点击右键,选择“查找->所有参考文本串”,会找到以下的错误提示信息:
图6
文本字串参考位于 HideTheI:CODE,条目 6502
地址=004EEECB
文本字串=ASCII "Invalid registration."
双击来到CPU窗口处:
004EEECB . B>mov ecx, 004EF118 ;ASCII "Invalid registration.来到这里
向上看找到是从004EED31分支跳转到这个出错的,所以断点应该在004EED31之前,我下在004EEC58处。
004EEC58 . 5>push ebp ;在这里下断
004EEC59 . 8>mov ebp, esp
004EEC5B . B>mov ecx, 8
如果大家跟踪过Delphi文件就知道,Delphi程序有许多库函数,如果人工识别是非常困难的,而用前面的map文件来解析反汇编代码,则会使它更具可读性。
在OD中选择“插件->GODUP Plugin->Map Loader”中的“Load labels”和“Load comments”,载入刚才用dede生成的“hide the ip.map”文件,这样GODUP插件就会导入map文件中解析出来的标签和注释了。我们来分析一下解析后的代码。
004EEC58 >push ebp ; <[email protected]
;控件Button1的Click函数开始
004EEC59 mov ebp, esp
004EEC5B mov ecx, 8
004EEC60 push 0
004EEC62 push 0
004EEC64 dec ecx
004EEC65 jnz short 004EEC60
004EEC67 push ebx
004EEC68 push esi
004EEC69 push edi
004EEC6A mov ebx, eax
004EEC6C xor eax, eax
004EEC6E push ebp
004EEC6F push <->[email protected]>
004EEC74 push dword ptr fs:[eax]
004EEC77 mov dword ptr fs:[eax], esp
004EEC7A mov dl, 1
004EEC7C mov eax, dword ptr [416D8C]
004EEC81 >call 00403B38 ; ->System.TObject.Create(TObject;Boolean);
004EEC86 mov dword ptr [ebp-4], eax
004EEC89 mov dl, 1
004EEC8B mov eax, dword ptr [416D8C]
004EEC90 >call 00403B38 ; ->System.TObject.Create(TObject;Boolean);
004EEC95 mov esi, eax
004EEC97 lea edx, dword ptr [ebp-C]
004EEC9A >mov eax, dword ptr [ebx+300>; *TForm3.Edit1:TEdit
004EECA0 >call 004478D8 ;->Controls.TControl.GetText(TControl):TCaption;
;得到E-mail的邮箱地址[email protected]
004EECA5 mov ecx, dword ptr [ebp-C]
004EECA8 lea eax, dword ptr [ebp-8]
004EECAB mov edx, 004EEFEC;ASCII "email="
004EECB0 >call 00404C48; ->[email protected]
;把“email=”和“[email protected]”连接成“email= [email protected]”
004EECB5 mov edx, dword ptr [ebp-8]
004EECB8 mov eax, dword ptr [ebp-4]
004EECBB mov ecx, dword ptr [eax]
004EECBD >call dword ptr [ecx+38] ; ->TStringList.Add(string)
004EECC0 lea edx, dword ptr [ebp-14]
004EECC3 >mov eax, dword ptr [ebx+304>;*TForm3.Edit2:TEdit
004EECC9 >call 004478D8 ; ->Controls.TControl.GetText(TControl):TCaption;
;获取Serial key的***1357924680
004EECCE mov ecx, dword ptr [ebp-14]
004EECD1 lea eax, dword ptr [ebp-10]
004EECD4 mov edx, 004EEFFC ;ASCII "ser="
004EECD9 >call 00404C48 ;->[email protected]
;连接字符串成ser=1357924680
004EECDE mov edx, dword ptr [ebp-10]
004EECE1 mov eax, dword ptr [ebp-4]
004EECE4 mov ecx, dword ptr [eax]
004EECE6 >call dword ptr [ecx+38] ;->TStringList.Add(string)
004EECE9 xor eax, eax
004EECEB push ebp
004EECEC push <->[email protected]>
004EECF1 push dword ptr fs:[eax]
004EECF4 mov dword ptr fs:[eax], esp
004EECF7 lea eax, dword ptr [ebp-18]
004EECFA push eax
004EECFB >mov eax, dword ptr [ebx+31C>;*TForm3.ip1:TIdHTTP
;注意这里开始使用TIdHTTP控件了,这个是我判断它用网络验证的依据
004EED01 mov ecx, dword ptr [ebp-4]
004EED04 mov edx, 004EF00C ;ASCII http://www.hide-the-ip.com/checkreg.php
;这个是验证网页了
004EED09 call 0048077C
004EED0E mov edx, dword ptr [ebp-18]
;在这里多下个断点,因为004EED09处会引起一个异常,异常之后Shift+F9返回到这里,返回的字符串是“00FE0894, (ASCII "no")”
004EED11 mov eax, esi
004EED13 mov ecx, dword ptr [eax]
004EED15 >call dword ptr [ecx+2C];->TStringList.SetTextStr(string)
004EED18 lea ecx, dword ptr [ebp-1C]
004EED1B xor edx, edx
004EED1D mov eax, esi
004EED1F mov edi, dword ptr [eax]
004EED21 >call dword ptr [edi+C];->TStringList.Get(Integer)
004EED24 mov eax, dword ptr [ebp-1C];00FFC514, (ASCII "no")
004EED27 mov edx, 004EF03C ; ASCII "yes"
004EED2C >call 00404D48 ; ->[email protected];
;比较字符串是否是yes
004EED31 jnz 004EEEC4 ;不是则跳到出错
如果还未能确定是否有在线验证,保持前面OD设置的两个断点004EEC58和004EED0E,输入信息运行,再次下断在004EED0E后,我们在OD处下函数断点:Bp recv。
Recv是常用的网络**断点函数,recv()函数原型为:int recv(int sockfd,void *buf,int len,unsigned int flags);,其中Sockfd是接受数据的socket描述符;buf 是存放接收数据的缓冲区;len是缓冲的长度;Flags也被置为0。Recv()返回实际上接收的字节数,当出现错误时,返回-1并置相应的errno值。
F9运行后断在下面的代码处。
71A2615A > 8BFF mov edi, edi
71A2615C 55 push ebp
71A2615D 8BEC mov ebp, esp
71A2615F 83EC 10 sub esp, 10
71A26162 53 push ebx
Recv成功断在了71A2615A,这时我们看OD右下方的堆栈窗口。
0012F4DC 0046DAC2 /CALL到recv来自HideTheI.0046DAC0
0012F4E0 00000260 |Socket = 260
0012F4E4 001E4008 |Buffer = 001E4008
;此为缓冲区地址,以你的机子为准
0012F4E8 00008000 |BufSize = 8000 (32768.)
0012F4EC 00000000 \Flags = 0
在OD命令行输入“DD 001E4008”,然后保持recv断点不变,“Alt+F9”返回,这时可以看到OD左下方的数据窗口的数据变为如下所示的代码。
001E4008 50545448 HTTP
001E400C 312E312F /1.1
001E4010 30303220 200
001E4014 0D4B4F20 OK.
往下拉动数据窗口可以看到这样的代码:
001E4108 746E6F43 Cont
001E410C 2D746E65 ent-
001E4110 65707954 Type
001E4114 6574203A : te
001E4118 682F7478 xt/h
001E411C 0D6C6D74 tml.
001E4120 6E0A0D0A ...n
001E4124 0000006F o...
001E4128 00000000 ....
出现字符串“no”了,之后就会回到下一个断点004EED0E了。
从上面的代码我们可以看出:这款软件使用了网络验证;网络验证的页面是http://www.hide-the-ip.com/checkreg.php,连接起注册信息则为http://www.hide-the-ip.com/checkreg.php?email=layper%4012%2Ecom&ser=1357924680;验证之后要返回“yes”,如果是“no”则出错。
伪装服务器和验证页面
网络验证**主要是要找出主机的地址和验证页面,然后用一台机器来伪装成验证主机。这款软件的**我用伪装数据包来**,即先伪装服务器和验证页面获取伪装的数据包后,恢复原先的网络验证,在程序中直接修改数据包来进行**的。
既然知道了验证网址是www.hide-the-ip.com和验证页面是checkreg.php,我们就把自己的机器伪装成www.hide-the-ip.com,建立一个文件checkreg.php,把网络验证改为本机验证。一般伪装主机分三步走。
1)修改Hosts文件
在你的系统盘的路径“WINDOWS\system32\drivers\etc”下找到hosts,用记事本打开后,在里面添加一行:
127.0.0.1 www.hide-the-ip.com
修改之后保存,这样你的机器就会把www.hide-the-ip.com解析为自己的机器了,登录www.hide-the-ip.com就是登录本机了。
2)建立验证页面
用记事本新建一个文件,在里面输入:yes,保存为checkreg.php,验证页面就构造好了。
3)架构服务器
这款软件使用的页面是PHP文件,所以我们要在本机架构一台PHP服务器。在网上下载一个EasyPHP,把我们的checkreg.php文件保存到EasyPHP所在目录中的www文件夹中,接着运行EasyPHP.exe,单击“Apache”,选择“开始”,如图7所示,到这里我们就伪装完成了。
图7
再次跟踪验证部分
重新把Hide The IP载入OD之后,输入注册信息,再次断在004EEC58,F9或Shift+F9运行到断点004EED0E,我们再来看看是否有变化。
004EED0E .>mov edx, dword ptr [ebp-18]
;前面是“no”,现在是“yes”
004EED11 .>mov eax, esi
004EED13 .>mov ecx, dword ptr [eax]
004EED15 > .>call dword ptr [ecx+2C] ;->TStringList.SetTextStr(string)
004EED18 .>lea ecx, dword ptr [ebp-1C]
004EED1B .>xor edx, edx
004EED1D .>mov eax, esi
004EED1F .>mov edi, dword ptr [eax]
004EED21 > .>call dword ptr [edi+C] ; ->TStringList.Get(Integer)
004EED24 .>mov eax, dword ptr [ebp-1C] ;注意这里00FFD33C, (ASCII "yes")
004EED27 .>mov edx, 004EF03C ;ASCII "yes"
004EED2C > .>call 00404D48 ;->[email protected];
004EED31 .>jnz 004EEEC4 ;这里不再跳转到出错
原本以为这样就可以完成**了,谁知下面又出现了一个拦路虎。
004EED37 lea edx, dword ptr [ebp-20]
004EED3A >mov eax, dword ptr [ebx+300] ;*TForm3.Edit1:TEdit
004EED40 >call 004478D8 ;->Controls.TControl.GetText(TControl):TCaption;
004EED45 mov eax, dword ptr [ebp-20] ;00FFD450, (ASCII "[email protected]")
004EED48 push eax
004EED49 mov eax, dword ptr [4FAC70]
004EED4E mov eax, dword ptr [eax]
004EED50 mov ecx, 004EF048 ;ASCII "Email"
004EED55 mov edx, 004EF058 ; ASCII "Options"
004EED5A mov edi, dword ptr [eax]
004EED5C call dword ptr [edi+4]
004EED5F lea edx, dword ptr [ebp-24]
004EED62 >mov eax, dword ptr [ebx+304] ;*TForm3.Edit2:TEdit
004EED68 >call 004478D8 ;->Controls.TControl.GetText(TControl):TCaption;
004EED6D mov eax, dword ptr [ebp-24] ;01000F58, (ASCII "1357924680")
004EED70 push eax
004EED71 mov eax, dword ptr [4FAC70]
004EED76 mov eax, dword ptr [eax]
004EED78 mov ecx, 004EF068 ;ASCII "Serial"
004EED7D mov edx, 004EF058 ;ASCII "Options"
004EED82 mov edi, dword ptr [eax]
004EED84 call dword ptr [edi+4]
004EED87 lea ecx, dword ptr [ebp-28]
004EED8A mov edx, 1
004EED8F mov eax, esi
004EED91 mov edi, dword ptr [eax]
004EED93 >call dword ptr [edi+C] ;->TStringList.Get(Integer)
;这里出现异常
在004EED93处出现异常,不能到达成功的消息框。如果没有前面导入的map文件注释,我们可能就会在这里卡住了。
注意观察004EED93的注释“TStringList.Get(Integer)”,应该是获取字符串。往上看代码004EED21,也用了“TStringList.Get(Integer)”,这个是获取验证页面字符串“yes”的函数,那么004EDD93会不会也是用来获取验证页面字符串的函数,由于获取不到而出现异常导致出错呢?于是我把验证文件checkreg.php修改为:
yes
“黑防专用”
保存好之后再次输入信息验证,终于跳出了可爱的消息框,如图8所示。
图8
看看这时候在文件夹里生成了什么?生成了options.ini文件,其内容如下:
[Options]
[email protected]
Serial=1357924680
Expire="黑防专用"
Name=layper
经过上面的**过程,大家应该明白**有网络验证的软件有以下几点关键:
1) 寻找验证的主机域名和验证页面。
2) 改造host文件和架构服务器,使域名解析到相应IP(通常是改为本地主机)。
3) 根据程序提示构造验证页面。
4)网络验证的API断点常用bp recv,以获取缓冲区读取的数据。
Hide The IP是用Delphi编写的软件,**Delphi除了选择dede之外,还可以用导入map文件到OD的方法来降低分析代码的难度。顺便提一点,Hide The IP除了用网络验证方法**之外,用拦截ini函数方法构造ini文件**应该也是可行的,大家可以自己试试看!