esp32_bluetooth_classic_sni.../libs/scapy/contrib/oncrpc.py
Matheus Eduardo Garbelini 86890704fd initial commit
todo: add documentation & wireshark dissector
2021-08-31 19:51:03 +08:00

162 lines
4.9 KiB
Python
Executable file

# This file is part of Scapy
# See http://www.secdev.org/projects/scapy for more information
# Copyright (C) Lucas Preston <lucas.preston@infinite.io>
# This program is published under a GPLv2 license
# scapy.contrib.description = ONC-RPC v2
# scapy.contrib.status = loads
from scapy.fields import XIntField, IntField, IntEnumField, StrLenField, \
FieldListField, ConditionalField, PacketField
from scapy.packet import Packet, bind_layers
import struct
class Object_Name(Packet):
name = 'Object Name'
fields_desc = [
IntField('length', 0),
StrLenField('_name', '', length_from=lambda pkt: pkt.length),
StrLenField('fill', '', length_from=lambda pkt: (4 - pkt.length) % 4)
]
def set(self, name, length=None, fill=None):
if length is None:
length = len(name)
if fill is None:
fill = b'\x00' * ((4 - len(name)) % 4)
self.length = length
self._name = name
self.fill = fill
def extract_padding(self, s):
return '', s
class RM_Header(Packet):
name = 'RM Header'
fields_desc = [
XIntField('rm', None)
]
def post_build(self, pkt, pay):
"""Override of post_build to set the rm header == len(payload)"""
if self.rm is None:
new_rm = 0x80000000 + len(self.payload)
pkt = struct.pack('!I', new_rm)
return Packet.post_build(self, pkt, pay)
class RPC(Packet):
name = 'RPC'
fields_desc = [
XIntField('xid', 0),
IntEnumField('mtype', 0, {0: 'CALL', 1: 'REPLY'}),
]
class Auth_Unix(Packet):
name = 'AUTH Unix'
fields_desc = [
XIntField('stamp', 0),
PacketField('mname', Object_Name(), Object_Name),
IntField('uid', 0),
IntField('gid', 0),
IntField('num_auxgids', 0),
FieldListField(
'auxgids', [], IntField('', None),
count_from=lambda pkt: pkt.num_auxgids
)
]
def extract_padding(self, s):
return '', s
class RPC_Call(Packet):
name = 'RPC Call'
fields_desc = [
IntField('version', 2),
IntField('program', 100003),
IntField('pversion', 3),
IntField('procedure', 0),
IntEnumField('aflavor', 1, {0: 'AUTH_NULL', 1: 'AUTH_UNIX'}),
IntField('alength', None),
ConditionalField(
PacketField('a_unix', Auth_Unix(), Auth_Unix),
lambda pkt: pkt.aflavor == 1
),
IntEnumField('vflavor', 0, {0: 'AUTH_NULL', 1: 'AUTH_UNIX'}),
IntField('vlength', None),
ConditionalField(
PacketField('v_unix', Auth_Unix(), Auth_Unix),
lambda pkt: pkt.vflavor == 1
)
]
def set_auth(self, **kwargs):
"""Used to easily set the fields in an a_unix packet"""
if kwargs is None:
return
if 'mname' in kwargs:
self.a_unix.mname.set(kwargs['mname'])
del kwargs['mname']
for arg, val in kwargs.items():
if hasattr(self.a_unix, arg):
setattr(self.a_unix, arg, val)
self.alength = 0 if self.aflavor == 0 else len(self.a_unix)
self.vlength = 0 if self.vflavor == 0 else len(self.v_unix)
def post_build(self, pkt, pay):
"""Override of post_build to handle length fields"""
if self.aflavor == 0 and self.vflavor == 0:
# No work required if there are no auth fields,
# default will be correct
return Packet.post_build(self, pkt, pay)
if self.aflavor != 0 and self.alength is None:
pkt = pkt[:20] \
+ struct.pack('!I', len(self.a_unix)) \
+ pkt[24:]
return Packet.post_build(self, pkt, pay)
if self.vflavor != 0 and self.vlength is None:
pkt = pkt[:28] \
+ struct.pack('!I', len(self.v_unix)) \
+ pkt[32:]
return Packet.post_build(self, pkt, pay)
class RPC_Reply(Packet):
name = 'RPC Response'
fields_desc = [
IntField('reply_stat', 0),
IntEnumField('flavor', 0, {0: 'AUTH_NULL', 1: 'AUTH_UNIX'}),
ConditionalField(
PacketField('a_unix', Auth_Unix(), Auth_Unix),
lambda pkt: pkt.flavor == 1
),
IntField('length', 0),
IntField('accept_stat', 0)
]
def set_auth(self, **kwargs):
"""Used to easily set the fields in an a_unix packet"""
if kwargs is None:
return
if 'mname' in kwargs:
self.a_unix.mname.set(kwargs['mname'])
del kwargs['mname']
for arg, val in kwargs.items():
if hasattr(self.a_unix, arg):
setattr(self.a_unix, arg, val)
self.length = 0 if self.flavor == 0 else len(self.a_unix)
bind_layers(RPC, RPC_Call, mtype=0)
bind_layers(RPC, RPC_Reply, mtype=1)