Ten wpis poświęcony jest tworzeniu własnego narzędzia w języku python, który zwykle jest zainstalowany na komputerach z systemem linux. Zwykle najbardziej znanym skanerem portów jest program nmap, który posiada bardzo rozbudowane opcje. Tymczasem wielokrotnie spotkałem się z przypadkami, że taki skaner trzeba było sobie samemu napisać, poniżej przedstawiam najprostszą jego postać wraz ze szczegółowym opisem:
#!/usr/bin/python
# pierwsza linijka to wskazanie lokalizacji interpretera języka
import socket
# import biblioteki odpowiedzialnej za komunikację z hostami
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# tutaj tworzę instancję obiektu socket i wskazuję, adres oraz rodzaj
# komunikacji na TCP
socket.setdefaulttimeout(3)
# ustawiam domyślny czas po którym przestaję odpytywać hosta
host = raw_input("Podaj hosta: ")
# proszę użytkownika o podanie hosta
port = 135
# ustawiam zmienną port na wartość 135
def portscanner(port):
if sock.connect_ex((host, port)):
print "Port %d jest zamkniety" % (port)
else:
print "Port %d jest otwarty" % (port)
# funkcja portscanner przyjmuje jako parametr wartość liczbową portu,
# następnie przy pomocy instrukcji warunkowej podaje informacje czy
# port danego hosta jest zamknięty czy otwarty
portscanner(port)
# wywołanie funkcji portscanner z przypisaną wcześniej wartością 135
Powyżej najprostsza postać skanera portu, mogę wskazać tylko jeden port w skrypcie. Dlatego też poniżej bardziej rozbudowana wersja skanera, opiszę różnice w programie poniżej:
#!/usr/bin/python
import socket
from termcolor import colored
# import biblioteki odpowiedzialnej za kolorowanie napisów
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.setdefaulttimeout(3)
host = raw_input("Podaj hosta: ")
def portscanner(port):
if sock.connect_ex((host, port)):
# pass
print(colored("Port %d jest zamkniety" % (port), 'red'))
else:
print(colored("Port %d jest otwarty" % (port), 'green'))
# w funkcji dodano parametr odpowiedzialny za kolor napisu, ponadto
# istnieje możliwość wykomentowania linijki odpowiedzialnej za
# wypisywanie komunikatu o zamkniętym porcie (usuń komentarz przed pass)
# wówczas program wypisze tylko otwarte porty
for port in range(1,30):
portscanner(port)
# pętla for do wykonania iteracji po portach, wartości w polu range
# odpowiadają portowi początkowemu i końcowemu
W tym skrypcie istnieje możliwość zdefiniowania zakresu portów oraz określenie czy ma zostać wypisana kompletna lista czy tylko otwarte porty. Poniżej przykład z wykonania programu w wersji jak powyżej:
root@kali:~/python# ./scaner1.py
Podaj hosta: localhost
Port 1 jest zamkniety
Port 2 jest zamkniety
Port 3 jest zamkniety
Port 4 jest zamkniety
Port 5 jest zamkniety
Port 6 jest zamkniety
Port 7 jest zamkniety
Port 8 jest zamkniety
Port 9 jest zamkniety
Port 10 jest zamkniety
Port 11 jest zamkniety
Port 12 jest zamkniety
Port 13 jest zamkniety
Port 14 jest zamkniety
Port 15 jest zamkniety
Port 16 jest zamkniety
Port 17 jest zamkniety
Port 18 jest zamkniety
Port 19 jest zamkniety
Port 20 jest zamkniety
Port 21 jest zamkniety
Port 22 jest otwarty
Port 23 jest zamkniety
Port 24 jest zamkniety
Port 25 jest zamkniety
Port 26 jest zamkniety
Port 27 jest zamkniety
Port 28 jest zamkniety
Port 29 jest zamkniety
Na koniec wpisu przedstawiam najbardziej rozbudowaną wersję skanera portów, który posiada wbudowaną instrukcję użytkowania programu.
#!/usr/bin/python
from socket import *
import optparse
from threading import *
from termcolor import colored
def connScan(tgtHost, tgtPort):
try:
sock=socket(AF_INET, SOCK_STREAM)
sock.connect((tgtHost, tgtPort))
print(colored('[+] %d/tcp Otwarty' % tgtPort, 'green'))
except:
print(colored('[-] %d/tcp Zamkniety' % tgtPort, 'red'))
finally:
sock.close()
def portScan(tgtHost, tgtPorts):
try:
tgtIP = gethostbyname(tgtHost)
except:
print 'Nieznany Host %s ' %tgtHost
try:
tgtName = gethostbyaddr(tgtIP)
print 'Wyniki skanowania dla:' + tgtName[0]
except:
print 'Wyniki skanowania dla:' + tgtIP
setdefaulttimeout(1)
for tgtPort in tgtPorts:
t=Thread(target=connScan, args=(tgtHost, int(tgtPort)))
t.start()
def main():
parser = optparse.OptionParser('Podaj parametry: ' + '-H <podaj host> -p <podaj port> lub <podaj port, kolejny port>')
parser.add_option('-H', dest='tgtHost', type='string', help='wskaz hosta do skanowania')
parser.add_option('-p', dest='tgtPort', type='string', help='wskaz porty do skanowania, oddziel przecinkiem')
(options, args) = parser.parse_args()
tgtHost = options.tgtHost
tgtPorts = str(options.tgtPort).split(',')
if (tgtHost == None) | (tgtPorts[0] == None):
print parser.usage
exit(0)
portScan(tgtHost, tgtPorts)
if __name__ == '__main__':
main()
Przykłady użycia skanera przedstawiam poniżej:
root@kali:~/python# ./advscanner.py
Podaj parametry: -H <podaj host> -p <podaj port> lub <podaj port, kolejny port>
root@kali:~/python# ./advscanner.py -H 192.168.0.103 -p 135,139
Wyniki skanowania dla:192.168.0.103
[+] 135/tcp Otwarty
[+] 139/tcp Otwarty
Wszystkie skrypty były testowane w środowisku KaliLinux na interpreterze języka Python w wersji 2. U mnie działa 🙂