1 ARP扫描
ARP报格式:
以太网首部:
字段 长度(Byte) 默认值 备注
接收方MAC 6 广播时,为 ff-ff-ff-ff-ff-ff
发送方MAC 6
Ethertype 2 0x0806 0x0806是ARP帧的类型值
ARP包:
字段 长度(Byte) 默认值 备注
硬件类型 2 0x1 以太网类型值
上层协议类型 2 0x0800 上层协议为IP协议
MAC地址长度 1 0x6 以太网MAC地址长度为 6
IP地址长度 1 0x4 IP地址长度为 4
操作码 2 0x1表示ARP请求包,0x2表示应答包
发送方MAC 6
发送方IP 4
接收方MAC 6
接收方IP 4
填充数据 18 因为物理帧最小长度为64字节,前面的42字节再加上4个CRC校验字节,还差18个字节
来自:
ARP小工具实现:
仿造ARP包构造:
# -- coding:UTF-8 --
import logging
import sys
from scapy.all import *
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错
def arp_request(ip_address,queue=None):
result = srp(Ether(dst='FF:FF:FF:FF:FF:FF')
/ARP(op=1,hwdst='00:00:00:00:00:00',pdst=ip_address),
timeout=1,verbose=False)
try:
result_list = result[0].res #将响应的数据报对组成为一组清单
#[0]为第一组相应的包
if queue == None:
return result_list[0][1].getlayer(ARP).fields['hwsrc']
#[1]接受的包,[0]发送的包
else:
queue.put((ip_address,result_list[0][1].getlayer(ARP).fields['hwsrc']))
except:
return
if __name__ == "__main__":
print(arp_request(sys.argv[1]))
# -- coding:UTF-8 --
import ipaddress
import logging
import sys
from arpRequest import arp_request
from multiprocessing import Process,Queue
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错
def arp_scan(network):
qyt_queue = Queue()
net = ipaddress.ip_network(network.decode('gbk'))
for ip in net:
ip_addr = str(ip)
arp_one = Process(target=arp_request,args=(ip_addr,qyt_queue))
arp_one.start()
time.sleep(2)
ip_mac_list =[]
while True:
if qyt_queue.empty():
break
else:
ip,mac = qyt_queue.get()
ip_mac_list.append((ip,mac))
return ip_mac_list
if __name__ =="__main__":
active_ip_mac = arp_scan(sys.argv[1])
print("活动的IP和MAC地址如下:")
for ip,mac in active_ip_mac:
print(ip,mac)
结果:
2 TCP端口扫描
1)全扫描
原理:
扫描主机尝试与目标主机的某个端口建立正规的三次握手的连接,连接由系统调用connect()开始。如果端口开放,则连接将建立成功;否则,返回-1,则表示端口关闭。
技术特点:
优点:实现简单;对操作者的权限没有严格要求;扫描速度快。
缺点:扫描方式不隐蔽;很容易被检测出来,且在日志文件中会有大量密集的连接和错误记录;容易被防火墙发现和屏蔽。
2)半扫描
原理:
扫描主机向目标主机的某个端口发送SYN数据段。如果应答是RST,那么,说明端口是关闭的,按照设定继续探听其他端口;如果应答中包含SYN和ACK,说明目标端口处于监听状态。由于SYN扫描时,全连接尚未建立,所以,这种技术通常被称为“半连接”扫描。
技术特点:
优点:日志中对于扫描的记录量很少。
缺点:在大部分操作系统中,发送主机需要构造适用于这种扫描的IP包,需要超级用户或者得到授权的用户才可以。
3)秘密扫描
原理:
使用FIN数据包探测端口:当一个FIN数据包到达一个关闭的端口,数据包会被丢掉,且返回一个RST数据包。当一个FIN数据包到达一个打开的端口,数据包只是简单丢掉(不返回RST数据包)。由于这种技术不包含标准的TCP三次握手协议的任何部分,所以无法被记录下来,所以叫秘密扫描。
技术特点:
优点:秘密扫描能躲避IDS、防火墙、包过滤器和日志审计,从而获取目标端口的开放或关闭的信息。
缺点:和SYN扫描类似,秘密扫描也需要构造自己的IP包,也需要权限。
构造包的依据:
半扫描依据:
发送标志syn=1的包,0000 0000 0010,可以写成flags=2或flags='S',
判断收到的包是否为ack+syn,0000 0001 0010,即判断flafs==18.
# -- coding:UTF-8 --
import logging
import sys
from scapy.all import *
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)#清除报错
def tcp_scan(hostname,lport,hport):
result = sr(IP(dst=hostname)
/TCP(dport=(int(lport),int(hport)),flags=2),
timeout=1,verbose=False)
result_list = result[0].res
for i in range(len(result_list)):
if result_list[i][1].haslayer(TCP):
TCP_Fields = result_list[i][1].getlayer(TCP).fields
if TCP_Fields['flags'] == 18:
print('*端口号:'+str(TCP_Fields['sport'])+'is open!')
if __name__ == "__main__":
print('------------------------------------------')
if len(sys.argv)<4:
print('格式错误,请按以下格式输入:tcpScan.py IP startport endport')
sys.exit(0)
else:
print('*正在扫描&'+sys.argv[1])
print(tcp_scan(sys.argv[1],sys.argv[2],sys.argv[3]))
结果:
首先,ARP找到对方,然后发TCP包判断
下面展示了不完整的三次握手过程!
3 NMAP Ping扫描
import nmap
import sys
def nmap_ping(host):
nm = nmap.PortScanner()
result_raw = nm.scan(hosts=host,arguments ='-v -n -sn')
host_list =[]
for result in result_raw['scan'].values():
if result['status']['state'] == 'up':
host_list.append(result['addresses']['ipv4'])
return host_list
if __name__ == "__main__":
for host in nmap_ping(sys.argv[1]):
print('%-20s %5s'% (host,'is up'))
4 NMAP 全能扫描信息处理
效果:
源码:
# -- coding:UTF-8 --
import nmap
import sys
def nmapAscan(host):
nm = nmap.PortScanner()
raw_result = nm.scan(hosts=host,arguments ='-v -n -A')
for host,result in raw_result['scan'].items():
if result['status']['state'] == 'up' :
print('#'*17 + 'Host:' + host + '#'*17)
print('-'*20 + '操作系统猜测' + '-'*20)
for os in result['osmatch']:
print('操作系统为:'+ os['name'] + '准确度为:' + os['accuracy'])
idno =1
try:
for port in result['tcp']:
try :
print('-'*17 + 'TCP服务详细信息' + '[' + str(idno) +']')
idno=idno+1
print('TCP端口号:' + str(port))
try:
print('状态:'+ result['tcp'][port]['state '])
except :
pass
try:
print('原因:'+ result['tcp' ][port]['reason'])
except :
pass
try:
print('额外信息:' + result['tcp'][port]['extrainfo'])
except :
pass
try:
print('名字:'+ result['tcp'][port]['name'])
except :
pass
try:
print('版本:'+ result['tcp'][port]['version'])
except :
pass
try:
print('产品:' + result['tcp'][port]['product'])
except :
pass
try:
print('CPE:'+ result['tcp'][port]['cpe'])
except :
pass
try:
print('脚本:'+ result['tcp'][port]['script'])
except :
pass
except:
pass
except:
pass