简单的端口扫描

0x01、端口扫描

端口扫描是指一些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型。(服务类型与端口号有关)
端口扫描器,是指客户端向服务器端端口发送请求信息,当我们收到回复时,就可以确定此端口的开放,也就了解了提供的网络服务。
扫描器应该有三项功能:发现一个主机或网络的能力;一旦发现一台主机,有发现什么服务正运行在这台主机上的能力;通过测试这些服务,发现漏洞的能力

0x02、扫描原理

端口扫描的分类:开放扫描、半开放扫描、隐蔽扫描

1、connect扫描
利用TCP的三次握手来判断端口开放情况,连接成功则表示端口开放。准确度高,但是很容易被防火墙和IDS检测到,在日志中也会存在大量连接请求和错误信息。

2、SYN扫描
扫描器向目标主机的一个端口发送请求连接的SYN包,扫描器在收到SYN/ACK后,不是发送的ACK应答而是发送RST包请求断开连接。这样,三次握手就没有完成,无法建立正常的TCP连接,因此,这次扫描就不会被记录到系统日志中。这种扫描技术一般不会在目标主机上留下扫描痕迹。但是,这种扫描需要有root权限。

端口开放:a、Client发送SYN; b、Server端发送SYN/ACK;c、Client发送RST断开(只需要前两步就可以判断端口开放)
端口关闭:a、Client发送SYN; b、Server端回复RST(表示端口关闭)

3、ACK扫描
扫描主机向目标主机发送ACK数据包。根据返回的RST数据包有两种方法可以得到端口的信息。方法一是:若返回的RST数据包的TTL值小于或等于64,则端口开放,反之端口关闭

0x04、常见端口对应的服务

21----FTP             22----SSH
23----TELNET          25----SMTP
80----HTTP            110----P0P3
443----HTTPS          1080----SOCKS
1433----Sql Server    1521----Oracle
3306----Mysql         3386----Misrosoft RDP

0x03、代码实现

1、将具有代表性的端口和对应的服务列出;
2、端口扫描模块使用socke实现;
3、输出端口开放情况;

定义get_remote_machine_info()函数获取输入网址的信息,socket.gethostbyname()获取ip

定义scan函数对目标进行扫描,使用socket编程实现端口扫描

总体代码如下:

#!/usr/bin/python
# -*- coding:UTF-8 -*-

Port = [80,21,23,22,25,110,443,1080,3306,3389,1521,1433]
Server = ['HTTP','FTP','TELNET','SSH','SMTP','POP3','HTTPS','SOCKS','MYSQL','Misrosoft RDP','Oracle','Sql Server']
result = []

import socket
import sys
import threading
import time

def get_remote_machine_info(Domain):
    try:
        return socket.gethostbyname(Domain)
    except socket.error,e:
        print '%s: %s'%(Domain,e)
        return 0

def scan(Domain,port,server):
    temp = []
    try:
        s = socket.socket()
        print "Attempting to connect to "+Domain+': '+str(port)
        s.connect((Domain,port))
        temp.append(port)
        temp.append(server)
        result.append(temp)
        s.close()
    except:
        pass


def output(Domain,IP):
    if result:
        print '\n'+Domain+': --> '+IP
        print '\nThe Open Port:'
        for i in result:
            print Domain+': %4d -->%s'%(i[0],i[1])
    else:
        print 'None Port!'

def main():
    payload = sys.argv
    IP = get_remote_machine_info(payload[1])
    print '\n'
    for port,server in zip(Port,Server):
        t = threading.Thread(target=scan,args=(payload[1],port,server,)) #for循环创建线程,每个端口开一个线程
        t.setDaemon(True) #将线程声明为守护线程,使其可快速退出
        t.start()
        time.sleep(0.1) #每个线程之间设置时间间隔,避免输出混乱
    output(payload[1],IP)

if __name__=='__main__':
    main()

效果:

参考连接:
http://www.360doc.com/content/12/0302/13/3725126_191092221.shtml
http://www.runoob.com/python/python-socket.html