본문 바로가기

Code

'Nmap-python' 모듈을 이용한 Nmap Port Scanner [Python]

import nmap
import argparse


def nmapScan(tgtHost, tgtPort):
    nmScan = nmap.PortScanner()
    nmScan.scan(tgtHost, tgtPort)
    state = nmScan[tgtHost]['tcp'][int(tgtPort)]['state']
    print " [*] " + tgtHost + " tcp/" + tgtPort + " " + state

def main():
    parser = argparse.ArgumentParser('usage%prog ' + \
            '-H <target host> -p <target port>')
    parser.add_argument('-H', dest = 'tgtHost', \
            help = 'specify target host')
    parser.add_argument('-p', dest = 'tgtPort', \
            help = 'specify target port[s] separated by comma')

    args = parser.parse_args()
    tgtHost = args.tgtHost
    tgtPorts = str(args.tgtPort).split(', ')

    if (tgtHost == None) | (tgtPorts[0] == None):
        print parser.usage
        exit(0)

    for tgtPort in tgtPorts:
        nmapScan(tgtHost, tgtPort)

if __name__ == '__main__':
    main()

 

사용 모듈은 nmap, argparse 입니다.

 

nmap : 네트워크 스캔 모듈입니다. 리눅스에서 사용하는 nmap이라고 생각하시면 됩니다. nmap은 파이썬과 아주 잘 맞는 툴 중 하나입니다.

 

argparse : 리눅스 쉘 에서 명령처럼 실행하게 만들어 주는 모듈입니다. 명령 줄을 쉽게 입력 가능하게 만들어 줍니다. 예전에는 'optparse' 라는 모듈을 사용했지만 현재는 'argparse'로 바뀌고 'optparse'는 더 이상 지원하지 않습니다. 그래도 해당 함수들과 거의 유사하게 사용이 가능하기 때문에 어렵진 않습니다. 'opt'부분을 'arg'로 바꿔 주기만 하면 거의 똑같이 사용 가능합니다.

 

 

 <코드 설명>

 

 

def nmapScan(tgtHost, tgtPort):


    nmScan = nmap.PortScanner()

-> 'nmap'을 실행합니다.


    nmScan.scan(tgtHost, tgtPort)

 

-> 실행된 'nmap'에 호스트 값고 포트 번호를 스캔합니다.


    state = nmScan[tgtHost]['tcp'][int(tgtPort)]['state']

-> 입력 받는 형식입니다. [타겟호스트][tcp로 탐색합니다.][포트번호][해당포트의 상태입니다.]


    print " [*] " + tgtHost + " tcp/" + tgtPort + " " + state

-> 위의 결과값을 출력합니다.

 

def main():

- 지금부터 nmap 모듈을 좀더 세부적으로 사용합니다. 해당 포트의 상태 즉, 잠겼는지 안열렸는지 열렸는지 에 대해 확인하고 명령줄에서 바로 호스트주소와 포트번호를 입력받아 동작할 수 있도록 'argparse' 모듈을 이용한 코딩을 시작합니다.


    parser = argparse.ArgumentParser('usage%prog ' + \
            '-H <target host> -p <target port>')

-> 위에서 'nmap'을 "[tgtHost]['tcp][int(tgtPort)]['state']"의 상태로 사용하기로 했기 때문에 해당 양식에 맞게 parser변수에 값을 입력해 줍니다. 'argparse.ArgumentParser'를 이용하여 명령줄에서 입력받게 사용할 수 있습니다.


    parser.add_argument('-H', dest = 'tgtHost', \
            help = 'specify target host')

-> 'add_argument'는 바로 위에 줄 인자에 해당 값을 채워주길 바랄때 사용됩니다. 또한 해당 명령에 대한 사용법 즉, help 입력시 어떻게 사용하면 되는지에 대해 사용법을 출력하게 만듭니다. 사용 법은 'help' 뒷 쪽으로 메시지로 표현됩니다.


    parser.add_argument('-p', dest = 'tgtPort', \
            help = 'specify target port[s] separated by comma')

-> 같은 부분입니다. 이번엔 포트번호에 대한 값을 채워주는 과정이고 그것에 대한 설명입니다.

    args = parser.parse_args()

-> 기존에 optparse 에서는 '(options, args) = parser.parse_args()'이런식으로 사용됬을 껍니다. 바뀐 'argparse'에서는 이런식으로 사용하게 됩니다. 위의 parser 변수를 이용해 명령줄에 입력이 가능하게 호출해주는 과정입니다.


    tgtHost = args.tgtHost

-> 타겟 호스트에 대한 정보를 입력받고 저장합니다.


    tgtPorts = str(args.tgtPort).split(', ')

-> 포트주소에 대한 정보를 입력받고 저장합니다. 여러게의 포트주소를 입력할 경우 ', '로 구분합니다.

    if (tgtHost == None) | (tgtPorts[0] == None):
        print parser.usage
        exit(0)
-> 만약에 타겟호스트 또는 포트번호가 없으면 오류메시지를 출력하고 종료합니다.


    for tgtPort in tgtPorts:
        nmapScan(tgtHost, tgtPort)

-> 포트번호를 여러개 입력했을 경우 해당 포트에 대한 상태를 전부다 출력하기 위해 반복하는 과정입니다.

 

 if __name__ == '__main__':
    main()

-> 'main' 함수를 호출합니다!  "if __name__ == '__main__':"를 사용하는 이유는 현재 코드의 상태를 파악하기 위해 사용합니다. 즉, 해당 if 함수를 기준으로 위쪽의 코드는 해당 파일의 이름으로 실행되어 __name__ = '__filename__' 이 됩니다. 그리고 위의 함수의 실행이 종료되면 다시 __name__ = '__main__'으로 돌아오게 됩니다. 하나의 코드에서 모듈을 만들고 해당 모듈을 실행하는 과정을 나누는 것입니다. '__name__'변수는 해당 import된 모듈, 파일을 저장하는 함수입니다. 그러니 이것이 메인 프로그램으로 사용될 것인지 아니면 모듈로써 사용될 것인지에 대해 나누는 기준점 역할을 하게 되는 것 입니다.

반응형