
الكود المصدري لكتاب "Violent Python" من تأليف TJ O'Connor. تم تحويل الكود بالكامل إلى Python 3، وإعادة تنسيقه ليتوافق مع معايير PEP8، وإعادة هيكلته لإزالة مشكلات التبعيات المتعلقة بتطبيق المكتبات المهجورة.
كود مصدر الكتاب "Violent Python" للمؤلف TJ O'Connor. تم تحويل الكود بالكامل إلى بايثون 3، وإعادة تنسيقه للامتثال لمعايير PEP8، وإعادة هيكلته لإزالة مشاكل الاعتماد على المكتبات القديمة المهجورة.
لقد قمت بنشر تحويل مشابه لهذا على الكود المصدري لكتاب "Black Hat Python" لجاستن سايتز. تحقق منه هنا إذا لم تكن قد قمت به بعد.
ببساطة أنشئ دليلاً جديداً (DIR) للمشروع، وأنشئ
بيئة افتراضية أو venv له (موصى به)، واستنسخ هذا المستودع
باستخدام git clone ثم ثبّت المتطلبات باستخدام pip install.
user@host:~/DIR$ git clone https://github.com/EONRaider/violent-python3
user@host:~/DIR$ python3 -m venv venv
user@host:~/DIR$ source venv/bin/activate
(venv) user@host:~/DIR$ pip install -r requirements.txt
optparse المهجورة الآن بمكتبة argparse
في جميع أنحاء الكود المصدري. أصبح تحليل جميع الوسائط محتوىً الآن
تحت نطاق تنفيذ __main__ لكل ملف. جميع وسائط سطر الأوامر CLI التي كانت
إلزامية لتنفيذ البرامج النصية لكنها عُوملت كاختيارية في
الكود الأصلي تُنفَّذ الآن كوسائط موضعية. رسالة الاستخدام أصبحت
متاحة لجميع البرامج النصية التي تستخدم argparse عن طريق توفير وسيط -h إلى
سطر الأوامر CLI. إن إسناد مسؤوليات كل من الحدود
والكائن المتحكم إلى محلل سطر الأوامر CLI ليس بالتأكيد الخيار الأفضل من حيث
بنية البرمجيات، لكنه تُرك كما هو نظراً
لضرورة الامتثال لنية المبرمج الأصلي.PEP 8: E722 do not use bare except تمت
إعادة هيكلتها باستخدام عبارات استثناء أكثر تحديداً.close() على كائنات الملف/قاعدة البيانات المفتوحة. لهذا
السبب
تمت إعادة هيكلة جميع حالات التعامل مع الملفات وقواعد البيانات
باستخدام مديري السياق.# -*- coding: utf-8 -*-) بسبب
توحيد UTF-8 كترميز افتراضي لبايثون 3 (بدلاً من
ASCII في بايثون 2).يمكن اعتبار أن الملفات غير المدرجة أدناه قد أعيدت هيكلتها بطريقة أو بأخرى على النحو المحدد في قسم "ملاحظات".
chapter01/vuln_scanner.py مهيكلاً بطريقة تجعل ملفاً غير موجود يؤدي إلى استثناء OSError في وقت التشغيل. لهذا
السبب، تم نقل التحكم بالتكرار الذي يستدعي check_vulns() إلى
العبارة الشرطية المعرفة في الدالة الرئيسية.chapter02/nmap_scan.py ينفذ دالة رئيسية فقط بغرض
استدعاء مكتبة optparse المهجورة، والتي تم استبدالها بـ
argparse. ولهذا السبب تمت إزالة الدالة الرئيسية. كان هناك تكرار
هيكل تحكم كان جزءاً من استدعاء optparse في الكود
الأصلي، وقد نُفذ بطريقة تجعل استدعاءً جديداً لـ nmap يُنفذ
لكل منفذ يتم فحصه. تم نقل التكرار إلى nmap_scan
لمنع إهدار الدورات.chapter02/ssh_command.py إلى
نطاق تنفيذ __main__. أسماء المتغيرات المستخدمة في النطاق الخارجي
التي كانت تتعارض مع أسماء معاملات الدوال تم
تغييرها. كانت معلومات المطالبة (prompt) المرتجعة مشفرة في الأصل، والآن
تم فك تشفيرها من أجل تحسين القراءة.chapter02/ssh_brute.py مكتبة pxssh كمكتبة مستقلة، لكن
في الحقيقة هي مكتبة داخل مكتبة . أدى الخطأ إلى
وتم تصحيحه. الكود نفسه كما ورد في
الكتاب كان مليئاً بأخطاء المسافات البادئة مما جعله غير قابل للاستخدام وقد
أُعيد إلى حالة تعمل.يمكن الاطلاع على المساهمات بلغات أخرى هنا:
من باب المنطق السليم، حاول أولاً مناقشة التغيير الذي ترغب في إجرائه على هذا المستودع عبر issue.
pexpectModuleNotFoundErrorchapter02/ssh_brutekey.py عدداً من المفاتيح المولّدة مسبقاً للعمل؛
علاوة على ذلك، يوجّه الكتاب القارئ للحصول على هذه المفاتيح من رابط
يعيد حالياً استجابة 403. لهذا السبب تمت إضافة أرشيف مضغوط
يحتوي على المفاتيح إلى الدليل الفرعي chapter02.chapter02/ssh_botnet.py عبارة استيراد غير مستخدمة لـ optparse وقد
تمت إزالتها. يبدو أنها قطعة من محاولة ملغاة
لتطبيق CLI لهذا البرنامج النصي. والمفاجئ أنها تُركت معلقة هناك,
حتى في النسخة المطبوعة من الكتاب. تم تنظيم الكود الذي يهيئ
شبكة البوتنت ويصدر أوامرها تحت نطاق تنفيذ __main__
بغرض التوحيد القياسي. تم توحيد الأمرين اللذين يصدران إلى البوتات
لتجنب عدد غير ضروري من عبارات الإرجاع.chapter02/conficker.py أزال استدعاءً غير مستخدم لمكتبة sys.chapter03/discover_networks.py بدلاً من مجرد
إعادة هيكلته. ففي الأصل لم يستخدم فقط مكتبة mechanize المهجورة بل
كان يتفاعل أيضاً مع خدمة WiGLE بطريقة لم تعد ضرورية,
إذ توفر WiGLE الآن واجهة برمجة تطبيقات (API). لهذا السبب تم توحيد الكود
وتم تنفيذ دالة جديدة wigle_print باستخدام requests library لإرسال طلب GET مصادق عليه عبر HTTP إلى WiGLE.
يعيد الاستجابة كائن JSON يمكن الوصول إليه مباشرة، مما يجعل
استخدام مكتبة re غير ضروري أيضاً. تمت إضافة معالجة الاستثناءات
لجعل البرنامج النصي قادراً على التعامل مع رسائل الخطأ
المرسلة من الواجهة البرمجية. لاحظ أن
هذا البرنامج النصي يعتمد على winreg، والتي تعمل فقط على تثبيتات بايثون
تحت نظام التشغيل Microsoft Windows، وتتطلب صلاحيات المسؤول
أثناء التنفيذ للوصول إلى مفاتيح السجل. يجب إنشاء حساب
مسجل على https://wigle.net/account للوصول إلى الواجهة.chapter03/pdf_read.py الآن مكتبة PyPDF4 بدلاً من
مكتبة PyPDF المهجورة. يشير الكتاب في نصه إلى ملف PDF محدد و
تمت إضافته إلى الدليل الفرعي chapter03.chapter03/exif_fetch.py وسيطاً features="html.parser" في
استدعاء مُنشئ كائن BeautifulSoup. تمت إضافته في السطر 15
. يعمل هذا البرنامج النصي فقط على تطبيقات الويب التي تغلف الصور بين وسوم img
وسوم HTML (وهي ممارسة نادرة في تطبيقات الويب الحديثة التي تعتمد بشكل كبير على
JavaScript).chapter03/skype_parse.py ملف main.db كمثال. وقد تمت
إضافته إلى الدليل الفرعي chapter03/skype_profile للراحة.chapter03/firefox_parse.py عدة ملفات .sqlite كأمثلة.
تمت إضافتها إلى الدليل الفرعي chapter03/firefox_profile من
أجل الراحة.chapter03/iphone_messages.py إلى ملفات نسخ احتياطي للآيفون لم
يتم توفيرها من قبل المؤلف. لهذا السبب تمت إعادة هيكلة الكود
لكنه لا يزال غير مختبر.chapter04/geo_ip.py مكتبة pygeoip المهجورة. كما
اقترح منشئها،
geoip2 يجب أن يُستخدم الآن. جرت محاولة لإبقاء الكود
مشابهاً قدر الإمكان للتنفيذ الأصلي في
الكتاب، لكن كان لا بد من إجراء بعض التغييرات لاستيعاب الحزمة الجديدة
بنية geoip2 وخصائصها. ملف قاعدة البيانات اللازم
لتشغيل البرنامج النصي تم تنزيله من
MaxMind وتم توفيره
في دليل chapter04. كما تم تنفيذ CLI
باستخدام argparse.chapter04/print_direction.py يثير استثناء UnicodeDecodeError عند
فتح الملف في التنفيذ الأصلي. تم إصلاح ذلك بإضافة
وسيط rb إلى مدير السياق الذي يتعامل مع الملف.chapter04/find_ddos.py يطبع عنوان المصدر لهجوم Hivemind
كوجهة له، مما جعل المخرجات عديمة الفائدة. المتغير الصحيح dst
يتم الآن عرضه على stdout. يشير الكتاب إلى ملف باسم
traffic.pcap لم يوفره المؤلف، لذلك تمت إعادة هيكلة الكود
لكنه يبقى غير مختبر.chapter04/test_domain_flux.py صفر طلبات بدون إجابة عند
تحليل ملف pcap المقدم من المؤلف. لسبب ما،
لا تحتوي الحزم نفسها على قيمة حقل سجل موارد DNS (DNS Resource Record) معيّنة،
لذا فإن الشرط في دالة dns_QR_test يُقيَّم دائمًا على أنه خطأ.
وبما أن الأمر كذلك، فقد تمت إزالة الشرط الذي يقيّم حقل DNSRR
من
العبارة الشرطية، وأصبح يتم الآن تحليل جميع حزم UDP التي يكون منفذها 53 كمصدر
لها. يؤدي ذلك إلى كود أقل كفاءة لكنه
على الأقل يُخرج النتائج كما هو مقصود في الكتاب.chapter05/blue_bug.py مكتبة PyBluez، والتي تطلب بدورها
مكتبة BlueZ وملفات الرأس كما هو مذكور في
تعليمات التثبيت.
يجب تثبيت هذه التبعيات قبل تثبيت PyBluez كشرط
أساسي. في لينكس يمكن القيام بذلك عن طريق إصدار الأمر
apt install bluetooth libbluetooth-dev. يشير الكود الأصلي إلى
كائن client_sock غير موجود وقد تم استبداله بـ phone_sock.chapter05/ftp_sniff.py خلل منطقي جعله يعرض اسماً
مختلساً لكن بدون كلمة مرور بسبب تنفيذ ضعيف لشرط if... else
تم تصحيح ذلك باستبدال العبارة الشرطية
بعبارة if متداخلة.chapter05/ninja_print.py مكتبة obexftp لكي يعمل. هذه
المكتبة كُتبت لبايثون 2 ولم يتم نقلها
أو استبدالها بمكتبة مكافئة حتى تاريخه، لذلك يظل الكود
كما كتبه المؤلف في نسخته لبايثون 2.chapter05/__init__.py وchapter06/__init__.py لتمكين
استيراد الوحدات من chapter05/dup.py وchapter06/anon_browser.py,
على التوالي.chapter06/anon_proxy.py باستخدام مكتبة MechanicalSoup
الخاصة ببايثون 3. وهو يدمج التعديلات التي كانت ضرورية
لـ proxy_test.py وuseragent_test.py وprint_cookies.py.chapter06/anon_browser.py أيضاً باستخدام MechanicalSoup
وخضع لبعض التعديلات في الكود. تم استبدال مكتبة cookielib
بـ http.cookiejar في طريقة البناء للفئة
AnonBrowser وأصبح المعامل user_agents يقبل الآن قائمة من
السلاسل النصية بدلاً من صف (tuple).chapter06/link_parser.py باستخدام طرق جديدة للتعامل
مع تطبيقات re وbs4.