Skip to content

Commit

Permalink
feat(#313): Add support for conversion of multiple exported sessions.
Browse files Browse the repository at this point in the history
Rebased on master by @obilodeau. Some problems likely remain.
  • Loading branch information
alxbl authored and obilodeau committed Jan 7, 2022
1 parent aaf781f commit 2023ac6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 13 deletions.
9 changes: 3 additions & 6 deletions pyrdp/convert/ExportedPDUStream.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
from pyrdp.convert.PCAPStream import PCAPStream
from pyrdp.convert.pyrdp_scapy import *
from pyrdp.convert.utils import extractInetAddressesFromPDUPacket, InetAddress
from pyrdp.convert.utils import Exported, extractInetAddressesFromPDUPacket, InetAddress


class ExportedPDUStream(PCAPStream):
Expand All @@ -25,17 +25,14 @@ def __iter__(self):
return self

def __next__(self):

while True:
if self.n >= len(self):
raise StopIteration

#packet = Exported(self.packets[self.n].load)
packet = self.packets[self.n]
src, dst = extractInetAddressesFromPDUPacket(packet)
data = packet.load[60:]
self.n += 1

if any(ip not in self.ips for ip in [src.ip, dst.ip]):
continue # Skip packets not meant for this stream.

return PCAPStream.output(data, packet.time, src, dst)
return PCAPStream.output(data, packet.time, src, dst)
47 changes: 40 additions & 7 deletions pyrdp/convert/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,30 @@ def createHandler(format: str, outputFileBase: str, progress=None) -> Tuple[str,
return HandlerClass(outputFileBase, progress=progress) if HandlerClass else None, outputFileBase


class Exported(Packet):
"""60 byte EXPORTED_PDU header."""
# We could properly parse the EXPORTED_PDU struct, but we are mostly dealing with IP exported PDUs
# so let's just wing it.
name = "Exported"
fields_desc = [
IntField("tag1Num", None), # 4
StrFixedLenField("proto", None, length=4), # 8
IntField("tag2Num", None), # 12
IPField("src", None), # 16
IntField("tag3Num", None), # 20
IPField("dst", None), # 24
IntField("tag4Num", None), # 28
IntField("portType", None), # 32
IntField("tag5Num", None), # 36
IntField("sport", None), # 40
IntField("tag6Num", None), # 44
IntField("dport", None), # 48
IntField("tag7Num", None), # 52
IntField("frame", None), # 56
IntField("endOfTags", None), # 60
]


# noinspection PyUnresolvedReferences
def tcp_both(p) -> str:
"""Session extractor which merges both sides of a TCP channel."""
Expand All @@ -101,7 +125,15 @@ def tcp_both(p) -> str:
return str(
sorted(["TCP", p[IP].src, p[TCP].sport, p[IP].dst, p[TCP].dport], key=str)
)
return "Other"

# Need to make sure this is OK when non-TCP, non-exported data is present.
if Ether not in p:
x = Exported(p.load)
return str(
sorted([x.proto.upper(), x.src, x.sport, x.dst, x.dport], key=str)
)

return "Unsupported"


# noinspection PyUnresolvedReferences
Expand Down Expand Up @@ -142,18 +174,19 @@ def loadSecrets(filename: str) -> dict:

def canExtractSessionInfo(session: PacketList) -> bool:
packet = session[0]
# TODO: Eventually we should be able to wrap the session as an ExportedSession
# and check for the presence of exported.
return IP in packet or Ether not in packet

def getSessionInfo(session: PacketList) -> Tuple[InetAddress, InetAddress, float, bool]:
"""Attempt to retrieve an (src, dst, ts, isPlaintext) tuple for a data stream."""
packet = session[0]

if IP in packet:
# This is a plaintext stream.
#
# FIXME: This relies on the fact that decrypted traces are using EXPORTED_PDU and
# thus have no `IP` layer, but it is technically possible to have a true
# plaintext capture with very old implementations of RDP.
# FIXME: This relies on the fact that decrypted traces are using EXPORTED_PDU and
# thus have no `Ether` layer, but it is technically possible to have a true
# plaintext capture with very old implementations of RDP.
if TCP in packet:
# Assume an encrypted stream...
return (InetAddress(packet[IP].src, packet[IP][TCP].sport),
InetAddress(packet[IP].dst, packet[IP][TCP].dport),
packet.time, False)
Expand Down

0 comments on commit 2023ac6

Please sign in to comment.