打破SSS的技术封锁
时间:2007-04-29 来源:sense5
作者:彭硕 文章来源:黑客防线
最近实在是忙得不亦乐乎,一边埋头整理开学要上交的网络安全研究课题,一边在网上清理恶意网站。我的爱机也跟着我连轴转,没有多少休息的时间(还好我的机器是双Xeon的服务器,哈哈)。一天突然要用到SSS,立刻到黑白网络上Down了一个下来。结果一注册傻眼了,这个SSS 7.30竟然用上了网络认证,注册机生成的注册文件根本没法通过认证。忽然想起了05年《黑客在线》上有一个文章介绍SSS,翻来看看。这不看还好,看完了我差点没从6楼跳下去。杂志上面写着:“面对SSS无法破解的问题,小编采用虚拟机恢复大法……”我真的绝望了,看来N多的高人已经对这个SSS束手无策,我还能做什么呢?难道就只能这样了吗?
不过,我就是不信邪,非得要把这个SSS破掉不可。爆破?不太可能。其它的方法呢?我又不会(检讨一下,当年破解没学好)。干脆顺水推舟,由着SSS来算了。
灵巧的破解
首先,咱们还是老方法,用注册机生成一个注册文件。这个注册文件不是万能的,但是没有它是万万不能的。填写注册信息,按Generate就OK了。
好了,我们先不管它,让它一边凉快去(蝴蝶:不管它你生成它做什么?欠扁……),不是这个意思,等一会才能用到它啦。
在下一步之前,必须说一个东西:host文件。这个文件大家不会不知道吧?它的功能就是替代DNS进行域名解析,以便达到快速访问的目的,而且它在查询中的优先权要比网络上的任何DNS服务器都高。所以,只要改host文件,就可以“绑架”域名了。有很多朋友的机器,就算输入了正确的网址,也会上一些恶意网站,多半是这个文件被修改了的原因。需要注意,这个文件没有后缀名,位于%windir%\system32\drivers\etc下(Windows 2000/XP/2003系统),我们用记事本把这个文件打开,在里面加入这么一行:
127.0.0.1 www.safety-lab.com
这个www.safety-lab.com是SSS的官方站点,我们这么做就是为了欺骗SSS,让它连接到自己的机器上。因为经过我的Sniffer抓包发现,SSS在认证注册的时候,向http://www.safety-lab.com/update/db/keys.php提交了用户数据,并且在验证失败的时候,服务器端返回了一个1。有经验的朋友一眼就能看出来,SSS应该就是靠这个返回值来判断用户是否合法。也就是说,只要让这个值变成0,我们就可以成功注册了。
有人会问了,你怎么知道返回0,就是注册成功呢?不可能是别的数字吗?其实这个我也是猜一半,用社会工程学推导一半。其实,有时玩黑客并不一定只需要技术,还需要那么一点点的运气。
我们先来架设一个Web服务器,既然大家都是Windows用户,就用IIS好了(以下配置IIS的过程是在2003系统下实现的,2000/XP可能有所不同,请参考相关资料)。进入站点的属性—〉主目录—〉配置—〉映射,为.dat,.pl和.php三种后缀的文件添加映射。可执行文件框里,你的.asp文件是怎么设置的,不动就行。
这样做的目的是让这三种后缀名的文件,在IIS中都可以被当作ASP文件执行。其实,用别的语言实现也可以的,不过笔者只会ASP,没办法。设置好映射,我们来做几个文件,“忽悠忽悠”SSS。
最要紧的就是先注册了,否则什么功能也不能用。我们来分析一下这个keys.php的代码(其实是asp语言,这个keys.php在IIS中是被当成asp执行的):
[以下代码在keys.php中]
<%
Dim crc,name,founder ‘定义几个变量
founderr=true '为了防止程序出错,把控制错误的变量设为true
if request("crc")<>"" and request("name")<>"" then
founderr=false
end if
if founderr=false then
response.write "<html><body>0" '如果有输入,就返回一个值
response.end
end if
if founderr=true then
response.write "<html><body>1" '处理意外情况,防止SSS收不到返回值而挂掉。
response.end
end if
%>
这段代码很简单,只接受SSS发送上来的CRC和NAME两个变量,并返回一个值。大家可能看出来了,这个返回值<html>和<body>标签并没有结束,其实这不需要结束。因为我分过析Sniffer抓到的完整的数据包,发现就是这样的。也许是Safety-Lab故意做的一个陷阱吧,管他呢,能注册就OK。
我们的host文件不是已经改好了吗?那就把以上的代码保存成keys.php,放到你的IIS根目录下的/update/db/下(如果你的IIS根目录在E:\inetpub\wwwroot\,就放在E:\inetpub\wwwroot\update\db\)。然后我们打开SSS,导入注册文件,点击Done,看看,这不就完事了?
不过,单单破解,并不能满足我们的要求。如果现在你用在线升级,仍然会失败。而且还会把你刚注册上去的授权撤销。那怎么办呢?嘿嘿,接着往后看不就知道了?
破了软件不能升级,那就跟用D版XP一个感觉——很不爽。所以,又花了点功夫,把升级的限制也解除了,虽然不是很完善,但确实可以检测升级了。
还是老方法,用Sinffer把升级过程的包抓下来,分析一下。我们看到SSS的升级程序访问了以下页面:(前面都是http://www.safety-lab.com/,省略)
\update\db\keys.php 还是验证身份,阴险……
\update\sss\update.dat 这是一个数据文件(功能未知);
\update\db\getdbaudits.pl 一个数据引导文件,用于生成更新列表。
先拿出来分析,然后各个击破。这个keys.php刚才讲过了,我就不说了。update.dat文件好像是一个引索文件,据我的观察,它还是在变动的,但是它却是没有经过服务器的解析,可以直接下载下来,但为了保持数据最新,我们还是用动态的方法来处理吧。先看一段代码吧:
[以下代码在update.dat中]
<%
On error resume next '没别的意思,防止出错而以
Dim sURL
Dim Retrieval
Function GetURL(url)
Set Retrieval = Server.CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "GET", url, False, "", ""
.Send
GetURL = .ResponseText
End With
Response.BinaryWrite retrieval.responseBody '输出二进制到浏览器
Set Retrieval = Nothing
End Function
sURL = "http://safety-lab.com/update/sss/update.dat" '这个是要获取地址
Response.Write GetURL(sURl)
%>
这是ASP编程中很经典的一个函数的应用。这个页面的作用就是让IIS到另一个站点,取得一个页面,然后传回客户端。假设这个存在于主机A上的页面指向的是主机B上的内容,但是主机A的客户通过访问这个页面,就可以在主机A上看见主机B上的东西。但是,这个和普通网页中用JavaScript实现的页面重定向是不同的:JavaScript是让客户端重新定向,这个是以IIS为中介的服务器的重定向。
尤其是针对程序请求的页面的时候。因为程序不会识别那些由JavaScript语言组成的重定向语句,而这样的方法则不需要客户端的支持。哦,差点忘了一个事情,如果你的机器上有类似VisNetic Firewall一类的带有IDS功能的防火墙,把它关闭,否则会出错的。我当时调试的时候,这个update.dat怎么访问都有问题,后来发现是VisNetic的过滤功能把请求给过滤了。
再来看另外一个文件代码:
[以下代码在getdbaudits.pl中]
<%
On error resume next
Dim outformat,sURL
outformat=request("outformat")
Dim Retrieval
Function GetURL(url)
Set Retrieval = Server.CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "GET", url, False, "", ""
.Send
GetURL = .ResponseText
End With
Response.BinaryWrite retrieval.responseBody '输出二进制到浏览器
Set Retrieval = Nothing
End Function
sURL = "http://safety-lab.com/update/db/getdbaudits.pl?outformat=" & outformat
Response.Write GetURL(sURl)
%>
这个文件和上一个文件是大同小异,只不过多了一个对变量的处理而已。明白ASP的朋友一眼就能看出来,不太清楚的,向高人讨教一下吧。这个页面请求的应该是更新列表,不过不算太大,全部返回的数据也就有8-10KB。我们很快就能看到结果。
看见了吧?这就得到了更新列表了。我猜有很多人可能马上就要去点击那个Next按钮了吧?别着急,这里有问题需要处理。先兜个圈子,给大家说说我原来的思路,以下的过程仅仅是概念讲解,大家无需跟着操作。
我仍然是采用了Sniffer抓包的方法,看到升级程序访问了\update\db\getaudits.pl文件,而且后面足足跟了有825个字符的变量!我不在文章里列出来了,免得占用空间(详见光盘:数据.txt)。这些变量虽然多,但是交给程序处理还是游刃有余的。于是乎,我写了一个对应的页面:
[以下代码在getaudits.pl中]
<%
On error resume next
Dim outformat,sURL
outformat=Request.ServerVariables("Query_String")
'注释: Request.ServerVariables("Query_String")用于获得url中?后面的东西
Dim Retrieval
Response.Buffer = True
Function GetURL(url)
Set Retrieval = Server.CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "GET", url, False, "", ""
.Send
GetURL = .ResponseText
End With
Response.BinaryWrite retrieval.responseBody '输出二进制到浏览器
Set Retrieval = Nothing
End Function
sURL = "http://safety-lab.com/update/db/getaudits.pl?" & outformat
Response.Write GetURL(sURl)
%>
这个页面是用来下载更新数据的。由于这个请求的页面没有变量名称,网页后边直接加数据,我也很为难。后来上网查找资料,原来用Request.ServerVariables("Query_String")就可以直接获取“?”后面的东西了。从理论上讲,这个页面能完全返回升级程序需要的数据,但是理论总是有和实际脱离的地方。
SSS的升级程序为了防止网络故障而让程序长时间失去响应,设置了一个连接超时时间,大概在10秒钟左右。Safety-Lab.com是俄罗斯的网站,而且要下载的数据,动不动就要几百KB,以目前的连接速度,根本无法在10秒内完成下载(我用的可是2M的网通ADSL),这个页面还不支持所谓的即时传递数据(就是下一点,传一点),等IIS把所有的数据从Safety-Lab.com下载回来的时候,SSS的升级程序早就Timed Out了。当然,有连接俄罗斯网站速度超快的朋友,也可以用这个方法。
那我们怎么办?办法是有的。后来我发现,访问Safety-Lab上的getaudits.pl是不需要授权的。怎么样?想到了没有?在升级程序出现更新列表的时候(如图4),在host文件“127.0.0.1 www.safety-lab.com”的前面加上一个“#”(没有引号),这样Windows就会忽略这行内容了。接着,点击Next,就可以下载升级数据了。
可能有的朋友看过文章会注意到我所有页面里的转向地址都写的是:http://safety-lab.com/。大家感觉这个地址与前面有www的地址是一样的,可那时在通过DNS解析的时候,在host文件里即使差一个字符也不行的。我们在host文件里,设置的是http://www.safety-lab.com/解析到本地,并不等于http://safety-lab.com/也解析到本地。另外强调一点,SSS一般把升级数据下载到C:\Program Files\Common Files\Safety-lab\Download,你到SSS的安装目录是找不到的。
最后,我做对一些常见的问题做出解答,也方便大家参考。
问:我的.dat(或.pl,.php)为什么无法执行,或者只看到源文件?
答:没有给以上的文件在IIS中设置映射。把以上三种后缀名的映射,都设置成与.asp文件的映射一样,就可以了。如果你的IIS是6.0,请在Web服务扩展中开启asp支持。
问:我其它的设置完全正确,但是升级程序提示“Download Error, HTTP Error Disconnect server”是怎么回事?
答:由于safety-Lab.com是境外网站,访问并不一定畅通。连接失败是时有发生的事情,请再试一次或者断线重连。另外,请检查防火墙是否限制了IIS进程(w3wp.exe)访问网络。
问:为什么我无法注册SSS?为什么我一更新就提示我的注册无效?
答:这是因为你没有修改host文件造成的。按照上文修改host文件,并在升级程序显示更新列表后(如图4所示)再改回来。
到此为止,一个在业界内拥有相当高的评价的扫描器,就已经被完全破解了。真是很难理解,一款在反破解上下了大功夫的安全审计软件,却栽在这样的小技巧下(我记得MS的程序员管这个叫Hack)。我想,这也就是WTF说的“灵活的入侵思维”吧。其实,按照这个思路走下去,很多带有网络注册认证功能,一度被认为是“无法破解”的软件,也可以轻易地解除使用限制。
实用的防护
上面我已经讲述了如何利用Web注册认证的缺陷破解软件,我们也见识到了针对Web注册认证这种新兴注册手段的攻击方法。在下面的文章中,我来和大家谈谈怎样才能堵住Web注册上的缺口(以下文章中的代码实例,完全用ASP语言实现)。
从上文的事例看,判断注册信息合法性并返回一个值的Keys.php文件的页面,在设计存在一个很严重的逻辑错误。该设计者最可能的想法是这样的:
[以下代码在keys.asp中]
<!--#include file="conn.asp"-->
<%
Dim CRC,Name,err
err=true
if request("crc")<>"" and request("name")<>"" then
crc=request("crc")
name=request("name")
err=false
end if
if Not IsNumeric(crc) or Not IsNumeric(name)then
err=true
response.write "<html><body>1"
response.end
end if
if err=false then
Set rs=Server.CreateObject("ADODB.Recordset")
sql="select * from users where ucrc="&crc &" and uname = " & name '我们假设name和crc的数据都存储在数据库中
rs.open sql,conn,1,1
if rs("id")="" then
response.write "<html><body>1"
response.end
else
response.write "<html><body>0"
response.end
end if
end if
%>
一切看起来似乎很完美了吧?我所实现的其实可能还不如人家,不过你还是可以看到过滤SQL Injection攻击的语句。但是,作为判断标示符返回的两个结果,0和1就是非常不恰当的选择了。一般有经验的攻击者,在得到错误时返回的“1”后,很自然地就会联想到正确的时候会返回“1”,这样,这道网络认证的保护就是形同虚设了。
最好的办法就是:首先,必须修改你的程序,不要让它仅仅靠判断返回的是“0”还是“1”来判断用户是否合法。你可以给程序添加一个模块,把Web验证服务器的返回信息处理一下,如果能和用户提交的信息形成某种特定的关系,就判断为合法用户,反之则为非法。
其次,你的Web验证服务器端的页面,也必须做更改。你的Web验证服务器,可以按照以下步骤处理用户提交的信息:
1. 把用户提交的信息放到数据库中查询;
2. 如果查询不到相关的数据,则直接返回一个失败代码(如“1”);
3. 如果查询成功,则把用户提交的数据做一个处理,并返回给客户端;
4. 为了防止用户滥用正版注册号,每个注册号应设定一个注册次数限制(如10次)。
最后,你需要给你的软件加以强大的反破解保护,让一般的Cracker根本对你的软件无从下手。否则,就算你的Web注册认证如何严密,都毫无意义了。因为,Cracker会直接通过修改程序,跳过你的Web注册认证。
另外,升级也是一个需要保护的地方。你可以把上边验证用户的代码,添加到显示更新列表的程序里,这样既不会占用你太多的资源,又可以阻止非授权的用户获取更新列表。客户的升级程序,在获得升级列表之前,也向验证服务器递交一下用户的身份信息。
其实,按照我上面所述的方法来看,实现并不十分复杂。这里面也没有太深奥的技术可言。不过,就是这一点点的小技巧,也可以为难住一大批想要吃白饭的人呢(我可不是指研究破解的同行)。