In [1]:
import pyshark
import pandas as pd
In [2]:
# Read packet capture and set display filter to only retrieve TDS traffic
cap = pyshark.FileCapture("ms-sql-tds-rpc-requests.pcap",display_filter="tds")
In [3]:
tds_types = {
"1": "SQL Batch",
"2": "Pre-TDS7 Login",
"3": "RPC",
"4": "Tabular result",
"5": "unused",
"6": "Attention signal",
"7": "Bulk load data",
"8": "Federated authentication token",
"9": "unused",
"10": "unused",
"11": "unused",
"12": "unused",
"13": "unused",
"14": "Transaction manager request",
"15": "unused",
"16": "TDS7 Login",
"17": "SSPI",
"18": "Pre-login"
}
procedure_codes = {
"1": "Sp_Cursor",
"2": "Sp_CursorOpen",
"3": "Sp_CursorPrepare",
"4": "Sp_CursorExecute",
"5": "Sp_CursorPrepExec",
"6": "Sp_CursorUnprepare",
"7": "Sp_CursorFetch",
"8": "Sp_CursorOption",
"9": "Sp_CursorClose",
"10": "Sp_ExecuteSql",
"11": "Sp_Prepare",
"12": "Sp_Execute",
"13": "Sp_PrepExec",
"14": "Sp_PrepExecRpc",
"15": "Sp_Unprepare"
}
cap_data = []
for pkt in cap:
pkt_data = {}
try:
pkt_data["ts"] = pkt.sniff_timestamp
pkt_data["src_ip"] = str(pkt.ip.src)
pkt_data["dst_ip"] = str(pkt.ip.dst)
pkt_data["src_port"] = int(pkt.tcp.srcport)
pkt_data["dst_port"] = int(pkt.tcp.dstport)
pkt_data["tds_type"] = int(pkt.tds.type)
pkt_data["tds_type_str"] = str(tds_types.get(pkt.tds.type))
if pkt_data["tds_type"] == 1:
# This is a SQL batch type
pkt_data["query"] = str(pkt.tds.query)
elif pkt_data["tds_type"] == 3:
# This is a remote procedure call
# Look for a procedure ID
try:
if procedure_codes.get(pkt.tds.rpc_proc_id) is not None:
pkt_data["rpc_proc_id"] = procedure_codes.get(pkt.tds.rpc_proc_id)
else:
pkt_data["rpc_proc_id"] = int(pkt.tds.rpc_proc_id)
except:
pass
# Look for a procedure name
try:
pkt_data["rpc_proc_name"] = str(pkt.tds.rpc_name)
except:
pass
else:
# Not a RPC or query
pass
cap_data.append(pkt_data)
except Exception as e:
print("Exception: " + str(e))
In [4]:
# Convert the data into a pandas dataframe
df = pd.DataFrame(cap_data).fillna(value="")
#df
df[['ts','src_ip','src_port','dst_ip','dst_port','tds_type','tds_type_str','query','rpc_proc_id','rpc_proc_name']]
Out[4]:
In [5]:
# Output and count all queries in the dataset
df['query'].value_counts()
Out[5]:
In [6]:
# Look at named remote procedure call functions called
df['rpc_proc_name'].value_counts()
Out[6]:
In [7]:
# Look at remote procedure call function values
df['rpc_proc_id'].value_counts()
Out[7]:
In [8]:
df.loc[df['rpc_proc_name'] == "p_GetBogusData"][['ts','src_ip','dst_ip','rpc_proc_name']]
Out[8]:
In [9]:
df2 = df.loc[(df['rpc_proc_name'] == "p_SetBogusSample") | (df['rpc_proc_name'] == "sp_executesql")]
df2[['ts','src_ip','dst_ip','rpc_proc_name']]
Out[9]: