مكتبة struct في بايثون
مكتبة ( struct ) في لغة Python, بدأنا بجزء خاص في ما يسمى sniffing و توجد لدينا مكتبة مهمة في لغة بايثون python تساعدنا كثيراً في السنيفينغ إسمها struct تُفيدنا بهذا القسم و هي تعني أنه نأخذ البيانات الموجودة لدينا و نعمل لها packing لتحويلها إلى بايت Byte لكي تسير في الشبكة و unpacking العكس لإرجاعها.
توجد لدينا فورمات Format تُمكننا من هذا العمل لكن يلزم أن نعرف أنه يوجد كركترز Caracter معين.
ترتيب البايت و الحجم و المحاذاة struct
بشكل إفتراضي يتم تمثيل أنواع C في التنسيق الأصلي للجهاز و يتم ترتيب البايت byte و يتم محاذاتها بشكل صحيح عن طريق تخطي البايتات السيئة إذا لزم الأمر وفقاً للقواعد المستخدمة بواسطة المترجم C compiler.
و بدلاً من ذلك يمكن إستخدام الحرف الأول من سلسلة التنسيق من أجل الإشارة إلى ترتيب البايت و حجم و محاذاة البيانات المعبأة وفقاً للجدول الآتي:
Character | Byte order | Size | Alignment |
@ | native | اnative | native |
== | native | Standard | none |
< | little-endian | Standard | none |
> | big-endian | Standard | none |
! | networks | Standard | none |
شرح الجدول السابق
- الـ @ هذا الإفتراضي يكون إن لم نستخدم أحد التاليات.
- الـ = بنفس مبدأ @ لكن حجم و المحاذاة هنا تكون موحدة.
- الـ > للعمل little endian.
- الـ < للعمل على big endian.
- الـ ! تستخدم في الشبكات.
و يتم إضافة المساحة المتروكة تلقائياً فقط بين أعضاء الهيكل و لا يتم إضافة حشوة في بداية أو نهاية البنية المشفرة, و لا تتم إضافة المساحة المتروكة عند إستخدام حجم و محاذاة غير أصليين على سبيل المثال بـ "<" و ">" و "=" و "!".
Format Characters library struct
يجب أن يكون التحويل بين قيم C و Python واضحاً نظراً لأنواعها و يشير عمود "Standard Size" إلى حجم القيمة المجمعة بالبايت, و عند إستخدام الحجم القياسي أي عندما تبدأ سلسلة التنسيق بأحد الرموز <، >، ! أو = و عند إستخدام الحجم الأصلي يعتمد حجم القيمة المجمعة على النظام الأساسي.
أمثلة عملية على مكتبة struct
لفهم مكتبة struct أكثر لا بد من توفير العديد من الأمثلة في إستخدام هذه المكتبة الرائعة و في هذه الفقرة سوف نقوم بشرح عدة أمثلة فيها.
>>> import struct >>> struct.pack("x") #pad bytes b'\x00' >>> struct.unpack("x",b' \x00') #عكس العملية السابقة () >>> struct.pack("c",b'F') #char b'F' >>> struct.pack("b",1) #signed char b'\x01' >>> struct.unpack("b",b'\x01') #عكس العملية السابقة (1,) >>> struct.pack("bb",1,2) #قيمتين b'\x01 x02' >>> struct.pack("2b",1,2) b'\x01 x02' >>> struct.unpack("2b",b'\x01\x02') #عكس السابقة (1, 2) >>> struct.pack("f",1.5) #float b'\x00\x00\xc0?' >>> struct.pack("b",1.5) #سيعطي خطأ لأنه ليس فلوت Traceback (most recent call last): File "<stdin>", line 1, in <module> struct.error: required argument is not an integer >>> struct.unpack("f",b'\x00\x00\xc0?') (1.5,) >>>
باقي الفورمات Format جربوها بأنفسكم من خلال الذهاب إلى موقع بايثون الرسمي أو كتابة الجملة "Format Characters python struct" في متصفح جوجل و إختيار نتيجة البحث الأولى.
إنشاء جلسة sniffing عبر socket و struct
سوف نستخدم في هذا الدرس الـ sniffing لكن الأفضل نستخدم مكتبة socket أفضل من scapy في الويندوز. لكن توجد مشاكل بتنزيل سكابي على إصدارات ويندوز المُختلفة, سكابي تكون أفضل على لينكس linux, سوف نستخدم في هذا الدرس socket و struct. لفتح جلسة sniffing يجب اولاً أن نستخدم الشل بصلاحيات adminstrator.
import socket import struct #ethnet header 0:14 !6s6s2s #ipheader 14:34 !12s4s4s #tcpheader 34:54 !HH16s s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP) s.bind(("127.0.0.1",0)) s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1) s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON) while True: data = s.recvfrom(10000) #ethernet header ethernetheader = data[0][0:14] eth_hdr = struct.unpack("!6s6s2s",ethernetheader) print(eth_hdr[0]) print(eth_hdr[1]) print(eth_hdr[2]) #ipheader ipheader = data[0][14:34] print(ipheader) #tcpheader tcpheader = data[0][34:54] #tcp_h = struct.unpack("!HH16s",tcpheader) print(tcpheader)
قُمنا في البداية بإستدعاء للمكتبات عبر الأمر import و المكتبات المطلوبة هي socket و struct و أنشأنا متغير من أجل تعيين الجلسة s = socket.socket و كتبنا له الأذرفاميلي AF_INET يعني IPV4 و SOCK_RAW تعني عمل sniff للـ raw و socket.IPPROTO_IP إخترنا له الآيبي بروتوكول.
و بعدها عملنا bind على local host لدينا و البورت حددناه 0 و setsockopt نحدد له الآيبي بروتوكول لدينا و أعطينا قيمة IP_HDRINCL القيمة 1 و هذه الخطوات هي خطوات أساسية مهمة في الويندوز و لا يجب الإستغناء عنها.
و الميثود ioctl يجب ايضاً أن تكون مفعلة في و يندوز من أجل عمل إستقبال rcv للبيانات و ممكن أن تكون off لكن نحن هنا وضعناها on و بعدها خزننا كل هذا في data و صورة الداتا تكون 10000.
تعليقات سكربت الجلسة
- تعليق ethnet header 0:14 !6s6s2s : يأخذ بايتس Bytes من 0 حتى 14 و الفورمات له هي !6s6s2s تعني 6+6+2 تساوي 14 أي من 0 حتى 14 و علامة التعجب تكلمنا عنها بدروس سابقة أنها تستخدم مع الشبكات.
- تعليق ipheader 14:34 !12s4s4s : يعني ipheader يأخذ من 14 حتى 34 و باقي الشرح نفس سابقتها.
- تعليق tcpheader 34:54 !HH16s : الـ tcpheader يأخذ من 34 حتى 54 و الفورمات لها !HH16 و كل حرف H يأخذ 2 بايتس Bytes.