22 dic 2016

Construyendo nuestro propio escáner de dispositivos conectados a Internet. Parte 5

Buenas a todos, en el post de hoy de nuestra cadena "Construyendo nuestro propio escáner de dispositivos conectados a Internet", vamos a comenzar el proceso de automatización (sin almacenar aún ningún dato). Para ello, implementaremos algunas nuevas funciones que nos ayudarán a lanzar un escaneo desde una IP inicial (ip1) a una IP final (ip2), pasando por todos las direcciones contenidas en dicho subrango.

Cómo novedades encontraremos las funciones ip_add, que dada una IP nos devolverá la dirección IP siguiente, e ip_order, que dada dos IPs, nos las devuelve ordenadas de mayor a menor. Así mismo, el cuerpo de nuestra función main se ha ampliado en 4 simples líneas que realizarán la automatización. Finalmente también hemos ajustado los tiempos del escaneo de puertos, para que sea lo más ágil posible, pero sin dar muchos falsos positivos.

Os dejamos la nueva versión del código a continuación:

import pygeoip
import socket
from ports import getcommonports

def geo(_file, _ip):
    ''' This function search the geolocation values of an IP address '''
    geoDb = pygeoip.GeoIP(_file)
    ip_dictionary_values = geoDb.record_by_addr(_ip)
    ip_list_values = ip_dictionary_values.items()
    print "*******************"
    print "*** Geolocation ***"
    print "*******************"
    for value in ip_list_values:
        print str(value[0]) + ": " + str(value[1])

def hosts(_ip):
    ''' This function search the hostnames '''
    print "\n*******************"
    print "***    Hosts    ***"
    print "*******************"
    try:
        hosts_values = socket.gethostbyaddr(_ip)
        print str(hosts_values[0])
    except:
        print 'No hosts associate'

def portscan(_host, _port):
    ''' This function execute a port scan '''
    banner = ''
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(0.25)
        result = sock.connect_ex((_host, _port))
        sock.send('GET HTTP/1.1 \r\n')
        banner = sock.recv(1024)
        sock.close()
    except:
        pass
    return result, banner

def ports(_ip):
    ''' This function search open ports '''
    common_ports = getcommonports()
    print "\n*******************"
    print "***    Ports    ***"
    print "*******************"
    for value in common_ports:
        banner_exists, banner = portscan(_ip, value)
        if not banner_exists:
            print 'Port: [' + str(value) + '] Protocol: [' + str(common_ports[value]) + ']'
            print 'Banner: [' + str(banner) + ']'

def ip_order(_ip1, _ip2):
    _ip1_split = _ip1.split('.')
    _ip2_split = _ip2.split('.')
    for i in range(0, 4):
        if _ip2_split[i] < _ip1_split[i]:
            return _ip1, _ip2
        elif _ip2_split[i] > _ip1_split[i]:
            return _ip2, _ip1
    return _ip2, _ip1

def ip_add(_ip):
    _ip_split = _ip.split('.')
    if int(_ip_split[3]) < 255:
        return "%s.%s.%s.%d" % (_ip_split[0], _ip_split[1], _ip_split[2], int(_ip_split[3])+1)
    elif int(_ip_split[2]) < 255:
        return "%s.%s.%d.%d" % (_ip_split[0], _ip_split[1], int(_ip_split[2])+1, 0)
    elif int(_ip_split[1]) < 255:
        return "%s.%d.%d.%d" % (_ip_split[0], int(_ip_split[1])+1, 0, 0)
    elif int(_ip_split[0]) < 255:
        return "%d.%d.%d.%d" % (int(_ip_split[0])+1, 0, 0, 0)
    else:
        return _ip

def main(_ip1,_ip2):
    ''' Main function, launch the main activities '''
    ''' You can download GeoIP databases from here: https://dev.maxmind.com/geoip/legacy/geolite '''
    _ip3 = _ip1
    while _ip3 <> _ip2:
        _ip3 = ip_add(_ip3)
        print "************************"
        print "  IP: %s" % (_ip3)
        print "************************"
        geo('GeoIP/GeoLiteCity.dat', _ip3)
        hosts(_ip3)
        ports(_ip3)

if __name__ == "__main__":
    print 'FluScan, an IPv4 scanner. Created by http://www.flu-project.com\n'
    ip1 = 'X.X.X.X'
    ip2 = 'Y.Y.Y.Y'
    ip2, ip1 = ip_order(ip1, ip2)
    main(ip1, ip2)
Y la salida que daría por pantalla:



Si veis posibles mejoras o ideas para ir evolucionando nuestro escáner compartirlas con nosotros y las publicaremos en próximas entradas.

Saludos!

3 comentarios:

  1. Muy buena serie de artículos Juan Antonio. Felicidades por vuestro trabajo en flu.
    Además viene genial para los novatos como yo en python.

    Te paso tan solo un pequeño cambio en la función de main por si se llama con la misma ip. Es algo sencillo y sin apenas relevancia. Te paso el código:

    def main(_ip1,_ip2):
    ''' Main function, launch the main activities '''
    ''' You can download GeoIP databases from here: https://dev.maxmind.com/geoip/legacy/geolite '''

    if _ip1 == _ip2:
    print "************************"
    print " IP: %s" % (_ip1)
    print "************************"

    # Extract geolocation values
    geo('GeoIP/GeoLiteCity.dat', _ip1)
    hosts(_ip1)
    ports(_ip1)
    else:
    _ip3 = _ip1

    while _ip3 <> _ip2:
    _ip3 = ip_add(_ip3)

    print "************************"
    print " IP: %s" % (_ip3)
    print "************************"

    # Extract geolocation values
    geo('GeoIP/GeoLiteCity.dat', _ip3)
    hosts(_ip3)
    ports(_ip3)

    ResponderEliminar
  2. Gracias! incluiremos tu aportación en un próximo post

    Saludos

    ResponderEliminar
  3. Muchas gracias Juan Antonio. Disculpa, había un bug en el código que te pasé. Ahora si que está ok:

    def main(_ip1,_ip2):
    ''' Main function, launch the main activities '''
    ''' You can download GeoIP databases from here: https://dev.maxmind.com/geoip/legacy/geolite '''

    if _ip1 == _ip2:
    print "************************"
    print " IP: %s" % (_ip1)
    print "************************"

    # Extract geolocation values
    geo('GeoIP/GeoLiteCity.dat', _ip1)
    hosts(_ip1)
    ports(_ip1)
    else:
    _ip3 = _ip1
    _ip2 = ip_add(_ip2)

    while _ip3 <> _ip2:
    print "************************"
    print " IP: %s" % (_ip3)
    print "************************"

    # Extract geolocation values
    geo('GeoIP/GeoLiteCity.dat', _ip3)
    hosts(_ip3)
    ports(_ip3)

    _ip3 = ip_add(_ip3)

    ResponderEliminar