import dpkt import argparse import socket # 定义阈值,用于判断是否存在攻击行为,初始值设为500,后续可通过命令行参数修改 THRESH = 500 # 函数功能:在给定的pcap数据包中查找是否有下载LoIc相关文件(.zip格式且包含'loic')的行为 # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def findDownload(pcap): for (ts, buf) in pcap: try: # 从以太网帧数据缓冲区解析出以太网数据包对象 eth = dpkt.ethernet.Ethernet(buf) # 获取以太网数据包中的IP数据部分 ip = eth.data # 将IP源地址从网络字节序转换为点分十进制格式 src = socket.inet_ntoa(ip.src) # 获取IP数据包中的TCP数据部分 tcp = ip.data # 判断是否是TCP协议类型的数据包 if isinstance(tcp, dpkt.tcp.TCP): # 尝试从TCP数据部分解析出HTTP请求对象 http = dpkt.http.Request(tcp.data) # 判断HTTP请求方法是否为GET if http.method == 'GET': # 将请求的URI转换为小写字母形式 uri = http.uri.lower() # 判断URI中是否包含.zip并且包含'loic',如果是则打印相应提示信息 if '.zip' in uri and 'loic' in uri: print('[!] ' + src + ' Downloaded LoIc.') except Exception as e: print(f"Error in findDownload at time {ts}: {e}") # 函数功能:在给定的pcap数据包中查找是否存在DDoS蜂巢命令(通过特定端口和特定关键字判断) # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def findHivemind(pcap): for (ts, buf) in pcap: try: eth = dpkt.ethernet.Ethernet(buf) ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) tcp = ip.data if isinstance(tcp, dpkt.tcp.TCP): # 获取TCP目标端口号和源端口号 dport = tcp.dport sport = tcp.sport # 判断目标端口或源端口是否为6667(特定的用于识别的端口号) if dport == 6667 or sport == 6667: # 判断TCP数据中是否包含特定关键字'!lazor'(用于识别相关命令),如果是则打印相关提示信息 if '!lazor' in tcp.data.lower(): print('[!] DDoS hivemind issued by: ' + src) print('[+] Target CMD: ' + tcp.data) except Exception as e: print(f"Error in findHivemind at time {ts}: {e}") # 函数功能:在给定的pcap数据包中查找是否存在攻击行为,通过统计特定流的数据包数量并与阈值比较来判断 # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def findAttack(pcap): pktCount = {} for (ts, buf) in pcap: try: eth = dpkt.ethernet.Ethernet(buf) ip = eth.data src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) tcp = ip.data if isinstance(tcp, dpkt.tcp.TCP): dport = tcp.dport # 构建一个表示流的字符串,格式为源IP:目的IP:目的端口号 stream = src + ':' + str(dst) + ':' + str(dport) # 如果该流已经在统计字典中,则数据包数量加1 if stream in pktCount: pktCount[stream] = pktCount[stream] + 1 else: # 如果是新的流,则初始化为1 pktCount[stream] = 1 except Exception as e: print(f"Error in findAttack at time {ts}: {e}") for stream in pktCount: pktsSent = pktCount[stream] # 判断该流的数据包发送数量是否超过设定的阈值,如果是则打印相应的攻击提示信息 if pktsSent > THRESH: src = stream.split(':')[0] dst = stream.split(':')[1] dport = int(stream.split(':')[2]) print('[+] ' + src + ' attacked ' + dst + ':' + str(dport) + ' with ' + str(pktsSent) + ' pkts.') # 函数功能:在给定的pcap数据包中查找是否存在FTP相关活动(通过检测FTP相关命令关键字和端口号判断) # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def findFTP(pcap): for (ts, buf) in pcap: try: eth = dpkt.ethernet.Ethernet(buf) ip = eth.data tcp = ip.data if isinstance(tcp, dpkt.tcp.TCP): # 判断是否是FTP相关端口(21端口用于FTP服务) if tcp.dport == 21 or tcp.sport == 21: data = tcp.data # 判断FTP数据中是否包含常见的FTP命令关键字(USER、PASS、RETR),如果是则打印相应提示信息 if data and ('USER' in data or 'PASS' in data or 'RETR' in data): src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) print(f'[!] FTP activity detected between {src} and {dst}') except Exception as e: print(f"Error in findFTP at time {ts}: {e}") # 函数功能:在给定的pcap数据包中查找是否存在HTTP相关请求(通过检测端口号和解析HTTP请求对象判断) # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def findHTTP(pcap): for (ts, buf) in pcap: try: eth = dpkt.ethernet.Ethernet(buf) ip = eth.data tcp = ip.data if isinstance(tcp, dpkt.tcp.TCP): # 判断是否是HTTP或HTTPS相关端口(80用于HTTP,443用于HTTPS) if tcp.dport == 80 or tcp.sport == 80 or tcp.dport == 443 or tcp.sport == 443: data = tcp.data if data: http = dpkt.http.Request(data) # 如果能成功解析出HTTP请求的方法和URI,则打印详细的请求信息 if http.method and http.uri: print(f'[!] HTTP {http.method} request from {socket.inet_ntoa(ip.src)} to {socket.inet_ntoa(ip.dst)} for {http.uri}') else: # 如果只能检测到有HTTP相关流量但无法解析出详细请求信息,则打印基本的流量提示信息 print(f'[!] HTTP traffic detected between {socket.inet_ntoa(ip.src)} and {socket.inet_ntoa(ip.dst)}') except Exception as e: print(f"Error in findHTTP at time {ts}: {e}") # 函数功能:解析给定的pcap数据包,打印出基本的数据包信息,如时间戳、以太网帧、IP地址、TCP端口等,并简单提示可能的FTP和HTTP相关流量 # 参数:pcap是通过dpkt.pcap.Reader读取的数据包对象,包含了多个时间戳和对应的数据缓冲区 def parse_packet(pcap): for (ts, buf) in pcap: try: eth = dpkt.ethernet.Ethernet(buf) print(f"Time: {ts}, Ethernet Frame") ip = eth.data if isinstance(ip, dpkt.ip.IP): src = socket.inet_ntoa(ip.src) dst = socket.inet_ntoa(ip.dst) print(f"IP: {src} -> {dst}") if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data print(f"TCP: {tcp.sport} -> {tcp.dport}") if tcp.dport == 21 or tcp.sport == 21: print("[!] Possible FTP traffic detected") if tcp.dport == 80 or tcp.sport == 80 or tcp.dport == 443 or tcp.sport == 443: print("[!] Possible HTTP/HTTPS traffic detected") except Exception as e: print(f"Error parsing packet at time {ts}: {e}") # 主函数,程序的入口点,负责解析命令行参数,读取pcap文件并调用各个分析函数来分析数据包内容 def main(): # 创建命令行参数解析器对象,用于解析输入的参数 parser = argparse.ArgumentParser(description='Analyze pcap file for network attacks.') # 添加-p/--pcap参数,用于指定要分析的pcap文件名,该参数是必需的 parser.add_argument('-p', '--pcap', dest='pcapFile', type=str, required=True, help='specify pcap filename') # 添加-t/--thresh参数,用于指定判断攻击行为的阈值数量,该参数是可选的 parser.add_argument('-t', '--thresh', dest='thresh', type=int, required=False, help='specify threshold count') args = parser.parse_args() # 如果通过命令行参数指定了阈值,则更新全局的阈值变量THRESH if args.thresh is not None: THRESH = args.thresh pcapFile = args.pcapFile with open(pcapFile, 'rb') as f: # 使用dpkt.pcap.Reader读取pcap文件,获取数据包对象 pcap = dpkt.pcap.Reader(f) # 调用解析数据包基本信息的函数 parse_packet(pcap) # 调用查找下载LoIc相关文件行为的函数 findDownload(pcap) # 调用查找DDoS蜂巢命令的函数 findHivemind(pcap) # 调用查找攻击行为的函数 findAttack(pcap) # 调用查找FTP相关活动的函数 findFTP(pcap) # 调用查找HTTP相关请求的函数 findHTTP(pcap) if __name__ == '__main__': main() 运行命令:
返回结果:标签:ip,dpkt,tcp,data,网御,守护者,pcap,数据包 From: https://blog.csdn.net/qq_68809241/article/details/144055426