-
دوشنبه, ۲۸ تیر ۱۴۰۰، ۱۲:۲۱ ب.ظ
-
۱۱۶۴
سلام دوستان :)
توی این پست میخوایم با هم نحوه ساخت یک اسکریپت پورت اسکنر با پایتون رو ببینیم.
همینطور که میدونید اسکن کردن پورت ها توی مباحث تست نفوذ و امنیت میتونه خیلی کاربرد داشته باشه و ما میتونیم با استفاده از پورت های باز، بسته به نوع سیستم و سیستم عامل و... بیایم و این پورت ها رو اکسپلویت کنیم.
خب توی این اسکریپت قراره به این صورت عمل کنیم:
1- اول لیست پورت هایی که میخوایم اسکن کنیم رو مشخص میکنیم
2- با استفاده از کتابخونه socket دونه دونه پورت ها رو امتحان میکنیم و پورت هایی که باز بودن رو مشخص میکنیم
اول میریم سراغ نوشتن اسکریپت ساده.
برای نوشتن این اسکریپت من از ماژول colorama برای رنگی چاپ کردن متن ها استفاده کردم .پس کار رو با نصب ماژول colorama شروع می کنیم.
برای نصب این ماژول توی ویندوز وارد cmd بشین و دستور زیر رو وارد کنین:
pip3 install colorama
برای نصب این ماژول توی لینوکس وارد terminal بشین و دستور زیر رو وارد کنین:
sudo pip3 install colorama
خب حالا میتونیم بریم سراغ کد؛
سورس پورت اسکنر ساده:
import socket # for connecting from colorama import init, Fore # some colors init() GREEN = Fore.GREEN RESET = Fore.RESET GRAY = Fore.LIGHTBLACK_EX def is_port_open(host, port): """ determine whether `host` has the `port` open """ # creates a new socket s = socket.socket() try: # tries to connect to host using that port s.connect((host, port)) # make timeout if you want it a little faster ( less accuracy ) s.settimeout(0.2) except: # cannot connect, port is closed # return false return False else: # the connection was established, port is open! return True # get the host from the user host = input("Enter the host:") # iterate over ports, from 1 to 1024 for port in range(1, 1025): if is_port_open(host, port): print(f"{GREEN}[+] {host}:{port} is open {RESET}") else: print(f"{GRAY}[!] {host}:{port} is closed {RESET}", end="\r")
اول ماژول های مورد نیاز رو import کردیم. بعد یک سری رنگ با استفاده از ماژول colorama تعریف کردیم. بعدش تابع is_port_open رو تعریف کردیم که دو تا ورودی host و port رو میگیره. خب داخل خط اول تابع، شئ سوکتمون رو درست کردیم. حالا داخل try گفتیم که به اون هاست و پورتی که به تابع داده بودیم وصل بشه. توی except (یعنی اگر کد داخل try اشتباه بود و به معنی این هست که اون پورت مشخص باز نبوده) گفتیم که مقدار False رو برگردونه و داخل else (یعنی اگر پورت باز بود و برنامه با موفقیت به هاست و پورت مد نظر متصل شد) گفتیم که True رو برگردونه. حالا گفتیم که آدرس هاست رو از کاربر دریافت کنه و داخل یک حلقه for از پورت 1 تا 1024 رو با استفاده از تابع is_port_open که قبلا تعریف کرده بودیم اسکن کنه و نتیجه رو چاپ کنه.
خب حالا اگر اسکریپت رو اجرا کنین، میبینین که ازتون یک ورودی دریافت میکنه که شما باید آدرس هاست مورد نظر رو وارد کنین. بعد برنامه پورت ها رو اسکن میکنه و نتیجه رو به شما میگه.
حالا ایرادش چیه؟ ایراد این اسکریپت اینه که خیلی کنده ! یعنی هر پورت رو تقریبا توی یک ثانیه اسکن میکنه ! و این خیلی طول میکشه !!!
برای اینکه پیشرفته ترش کنیم میتونیم از multi threading استفاده کنیم که توی این دو تا پست:
1- پست 1
2- پست 2
راجع بهش توضیح دادم :))
خب پس بریم پیشرفته ترش کنیم؛
سورس پورت اسکنر پیشرفته:
import argparse import socket # for connecting from colorama import init, Fore from threading import Thread, Lock from queue import Queue # some colors init() GREEN = Fore.GREEN RESET = Fore.RESET GRAY = Fore.LIGHTBLACK_EX # number of threads, feel free to tune this parameter as you wish N_THREADS = 200 # thread queue q = Queue() print_lock = Lock() def port_scan(port): """ Scan a port on the global variable `host` """ try: s = socket.socket() s.connect((host, port)) except: with print_lock: print(f"{GRAY}{host:15}:{port:5} is closed {RESET}", end='\r') else: with print_lock: print(f"{GREEN}{host:15}:{port:5} is open {RESET}") finally: s.close() def scan_thread(): global q while True: # get the port number from the queue worker = q.get() # scan that port number port_scan(worker) # tells the queue that the scanning for that port # is done q.task_done() def main(host, ports): global q for t in range(N_THREADS): # for each thread, start it t = Thread(target=scan_thread) # when we set daemon to true, that thread will end when the main thread ends t.daemon = True # start the daemon thread t.start() for worker in ports: # for each port, put that port into the queue # to start scanning q.put(worker) # wait the threads ( port scanners ) to finish q.join() if __name__ == "__main__": # parse some parameters passed parser = argparse.ArgumentParser(description="Simple port scanner") parser.add_argument("host", help="Host to scan.") parser.add_argument("--ports", "-p", dest="port_range", default="1-65535", help="Port range to scan, default is 1-65535 (all ports)") args = parser.parse_args() host, port_range = args.host, args.port_range start_port, end_port = port_range.split("-") start_port, end_port = int(start_port), int(end_port) ports = [ p for p in range(start_port, end_port)] main(host, ports)
خب چون اکثرشو توی سورس بالا توضیح دادم الان فقط قسمت های جدید رو میگم. خب تابع scan_thread رو برای این نوشتیم چون از multi threading استفاده میکنیم یک صف درست کنه و process ها رو به ترتیب اجرا کنه یعنی ما بتونیم خروجی نهایی رو بخونیم :))) که اینکار هم با استفاده ازماژول queue انجام دادیم.
توی تابع main گفتیم که بیاد یک thread از تابع scan_thread بسازه و بعد هم مقدار daemon رو برابر True قرار بده یعنی thread وقتی تموم بشه که thread اصلی به پایان میرسه. بعد هم هر پورت رو توی صف پورت ها قرار میدیم که بعدا اسکنشون کنیم.
حالا توی if گفتیم که یک سری پارامتر برای برنامه مون تعریف کنه مثل هاست و رنج پورت ها. بعد هم پورت اول و پورت آخر رو تعریف کردیم، حالا کل پورت ها رو با استفاده از یک حلقه داخل یک لیست قرار دادیم.
در نهایت هم پورت ها رو اسکن کردیم.
خب اینم از سورس پیشرفته؛
برای اجرا کردن این برنامه cmd یا terminal رو باز کنید و وارد مسیر برنامه تون بشین. حالا دستور زیر رو وارد کنین:
python3 fast_port_scanner.py --ports [start_port]-[end_port] [host]
توجه کنید که باید جای fast_port_scanner.py اسم برنامه تون رو بذارین، جای [start_port] پورت اول، جای [end_port] باید پورت آخر رو بذارین و جای [host] باید هاستی که میخواین پورت هاشو اسکن کنین وارد کنین.
حالا میتونین ببینین که سرعت اسکریپت خیلی بیشتر شده و حداقل 20 پورت در ثانیه اسکن میکنه :)). اگر کل پورت ها (1 تا 65535) رو اسکن کنین میبینین که توی چند ثانیه همرو اسکن میکنه !
امیدوارم براتون مفید بوده باشه D: