تجاوز بعض طبقات الحزمة في بيثون سكابي
-
21-12-2019 - |
سؤال
أريد بناء حزمة إب مع جزء شبكة محلية ظاهرية.يتم ذلك بسهولة مع سكابي:
from scapy import inet
newpkt = inet.Ether()/inet.Dot1Q()/inet.IP()
أحيانا أريد أن يكون inet.Dot1Q()
في الحزمة ، في بعض الأحيان لا.ما يجب أن تكون القيمة الافتراضية ل inet.Dot1Q()
لذلك يتم تجاوزه ببساطة في المشغل'/'?حاولت ''
و None
- إنهم لا يعملون.
from scapy import inet
myDot1Q = SOME DEFAULT VALUE
newpkt = inet.Ether()/myDot1Q/inet.IP()
#new packet is a valid IP packet here
تحرير:تفسير مختلف لمشكلتي
1) يمكنني إنشاء حزمة مع علامة شبكة محلية ظاهرية
inet.Ether()/inet.Dot1Q/inet.IP()
2) يمكنني إنشاء حزمة مع علامة شبكة محلية ظاهرية مزدوجة
inet.Ether()/inet.Dot1Q/inet.Dot1Q/inet.IP()
3) كيف يمكنني بناء حزمة التي قد تكون حزمة غير ملحوظ, شبكة محلية ظاهرية الموسومة حزمة أو مزدوجة شبكة محلية ظاهرية الموسومة حزمة?سيكون من الرائع أن يكون لديك شيء مثل:
#No VLAN
myVlan = ???
myDoubleVlan = ???
#VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = ???
#Double VLAN
myVlan = inet.Dot1Q()
myDoubleVlan = inet.Dot1Q()
#In any case the packet structure should remain the same
inet.Ether()/myVlan/myDoubleVlan/inet.IP()
لا يمكنني معرفة القيمة الافتراضية ???
يجب أن تكون قادرة على بناء الحزمة بشكل صحيح.
المحلول
بادئ ذي بدء ، لا يمكنني التفكير في أي سبب لعدم استخدام حل بسيط مثل هذا:
# example for single Vlan
# myVlan = Dot1Q()
# myDoubleVlan = None
# generate the package
package = Ether()
if myVlan: package /= myVlan
if myDoubleVlan: package /= myDoubleVlan
package /= IP()
ولكن على أي حال ، إذا كان هذا النهج غير مقبول لأي سبب من الأسباب ، فهناك احتمال آخر...
هل يمكن تجاوز Packet
الطبقة وخلق الطبقة الخاصة بك التي هي محايدة لمشغل الانقسام.الشيء الوحيد الذي تحتاجه هو تجاوز __div__
طريقة وإضافة بعض الأقواس للحفاظ على الأسبقية الصحيحة.
هذه هي الطريقة التي ستنفذها:
from scapy.all import *
class NeutralPacket(Packet):
def __init__(self, _pkt="", _internal=0, **fields):
super(NeutralPacket, self).__init__(_pkt, _internal, **fields)
def __div__(self, other):
return other
#No VLAN
myVlan = NeutralPacket()
myDoubleVlan = NeutralPacket()
#VLAN
myVlan = Dot1Q()
myDoubleVlan = NeutralPacket()
#Double VLAN
myVlan = Dot1Q()
myDoubleVlan = Dot1Q()
# this part doesn't need to change, but you need to have two
# additional parenthesis for proper precedence
Ether()/(myVlan/(myDoubleVlan/IP()))
شرح إضافي:
ال __div__()
الطريقة هي التقسيم operator
التنفيذ.المترجم ينفذ a/b
كما a.__div__(b)
, ، و ال Packet
الطبقة لديها تنفيذها الخاص لهذا المشغل.إذا كنت نلقي نظرة على لها كود, ، يمكنك أن ترى أن إلحاق أساسا payload
من الحزمة b
لحزمة a
.
ما نقوم به هنا بدلا من ذلك هو مجرد العودة other
حزمة ، ويجري b
في هذه الحالة ، تجاهل فعال a
تماما.
لاحظ أن هذا يعمل فقط في اتجاه واحد ، عندما NeutralPacket
هو عامل الجانب الأيسر ، لأنه بخلاف ذلك يكون فئة البعض الآخر __div__()
الطريقة التي يتم تنفيذها.للتعامل مع هذا ، علينا أن نضيف قوسين بحيث الأسبقية سيجعل لدينا NeutralPacket
فئة يكون دائما المشغل الجانب الأيسر.وبما أن هذا لا يؤثر على النتيجة الإجمالية بسبب Packet
التنفيذ ، وهذا يعمل بشكل جيد لقضيتك.الشيء الوحيد الذي لن ينجح هو إذا كان NeutralPacket
سيكون الجانب الأيمن (أي.المشغل الأخير) ، منذ ذلك الحين لم تتمكن من فرض الأسبقية الصحيحة.ولكن بالنسبة لشبكة محلية ظاهرية هذه ليست قضية ، لأن هناك دائما طبقات فوقه..
نصائح أخرى
كنت قد نسيت تماما عن Raw()
.
ال Raw
الطبقة هي ما تريد.
Raw()
, إذا لم يتم وضع أي بيانات هناك ، فلن تضيف شيئا إلى الحزمة التي تم إنشاؤها.يمكنك استخدام هذا كقيمة افتراضية ل myDot1Q
متغير.
>>> b = Raw() / ICMP()
>>> a = Raw() / ICMP()
>>> b = ICMP()
>>> a.show()
###[ Raw ]###
load= ''
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
>>> b.show()
###[ ICMP ]###
type= echo-request
code= 0
chksum= None
id= 0x0
seq= 0x0
>>> a.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> b.build()
'\x08\x00\xf7\xff\x00\x00\x00\x00'
>>> a.build() == b.build()
True