Skip to content

Commit 06afa39

Browse files
authored
PcapNg - Apple Process Information Block (#4396)
1 parent 160e20d commit 06afa39

File tree

3 files changed

+68
-6
lines changed

3 files changed

+68
-6
lines changed

scapy/packet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ class Packet(
100100
"direction", "sniffed_on",
101101
# handle snaplen Vs real length
102102
"wirelen",
103-
"comment"
103+
"comment",
104+
"process_information"
104105
]
105106
name = None
106107
fields_desc = [] # type: List[AnyField]
@@ -178,6 +179,7 @@ def __init__(self,
178179
self.direction = None # type: Optional[int]
179180
self.sniffed_on = None # type: Optional[_GlobInterfaceType]
180181
self.comment = None # type: Optional[bytes]
182+
self.process_information = None # type: Optional[Dict[str, Any]]
181183
self.stop_dissection_after = stop_dissection_after
182184
if _pkt:
183185
self.dissect(_pkt)

scapy/utils.py

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from decimal import Decimal
1212
from io import StringIO
1313
from itertools import zip_longest
14+
from uuid import UUID
1415

1516
import array
1617
import argparse
@@ -1646,7 +1647,8 @@ class RawPcapNgReader(RawPcapReader):
16461647
PacketMetadata = collections.namedtuple("PacketMetadataNg", # type: ignore
16471648
["linktype", "tsresol",
16481649
"tshigh", "tslow", "wirelen",
1649-
"comment", "ifname", "direction"])
1650+
"comment", "ifname", "direction",
1651+
"process_information"])
16501652

16511653
def __init__(self, filename, fdesc=None, magic=None): # type: ignore
16521654
# type: (str, IO[bytes], bytes) -> None
@@ -1668,8 +1670,10 @@ def __init__(self, filename, fdesc=None, magic=None): # type: ignore
16681670
3: self._read_block_spb,
16691671
6: self._read_block_epb,
16701672
10: self._read_block_dsb,
1673+
0x80000001: self._read_block_pib,
16711674
}
16721675
self.endian = "!" # Will be overwritten by first SHB
1676+
self.process_information = [] # type: List[Dict[str, Any]]
16731677

16741678
if magic != b"\x0a\x0d\x0d\x0a": # PcapNg:
16751679
raise Scapy_Exception(
@@ -1868,6 +1872,18 @@ def _read_block_epb(self, block, size):
18681872

18691873
# Parse options
18701874
options = self._read_options(block[opt_offset:])
1875+
1876+
process_information = {}
1877+
for code, value in options.items():
1878+
if code in [0x8001, 0x8003]: # PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX
1879+
proc_index = struct.unpack(self.endian + "I", value)[0]
1880+
if proc_index < len(self.process_information):
1881+
key = "proc" if code == 0x8001 else "eproc"
1882+
process_information[key] = self.process_information[proc_index]
1883+
else:
1884+
warning("PcapNg: EPB invalid process information index "
1885+
"(%d/%d) !" % (proc_index, len(self.process_information)))
1886+
18711887
comment = options.get(1, None)
18721888
epb_flags_raw = options.get(2, None)
18731889
if epb_flags_raw:
@@ -1884,6 +1900,7 @@ def _read_block_epb(self, block, size):
18841900

18851901
self._check_interface_id(intid)
18861902
ifname = self.interfaces[intid][2].get('name', None)
1903+
18871904
return (block[20:20 + caplen][:size],
18881905
RawPcapNgReader.PacketMetadata(linktype=self.interfaces[intid][0], # noqa: E501
18891906
tsresol=self.interfaces[intid][2]['tsresol'], # noqa: E501
@@ -1892,7 +1909,8 @@ def _read_block_epb(self, block, size):
18921909
wirelen=wirelen,
18931910
comment=comment,
18941911
ifname=ifname,
1895-
direction=direction))
1912+
direction=direction,
1913+
process_information=process_information))
18961914

18971915
def _read_block_spb(self, block, size):
18981916
# type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]
@@ -1918,7 +1936,8 @@ def _read_block_spb(self, block, size):
19181936
wirelen=wirelen,
19191937
comment=None,
19201938
ifname=None,
1921-
direction=None))
1939+
direction=None,
1940+
process_information={}))
19221941

19231942
def _read_block_pkt(self, block, size):
19241943
# type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]
@@ -1941,7 +1960,8 @@ def _read_block_pkt(self, block, size):
19411960
wirelen=wirelen,
19421961
comment=None,
19431962
ifname=None,
1944-
direction=None))
1963+
direction=None,
1964+
process_information={}))
19451965

19461966
def _read_block_dsb(self, block, size):
19471967
# type: (bytes, int) -> None
@@ -1995,6 +2015,35 @@ def _read_block_dsb(self, block, size):
19952015
else:
19962016
warning("PcapNg: Unknown DSB secrets type (0x%x)!", secrets_type)
19972017

