利用Python實現DGA域名檢測
前段時間爆發的利用永恆之藍進行勒索及xshell等事件,各大廠家都站在不同的角度分析了相應的事件及程序,對於對逆向不了解看著的確很吃力。上段時間看到宮總及袁哥都在講DNS對於分析這種攻擊的可行性。
永恆之藍和xshell事件有如下的特徵:
1. 永恆之藍中黑客預留了一個沒有註冊的域名,用於防護事件不受控制時,啟用該域名可以抑制事件的擴大
2. Xshell事件中黑客通過DNS的txt欄位進行傳輸數據與指令
兩起事件都有一個共同特徵就是利用DNS來進行事件的抑制與數據與指令的下發,這樣的話,針對這種類型的黑客攻擊與安全事件,我們可以站在底層網路來分析這事件。
利用永恆之藍進行勒索事件中黑客預留的域名是DGA域名,在某些條件下探測該DGA域名是否可以正常解析,若解析成功則不進行加密,若解析成功則不加密。
DGA一般都是通過硬編碼寫入到程序中,在沒有能力對其逆向的情況下,我們可以分析網路流量來分析DNS請求的DGA域名。這樣就需要了解哪些域名是DGA域名,這裡面有多種方法與思路:
1. 利用開放平台里的DGA庫,目前個人所了解的國內360在開放相應的數據,這個也是個人首推的選擇
2. DGA域名有個特徵,很多DGA並沒有註冊,黑客前期會生成大量的DGA域名,但是在某些情況下,如傳輸數據與命令或抑制事件時,會選擇性的註冊少量域名,這樣的話可以對DNS解析不成功的域名進行記錄,並將這些域名進行進行,若其沒有註冊,且域名很隨機可以判斷為疑似DGA域名。這裡面有大牛介紹過 http://www.freebuf.com/geek/144459.html
3. 深度學習檢測DGA域名,可參考http://www.freebuf.com/articles/network/139697.html
由於上面的方法二和方法三都有人實現了,這裡面我主要介紹方法一的實現。這個思路是這樣:通過監測網路流量(有條件的同學可以在大網環境下測試下),分析DNS的請求,一旦請求的DNS和DGA庫中的匹配,輸出相應的IP、埠,當然後期也可以做相應的統計與告警。
DGA庫網上找了有一些,個人了解的國內推薦360的開放DGA的數據,100W+的DGA數據,並且每天都有更新。有需要的同學可直接下載,http://data.netlab.360.com/feeds/dga/dga.txt
DNS檢測DGA實現的代碼如下:
在代碼實現過程中,本個DGA正常解析成功的IP地址也記錄了下來,DGA都有問題,那麼解析的IP基本上也不正常。在大網環境下可以記錄下相應的IP地址,在做Passive DNS時可以利用這些數據完善相應的庫。
考慮到DGA的文件每天都會更新,可以進行定時下載該文件。
測試後,效果如下:
這樣的話就實現了監測異常DGA記錄,內網環境下可以分析機器被黑或者中馬,大網環境下可以通過DNS側重了解區域安全態勢。
完整實現的代碼如下:
#coding:utf-8
import time
from scapy.all import *
from requests import *
conf.iface="Intel(R) Dual Band Wireless-AC 8260"
list=[]
dgalist = open("dga.txt","r")
dgalist = (dgalist.readlines())[18:]
for dga in dgalist :
list.append(dga.split(" ")[1])
data = set(list)
#Capture and Filter DGA
def capture(packet):
if packet:
i =0
for p in packet:
src = p[i][IP].src
dst = p[i][IP].dst
sport = p[i][UDP].sport
dport = p[i][UDP].dport
qr = str(p[i][DNS].qr)
rcode = str(p[i][DNS].rcode)
if "0" in qr:
qr = "Query"
qname = p[i][DNS].qd.qname
if type(qname) == bytes:
qname = (qname.decode("utf-8"))[:-1]
if qname in data:
print("[*] Found DGA Request:-->",src,sport,qr,qname)
if "1" in qr:
if "0" in rcode:
for j in range(10):
try:
qr = "Response"
rrname = p[j][DNS].an[j].rrname
rdata = p[j][DNS].an[j].rdata
if type(rrname) == bytes:
rrname = (rrname.decode("utf-8"))[:-1]
if type(rdata) == bytes:
rdata = (rdata.decode("utf-8"))[:-1]
if rrname in data:
print ("[*] Found DGA Response:-->",src,dst,qr,rrname,rdata,"
")
except Exception as e:
pass
i = i + 1
#update dgafile
def dgafileupdate():
url = "http://data.netlab.360.com/feeds/dga/dga.txt"
dgafile = get(url)
with open("./dga.txt","w") as f:
f.write(dgafile.text)
print("Download DGAFile Finished")
if __name__ == "__main__":
sniff(prn=capture,filter="udp port 53")
while True:
dgafileupdate()
time.sleep(86400)
本文原創作者:feiniao,本文屬於 FreeBuf 原創獎勵計劃,未經許可禁止轉載


※利用忘記密碼功能繞過Windows auth & BitLocker
※大疆的漏洞獎勵計劃來了,美國的「安全控訴」是不是可以歇會兒了?
※特別企劃 | 銀行業木馬黑產報告
※再見了,接碼平台:互動式語音驗證碼
TAG:FreeBuf |