سنقوم في الدرس بإنشاء برنامج بسيط نقوم من خلاله إجراء مسح شامل على منافذ الكمبيوتر بدون تثبيت مكتبات خارجية والإكتفاء بالمكتبات و الوحدات المدمجة
وقبل أن نبدأ دعوني أتكلم عن بعض التعريفات الأساسية في عالم الشبكات حتى يكون الموضوع موجه للجميع المبتدئين والمتقدمين على التوالي .
المنفذ : هو مكان يتم من خلاله إستقبال وإرسال المعلومات وكل برنامج لديه منفذ خاص به حتى تكون الأمور منظمة (مزيد من المعلومات ).
مسح المنافذ : هي عملية إرسال مجموعة من الحزم الى منفذ معين من أجل معرفة إذا كان مفتوح أو لا و معرفة ما هي الخدمات التي يقدمها هذا المضيف وبالتالي إستغلال ذلك المفذ عبر جمع معلومات وثغرات البرنامج الذي يستخدمه.
إجتياح المنفذ: هو عملية مسح لمنفذ معين في حالة إستماع لعديد من الأجهزة في نفس الوقت وعادة ماتستخدم هذه الطريقة من أجل البحث عن خدمة معينة (وعلى سبيل تخيل معي دودة خبيثة خاصة ب SQL تقوم بإكتساح العديد من أجهزة الكمبيوتر للبحث عن جهاز ما يقوم بالإستماع عبر المنفذ 1433).
TCP/IP :إن جميع العمليات والتصاميم الموجودة على شبكة الأنترنيت قائمة على أساس بروتوكول الأنترنيت وعادة مايسمى ب TCP/IP ففي هذا النظام تقوم جميع الأجهزة و الأجهزة المقدمة للخدمات عنصرين أساسيين هما العناوين وأرقام المنافذ حيث يوجد أكثر من 6000 منفذ يمكن إستعماله .
هناك بعض برامج المسح تقوم بمسح المنافذ المشهورة فقط وبعضها اﻷاخر يقوم بمسح المنافذ المشهورة بثغراتها .
سأكتفي يهذا القدر من التعريفات لأن المقام لا يسمح لي بأكثر من هذا ولو سمحت لنفسي لن أنتهي من موضوع الشبكات أبدا ولكن يمكنك البحث عن المزيد عبر محركات البحث عن فحص المنافذ.
نعود ألان الى بايثون والبرنامج الخاص بنا لفحص منافذ الجهاز حيث سأقوم بوضع الكود الكامل للبرنامج ثم نقوم بعد ذلك بشرح كل جزء منه .
# -*- coding: UTF-8 -*- import socket import sys,os # Clear the screen os.system("clear") max_port=5000 min_port=1 host=input(":قم بإدخال عنوان المضيف لعمل مسح المنافذ ") host_ip=socket.gethostbyname(host) # عرض هيدر جميل مع مجموعة من المعلومات عن المضيف print ("-" * 60) print("من فضلك أنتظر تتم الأن عملية مسح العنوان التالي : ", host_ip) print ("-" * 60) try: for port in range(min_port,max_port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(0.5) result = sock.connect_ex((host_ip, port)) if result == 0: print ("Port %d : \t Open "%(port)) sock.close() except KeyboardInterrupt: print ("You pressed Ctrl+C") print ("\n\n[*] User Requested An Interrupt.") print ("[*] Application Shutting Down.") sys.exit() except socket.gaierror: print ('Hostname could not be resolved. Exiting') sys.exit() except socket.error: print ("Couldn't connect to server") sys.exit() # عرض معلومات أخرى على الشاشة print ("[*] Have a nice day !!!! ... From http://Pyarab.com ")
هذا هو كود البرنامج وهو لا يتعدي 40 سطر وكان يمكن أقل من ذلك ولكن تم إضافة بعض السطور للمزيد من التوضيح فقط .
نقوم الان بشرح الكود سطر بسطر حتى نفهم كيف تمت العملية .
ملاحظة السطر التالي : -*- coding: UTF-8 -*- # ترميز خاص باللغة حتى لا تكون لدينا مشاكل خاصة وأنني إسعملت بعض الجمل باللغة العربية وتم تجريب البرنامج على نظام أوبنتو يمكنك الاستغناء عن هذا السطر وحذف الجمل العربية .
الجزء الأول
import socket import sys,os
في هذا الجزء سنقوم بإستدعاء جميع المكتبات والوحدات التي سنحتاجها في برنامجنا .
المكتبة الاولى هي مكتبة socket وهي المكتبة الأساسية ولا يمكن الإستغناء عنها .
الوحدتان التاليتان هما وحدتا os و sys على التوالي وهما وحدتان غير أساسيتان ويمكن الإستغناء عن هما و لكن سنقوم بإستخدامهما من أجل ترتيب البرنامج .
كان بإمكاني إستدعاء مكتبات أخرى من أجل جمالية البرنامج مثل مكتبة الوقت لحساب مدة عملية المسح وغيرها ولكن يكفي بهذه المكتبات كبداية .
الجزء الثاني :
# تنظيف الطرفية os.system(clear)
هذا الجزء جزء تجميلي فقط و طبعا هو غير مهم حيث أن مهمته الوحيدة مسح جميع السطور السابقة والموجودة على الطرفية وبدا البرنامج من أعلى الشاشة .
الجزء الثالث :
max_port=5000 min_port=1 host=input(":قم بإدخال عنوان المضيف لعمل مسح المنافذ ") host_ip=socket.gethostbyname(host)
في هذه المرحلة قمت بتعيين متغيرين الأول عبارة عن القيمة الأعلى للمنافذ التي يمكن للبرنامج أن يقوم بمسحها أما المتغير الثاني عبارة عن القيمة الأدنى للمنافذ والتي سيبدأ البرنامج بعملية المسح إنطلاقا منها .
ثم قمت بتعيين متغير أخر ستكون قيمته إسم (إسم الدومين أو عنوان الأبي ) المضيف أو السيرفر الذي سنقوم بعملية المسح عليه أما المتغير الرابع ستكون قيمته عنوان الأيبي للدومين المختار في المتغير الثالث .
الجزء الرابع :
# عرض هيدر جميل مع مجموعة من المعلومات عن المضيف print ("-" * 60) print("من فضلك أنتظر تتم الأن عملية مسح العنوان التالي : ", host_ip) print ("-" * 60)
هذا الجزء عبارة عن تصميم هيدر البرنامج (خطوة غير مهمة أو أساسية).
الجزء الخامس :
try: for port in range(min_port,max_port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(0.5) result = sock.connect_ex((host_ip, port)) if result == 0: print ("Port %d : \t Open "%(port)) sock.close()
هذا هو أهم جزء في البرنامج إذ أن عملية المسح تتم في هذه المرحلة .
قمت بإستخدام دالة range من أجل توليد قائمة من الأرقام والأعداد إنطلاقا من الرقم الأدنى الى الرقم الأكبر داخل حلقة for وسيكون ناتج القائمة مجموعة من أرقام المنافذ الذي سيقوم البرنامج بمسحها.
في السطر الثاني قمت بإنشاء كائن المقبس وهو ضروري للقيام بعملية الإتصال حيث أن العملية ستتم عبر الشبكة (لمزيد من المعلومات حول المقبس ) .
sock.settimeout(0.5)
قبل أن أتكلم عن هذا السطر عليك أن تعلم أن عملية مسح المنافذ قد تأخذ وقت طويل في بعض الأحيان خاصة على الانترنيت وذلك لعدة أسباب (الظغط ، الحماية الخ …)
وبما أن العملية قد تطول كثيرا قمت بإستخدام هذا السطر وكأنني أقول للبرنامج جرب مع كل منفذ على الأكثر 5 ثواني فإن لم يستجب إعتبره منفذ ميت وقم بالمرور الى المنفذ الموالي.
بعد ذلك قمت بإنشاء متغير أخر مهمته الإتصال بالعنوان والمنفذ ثم تخزين البيانات الملتقطة من خلال عملية الإتصال بعد ذلك نقوم بالتحقق من قيمة المتغير فإذا كانت قيمته صفر وهي القيمة التي تستخدمها جميع برامج اللينكس عندما يكون هناك تنفيذ ناجح وفي حالة عدم وجود أي إتصال ستكون قيمة المتغيير واحد وستكون هناك رسالة لتخبرك بعدم وجود أي إتصال .
بعد ذلك (في حالة نجاح الإتصال) سيقوم البرنامج بعرض جميع المنافذ المفتوحة مع أرقامه مع كلمة مفتوح أمامها.
الجزء السادس :
except KeyboardInterrupt: print ("You pressed Ctrl+C") print ("\n\n[*] User Requested An Interrupt.") print ("[*] Application Shutting Down.") sys.exit() except socket.gaierror: print ('Hostname could not be resolved. Exiting') sys.exit() except socket.error: print ("Couldn't connect to server") sys.exit()
هذا الجزء خاص بالأخطاء المحتملة من طرف المستخدم او من الشبكة ففي حالة أراد المستخدم إنهاء البرنامج من خلال الزرين CTRL+Z فستاتيه رسالة تخبره بأنه ظغط على تلك الأزرار مع رسالة أخرى تدل على أن البرنامج سيغلق.
أما في حالة عدم وجود السيرفر المراد الاتصال به أو يكون في حالة غير متصل ستكون هناك رسالة أخرى تدل على ذلك
وقبل أن أنهي هذا الموضوع أترككم مع الصورة من جهازي بعد تجريب البرنامج على محرك البحث قوقل.
إلى هنا نصل الى ختام هذه الجولة وارجوا أن تكونوا إستمتعتم وإستفدتم وأي إستفسار أرجو تركه في التعليقات .