/* This script originally lived at http://evolvedcode.net/ For the original version of this script and a wide variety of other code and scripts, please visit the site. - EvolvedCode.net staff Changes: 26.10.2002 Included simplified dictionary loader Included smart temporary table deletion */ --Check if any of our temporary objects already exist IF (OBJECT_ID('tempdb..#tLogins') IS NOT NULL) DROP TABLE #tLogins; IF (OBJECT_ID('tempdb..#tBruteDict') IS NOT NULL) DROP TABLE #tBruteDict; IF (OBJECT_ID('tempdb..#tUserDict') IS NOT NULL) DROP TABLE #tUserDict; GO --Variables for use throughout the script DECLARE @Counter INT; DECLARE @WordList VARCHAR(1000); SET @WordList = 'E:\Wordlists\QuickDict.txt'; SET NOCOUNT ON --Create tables to hold temporary data CREATE TABLE #tLogins( [UID] INT IDENTITY(1,1) NOT NULL, [Login] SYSNAME NOT NULL, [SID] VARBINARY(85) NOT NULL, [Password] SYSNAME NULL, [PasswordHash] VARBINARY(256) NULL, [IsAdmin] BIT DEFAULT(0) NOT NULL, [BlankPass] BIT DEFAULT(0) NOT NULL, [SamePass] BIT DEFAULT(0) NOT NULL, [BrutePass] BIT DEFAULT(0) NOT NULL ); CREATE TABLE #tBruteDict( [RawText] SYSNAME NOT NULL ); CREATE TABLE #tBruteCS( [RawText] SYSNAME NOT NULL ); CREATE TABLE #tUserDict( [RawText] SYSNAME NOT NULL ); --Create a list of the regular (non-nt) users INSERT INTO #tLogins( [SID], [Login], [IsAdmin], [PasswordHash] ) SELECT L.[sid], L.[name], CASE WHEN L.[sysadmin] = 1 OR L.[securityadmin] = 1 OR L.[serveradmin] = 1 OR L.[setupadmin] = 1 OR L.[processadmin] = 1 OR L.[diskadmin] = 1 THEN 1 ELSE 0 END, LX.[password] FROM [master]..[syslogins] AS L LEFT JOIN [master]..[sysxlogins] LX ON L.sid = LX.sid WHERE L.[isntname] = 0; --Identify users with blank passwords UPDATE #tLogins SET [BlankPass] = 1 FROM #tLogins WHERE [PasswordHash] IS NULL; --Identify users with password = username UPDATE #tLogins SET [SamePass] = 1, [Password] = [Login] WHERE PWDCOMPARE( [Login], [PasswordHash] ) = 1; --Identify users with one or two character (ASCII 0-255) passwords SET @Counter = 0; WHILE @Counter <= 255 BEGIN INSERT INTO #tBruteCS( [RawText] ) VALUES( CHAR(@Counter) ); SET @Counter = @Counter + 1; END INSERT INTO #tBruteDict( [RawText] ) SELECT Src.[RawText] FROM #tBruteCS AS Src INSERT INTO #tBruteDict( [RawText] ) SELECT Src.[RawText]+New.[RawText] FROM #tBruteDict AS Src, #tBruteCS AS New; DROP TABLE #tBruteCS; UPDATE #tLogins SET [BrutePass] = 1, [Password] = Dict.[RawText] FROM #tLogins AS Src LEFT JOIN #tBruteDict AS Dict ON PWDCOMPARE( Dict.[RawText], Src.[PasswordHash] ) = 1 WHERE Dict.[RawText] IS NOT NULL AND Src.[BrutePass] = 0 AND Src.[BlankPass] = 0 AND Src.[SamePass] = 0; DROP TABLE #tBruteDict; --Identify users with passwords from our dictionary IF @WordList IS NOT NULL BEGIN BULK INSERT #tUserDict FROM 'E:\WordLists\QuickDict.txt'; UPDATE #tLogins SET [BrutePass] = 1, [Password] = Dict.[RawText] FROM #tLogins AS Src LEFT JOIN #tUserDict AS Dict ON PWDCOMPARE( Dict.[RawText], Src.[PasswordHash] ) = 1 WHERE Dict.[RawText] IS NOT NULL AND Src.[BrutePass] = 0 AND Src.[BlankPass] = 0 AND Src.[SamePass] = 0; END DROP TABLE #tUserDict; --Reset nocount SET NOCOUNT OFF --Report any users whose logins were weak SELECT [Login] AS [Username], ISNULL( [Password], '-- currently unknown --' ) AS [Password], CASE WHEN [BlankPass] = 1 OR [SamePass] = 1 OR [BrutePass] = 1 THEN 1 ELSE 0 END AS [Cracked?], [IsAdmin] AS [Admin User?], [BlankPass] AS [Blank Password?], [SamePass] AS [Username = Password?], [BrutePass] AS [Password Bruteforced?] FROM #tLogins ORDER BY [Login]; DROP TABLE #tLogins;