主机系统扫描程序设计
主机系统扫描程序设计
- 1、相关原理、技术分析
- 1.1获得主机的网络信息
- 1.2系统信息
- 1.3端口信息
- 2、设计思路、算法描述
- 3、详细实现(代码必须注释)
- 4、程序测试、结果分析
- 5、总结
1、相关原理、技术分析
1.1获得主机的网络信息
获取主机的网络信息非常简单,我们就拿获取
主机的IP地址
,获取主机的网卡来说
- 获取目标主机的IP地址
最简单的办法就是ping目标主机
,就会得到IP地址,当然扫描主机也要得到IP地址,在python中用一个函数也可以搞定
- 获取目标主机的网卡
获取目标主机的网卡有点东西,需要使用interfaces 和 wr
这两个模块,需要找到对应的注册表,再得到网卡信息
1.2系统信息
获取系统信息最好的办法就是ping目标主机,根据TTL值来判断目标系统信息,如果
TTL值再53左右就是Linux系统,如果TTL值再128左右就是Windows系统
,如下可以看到百度是Linux系统
1.3端口信息
端口信息我使用套接字编程实现的,我先建立一个套接字,然后与目标主机的对应端口连接,
连接不成功会返回socket.error错误
,根据这一点,我就可以判断目标主机开放的端口,进而推算出目标主机的服务
不同端口对应的服务:
FTP (21/TCP)
SSH (22/TCP)
- Telent (23/TCP)
- SMTP (25/TCP)
DNS (53/UDP & 53/TCP)
DHCP 67/68
- Kerberos (88/TCP)
POP3 (110/TCP & 995/TCP)
- RPC (135/TCP)
- NetBIOS (137/UDP & 138/UDP)
- NetBIOS / Samba (139/TCP)
- IMAP (143/TCP & 993/TCP)
- SNMP (161/TCP & 161/UDP)
- LDAP (389/TCP)
HTTPS (443/TCP)
Linux Rexec (512/TCP & 513/TCP & 514/TCP)
- Rsync (873/TCP)
- RPC (1025/TCP)
- Java RMI (1090/TCP & 1099/TCP)
MSSQL (1433/TCP)
Oracle (1521/TCP)
- NFS (2049/TCP)
- ZooKeeper (2171/TCP & 2375/TCP)
- Docker Remote API (2375/TCP)
MySQL (3306/TCP)
- RDP / Terminal Services (3389/TCP)
- Postgres (5432/TCP)
- VNC (5900/TCP)
- CouchDB (5984/TCP)
- WinRM (5985/TCP)
Redis (6379/TCP)
- Kubernetes API Server (6443/TCP && 10250/TCP)
- JDWP (8000/TCP)
- ActiveMQ (8061/TCP)
- Jenkin (8080/TCP)
- Elasticsearch (9200/TCP)
- Memcached (11211/TCP & 11211/UDP)
- RabbitMQ (15672/TCP & 15692/TCP & 25672/TCP)
- MongoDB (27017/TCP)
- Hadoop (50070/TCP & 50075/TCP)
2、设计思路、算法描述
该算法分为三步,获得主机的网络信息,获取网络信息,获取端口信息,首先获取计算机信息,platform中,有对应的函数,然后获取端口信息,直接建立套接字,再进行连接,
连接不成功会返回socket.error错误,连接成功就加入prettytable中,以表格的形式输出结果
,最后再获取网卡信息
3、详细实现(代码必须注释)
import socket
import platform
from prettytable import PrettyTable
from netifaces import interfaces
import winreg as wr
total = 0 # 计算开放的端口数量
t = PrettyTable()
column_names = ["开放的端口 ", "开放的服务 "]
# 定义获取Windows系统网卡接口的在注册表的键值的函数
def get_key(ifname):
# 获取所有网络接口卡的键值
id = interfaces()
# 存放网卡键值与键值名称的字典
key_name = {}
try:
# 建立链接注册表,"HKEY_LOCAL_MACHINE",None表示本地计算机
reg = wr.ConnectRegistry(None, wr.HKEY_LOCAL_MACHINE)
# 打开r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}',固定的
reg_key = wr.OpenKey(reg, r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}')
except:
return ('路径出错或者其他问题,请仔细检查')
for i in id:
try:
# 尝试读取每一个网卡键值下对应的Name
reg_subkey = wr.OpenKey(reg_key, i + r'\Connection')
# 如果存在Name,写入key_name字典
key_name[wr.QueryValueEx(reg_subkey, 'Name')[0]] = i
# print(wr.QueryValueEx(reg_subkey , 'Name')[0])
except FileNotFoundError:
pass
# print('所有接口信息字典列表: ' + str(key_name) + '\n')
return key_name[ifname]
def get_platform():
"""获取操作系统名称及版本号"""
return platform.platform()
def get_version():
"""获取操作系统版本号"""
return platform.version()
def get_architecture():
"""获取操作系统的位数"""
return platform.architecture()
def get_machine():
"""计算机类型"""
return platform.machine()
def get_node():
"""计算机的网络名称"""
return platform.node()
def get_processor():
"""计算机处理器信息"""
return platform.processor()
def get_system():
"""获取操作系统类型"""
return platform.system()
def main():
host = input('请输入主机信息:\n')
ip = [22, 53, 67, 80, 110, 443, 3306] # 由于主机端口太多了,我这里就扫描几个常见的端口
print('操作系统信息如下:')
table = PrettyTable() # 建立表格,用来存放目标主机信息
table.field_names = ["platform", "version", "architecture", "machine", "processor", "system"] # 一行一行存储信息
table.add_row([get_platform(), get_version(), get_architecture(), get_machine(), get_processor(), get_system()])
print(table) # 输出目标主机信息
for port in ip: # 循环端口扫描
Scan(host, port)
print("常见端口信息如下:\n")
print(t)
print(f"重要端口总共开放了{total}个")
print("网卡(网络)信息如下:")
print(get_key('WLAN'))
def Scan(IP, port):
global total # 计数
try:
Socket_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 发起连接,连接不成功会返回socket.error错误
Socket_tcp.connect((IP, port))
# 计数
total += 1
t.add_column(column_names[0], [port])
# 各个端口开放所代表的服务
if port == 22:
t.add_column(column_names[1], ['SSH'])
elif port == 53:
t.add_column(column_names[1], ['DNS'])
elif port == 67:
t.add_column(column_names[1], ['DHCP'])
elif port == 80:
t.add_column(column_names[1], ['HTTP'])
elif port == 110:
t.add_column(column_names[1], ['POP3'])
elif port == 443:
t.add_column(column_names[1], ['HTTPS'])
elif port == 3306:
t.add_column(column_names[1], ['mysql'])
# 关闭连接
Socket_tcp.close()
except:
pass
if __name__ == '__main__':
main() # 主函数
4、程序测试、结果分析
程序的结果如下所示:
这里我扫描的是自己的主机,由于端口信息有65535个,我这里只扫描了几个常用的端口信息``(22, 53, 67, 80, 110, 443, 3306)
,
连接不成功会返回socket.error错误,连接成功就加入prettytable中`,以表格的形式输出结果,完全正确。几乎代码分析全再代码中,我这里只验证结果
如上是本机的信息,可以和程序结果对比。
5、总结
总体来说python的模块功能非常强大