网络编程大家都学会了吗?socket->bind->listen->accept->recv/recvfrom->send/sendto一气呵成,什么select,poll,epoll多路复用模型,信手拈来。但是这套东西只是基于传输层TCP和UDP开发应用。有没有想过如何编程批量发送一批TCPSYN握手包进行端口扫描?如何编程发送带有伪造IP地址的ARP包和IP数据包?甚至,如何编程发送一个伪造的MAC地址的以太网数据帧?一旦掌握了以上技巧,玩转数据包不在话下,开发各种神器也轻而易举。但是一定要用在正确的路径上,不是为了监狱编程~那怎么构造和发送各种数据包呢?今天给大家介绍一个强大的工具:scapy这是一个强大的数据包构建工具,你可以在Python中使用它的时候,是时候喊一声:Python大法好!ARP我们使用ARP作为地址解析协议。局域网内的通信需要使用网卡的MAC地址,而网络层通信则使用IP地址。在应用程序的数据包发出前,在IP报文前面加上以太网帧头时,需要填写接收方的MAC地址。如果是局域网内部通信,则接收方地址为目标计算机网卡的MAC地址,如果是公网IP地址,收件人地址就是网关的MAC地址。无论如何,必须有一个MAC地址,那怎么办?这就是ARP协议的作用。它可以将IP地址转换为MAC地址。ARP解析的过程这里不再赘述。简单的说,比如你要查询192.168.1.100的MAC地址,主机在局域网内使用ARP协议发送广播:192.168.1.100,我给你打电话,你敢答应吗?网络中的每个人都能收到这个广播(因为它的收件人MAC地址是FF-FF-FF-FF-FF-FF),但是只有IP地址为192.168.1.100的人会回复:Grandpaishere!MyMACaddressisxxxxxx。注意,在我们平时的应用程序进行通信时,上述过程是由操作系统底层协议栈自动完成的,我们的应用程序无法感知到这一点。我们可以使用Scapy库发起ARP解析。fromscapy.allimport*defarp_scan(ip):answer,uanswer=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip),inter=0.1,timeout=2,verbose=False)mac_list=[]forsend,recvinanswer:ifrecv[ARP].op==2:mac_list.append((recv[ARP].psrc,recv[Ether].hwsrc))returnmac_list以上代码,通过scapy库srp函数中发送一个以太网帧,接收方为ff:ff:ff:ff:ff:ff,说明这是一个广播包,ARP协议在链路层之上,需要的IPparsed传入被解析的IP地址参数。上面的函数执行完,就可以在wireshark中抓取数据包了:上面说了,一般情况下,只有目的地址是我查到的主机才会回复我。但如果你局域网内有人有恶意,请在真主前回答我:爷爷来了!我的MAC地址是yyyyyy。那可就糟了,后面所有的通讯信息都发给了这个冒牌货,这就是大名鼎鼎的ARP欺骗攻击!再想象一下,如果查询的IP地址是网关的IP地址,后果会更严重,所有的网络流量都发给了这个家伙。既然可以发送ARP查询报文,那么把上面的代码改一下,自然也可以发送ARP响应报文了……ARP的故事先到这里,我们再来看看,用scapy做端口扫描器。端口扫描TCP端口扫描,通过发送三次握手的第一个SYN包,根据返回结果判断端口开放:如果返回ACK+SYN,即flags字段为18,则表示端口开放:如果返回ACK+RST,即flags字段为20,表示端口关闭:可以实现如下函数:fromscapy.allimport*defport_scan(port):answer,uanswer=sr(IP(dst="192.168.1.1")/fuzz(TCP(dport=int(port),flags="S")))fors,rinans:ifr[TCP].flags==18:print("portisOpen")ifr[TCP].flags==20:print("portisClosed")抓包:握手包和服务器返回包都可以清晰看到。如果在循环中不断调用这个函数,传入不同的端口,就可以实现批量端口扫描。scapy构造数据包的能力只是冰山一角,更多强大的功能等着你去研究。学习计算机网络,不要仅仅停留在看书和博文的基础上。如果能自己编程收发数据包,实现ARP、ICMP、DHCP、DNS等功能,或者开发一些简单的网络工具,肯定比别人强。深刻的。最后留个问题给大家思考一下。如何通过构造IP包实现traceroute的路由跟踪功能?大家想一想,这怎么实现呢?
