الأحد، 2 سبتمبر 2012

برمجة sniffer بواسطة البايثون (الجزء الأول )

بسم الله الرحمن الرحيم

مقدمة :

في أغلب البرامج التي تتعامل مع الشبكة يتعامل المبرمج مع طبقة التطبيقات "Application Layer" بواسطة الواجهة SOCK_STREAM للبرامج العاملة بواسطة بروتوكول TCP و الواجهة SOCK_DGRAM للبرامج التي تستخدم بروتوكول UDP .

 

و تقوم هذه الواجهتين بتسهيل عملية البرمجة و أخذ جميع المهام من المبرمج , و قد شرحت هذه الواجهتين في هذا الموضوع .


و لكن هنالك بعض البرامج التي تتطلب التحكم الكامل في جميع طبقات الشبكة , مثل مثالنا و هو برامج تعقب حركة الحزم في الشبكة "Sniffer" و لذا تم تصميم الواجهة RAW_SOCK التي تسمح لي المبرمج من الحصول على الحزم المرسلة عبر الشبكة بكامل بياناتها , و كما يمكن المبرمج من بناء الحزم "packet" من الصفر , و لذا فأن أنظمة التشغيل التي تحتوي على هذه الواجهة تلزم المستخدم للبرامج التي تستخدم هذه الواجهة بأن يكون لديه صلاحية المستخدم الجذر "Root" أو administrator في نظام ويندوز  .

  • إنشاء القابس الخام في البايثون (Raw socket) :
import socket

sos=socket.socket(socket.AF_INET,socket.SOCK_RAW)


في السطر الأول قمنا بأستدعاء المكتبة  socket , أما السطر الثاني فقمنا بإنشاء المقبس و هذا شرح معاملات القابس :

socket.AF_INET,socket.SOCK_RAW

1. AF_INET     : نوع العناوين المستخدمة و في حالتنا ستكون عناوين IP الإصدارة الرابعة .
2. SOCK_RAW : نوع القابس و في حالتنا قابس خام .

يمكن تعديل الأستدعاء الخاص بالقابس بأضافة معامل ثلاث , لتحديد نوع البرتوكول الذي ستتعامل معه و يفيد هذا المعامل في حالة أردت أن تصنع برنامج يراقب حزم برتوكول ICMP مثالا :

sos=socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)

في هذه الحالة ستقوم نواة نظام التشغيل بأرسال نسخ من حزم ICMP فقط لبرنامجنا .

  • البدأ في استقبال البيانات :
while 1:

        data=sos.recv(1245)

        print data

قمنا بإنشاء حلقة تكرارية ثم أستقبال البيانات و حفظها بالمتغير data , و في النهاية سنطبع هذه البيانات, عند تنفيذ البرنامج سيطبع بيانات غير مقروء لك , لذا في الجزء الثاني سنستخدم مكتبة struct للحصول على البيانات بشكل مقروء لنا .

هذا البرنامج تم تنفيذه على نظام لينكس , و لمستخدمي نظام و يندوز هنالك  خطوتين أضافية :

  • حجز الواجهة (bind) :
HOST = socket.gethostbyname(socket.gethostname())

sos.bind((HOST, 0))

حجزنا الواجهة التي يتم أرسال و أستقبال البيانات عليها في نظام لينكس .

  • تضمين جميع بيانات حزمة IP :

sos.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

الطلب من النظام إرسال جميع بيانات الحزم من دون تعديل .

 

النص البرمجي الكامل لمثالنا في لينكس 
import socket

sos=socket.socket(socket.AF_INET,socket.SOCK_RAW)
while 1:

        data=sos.recv(1245)

        print data


النص البرمجي الكامل في نظام و يندوز

import socket
HOST = socket.gethostbyname(socket.gethostname())
sos=socket.socket(socket.AF_INET,socket.SOCK_RAW)

sos.bind((HOST, 0))

sos.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

while 1:

        data=sos.recv(1245)

        print data



الرجاء ذكر المصدر عند النسخ

    هناك تعليقان (2):

    1. شرحٌ جميل، و إن كنتُ أتمني أن تقوم بتكبير الخط بعض الشيء *0*

      جميلةٌ هي البايثون و مريحة، و تختصر الكثير من الجهد و الوقت.

      ردحذف
    2. استمر اخوي بس ياريت تشرح كيف تعمل عملية اتصال بين جهازين مع بعض بستخدام مكتبة socket
      وشكرا لك

      ردحذف