2018+
def _read_block_pib(self, block, _):
2019+
# type: (bytes, int) -> None
2020+
"""Apple Process Information Block"""
2021+
2022+
# Get the Process ID
2023+
try:
2024+
dpeb_pid = struct.unpack(self.endian + "I", block[:4])[0]
2025+
process_information = {"id": dpeb_pid}
2026+
block = block[4:]
2027+
except struct.error:
2028+
warning("PcapNg: DPEB is too small (%d). Cannot get PID!",
2029+
len(block))
2030+
raise EOFError
2031+
2032+
# Get Options
2033+
options = self._read_options(block)
2034+
for code, value in options.items():
2035+
if code == 2:
2036+
process_information["name"] = value.decode("ascii", "backslashreplace")
2037+
elif code == 4:
2038+
if len(value) == 16:
2039+
process_information["uuid"] = str(UUID(bytes=value))
2040+
else:
2041+
warning("PcapNg: DPEB UUID length is invalid (%d)!",
2042+
len(value))
2043+
2044+
# Store process information
2045+
self.process_information.append(process_information)
2046+
19982047

19992048
class PcapNgReader(RawPcapNgReader, PcapReader):
20002049

@@ -2013,7 +2062,7 @@ def read_packet(self, size=MTU, **kwargs):
20132062
rp = super(PcapNgReader, self)._read_packet(size=size)
20142063
if rp is None:
20152064
raise EOFError
2016-
s, (linktype, tsresol, tshigh, tslow, wirelen, comment, ifname, direction) = rp
2065+
s, (linktype, tsresol, tshigh, tslow, wirelen, comment, ifname, direction, process_information) = rp # noqa: E501
20172066
try:
20182067
cls = conf.l2types.num2layer[linktype] # type: Type[Packet]
20192068
p = cls(s, **kwargs) # type: Packet
@@ -2031,6 +2080,7 @@ def read_packet(self, size=MTU, **kwargs):
20312080
p.wirelen = wirelen
20322081
p.comment = comment
20332082
p.direction = direction
2083+
p.process_information = process_information.copy()
20342084
if ifname is not None:
20352085
p.sniffed_on = ifname.decode('utf-8', 'backslashreplace')
20362086
return p

test/regression.uts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,16 @@ for i in range(len(plist)):
22742274
assert type(plist_check[i]) == type(plist[0])
22752275
assert bytes(plist_check[i]) == bytes(plist[i])
22762276

2277+
= PcapNg - Process Information Block
2278+
2279+
pib_pcapng_file = BytesIO(b'\n\r\r\n\xbc\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x02\x00\x05\x00arm64\x00\x00\x00\x03\x00f\x00Darwin Kernel Version 23.3.0: Thu Dec 21 02:29:41 PST 2023; root:xnu-10002.81.5~11/RELEASE_ARM64_T8122\x00\x00\x04\x00 \x00tcpdump (libpcap version 1.10.1)\x00\x00\x00\x00\xbc\x00\x00\x00\x01\x00\x00\x00 \x00\x00\x00\x01\x00\x00\x00\x00\x00\x08\x00\x02\x00\x03\x00en0\x00\x00\x00\x00\x00 \x00\x00\x00\x01\x00\x00\x80 \x00\x00\x00$\'\x00\x00\x02\x00\x06\x00trustd\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x01\x00\x00\x80$\x00\x00\x00")\x00\x00\x02\x00\x0c\x00mobileassetd\x00\x00\x00\x00$\x00\x00\x00\x06\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\xfb\x18\x06\x00EcqdB\x00\x00\x00B\x00\x00\x00\xe8\x9f\x80\xfa\x8c\xc6P\xa6\xd8\xd5\x83v\x08\x00E\x00\x004\x00\x00@\x00@\x06\x90T\nh\x01\xc3\xc0\xe5\xdd_\xf4\xb8\x00P\x95\xc3\xcb\x01\xcb\xeb\x11\xe8\x80\x11\x08\x00\x0c\xe6\x00\x00\x01\x01\x08\n\xbe\xb8\xd4\xb3\xbb\x9b4\xbc\x00\x00\x01\x80\x04\x00\x00\x00\x00\x00\x03\x80\x04\x00\x01\x00\x00\x00\x02\x00\x04\x00\x02\x00\x00\x00\x02\x80\x04\x00\x00\x00\x00\x00\x04\x80\x04\x00\x10\x00\x00\x00\x00\x00\x00\x00\x90\x00\x00\x00')
2280+
2281+
l = rdpcap(pib_pcapng_file)
2282+
assert(len(l) == 1)
2283+
assert(TCP in l[0])
2284+
assert(len(l[0].process_information) == 2)
2285+
assert(l[0].process_information["proc"]["name"] == "trustd")
2286+
22772287
= OSS-Fuzz Findings
22782288

22792289
from io import BytesIO

0 commit comments

Comments
 (0)