From 146e61ea369dfef957787b1cf21d19f8bc45bf3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20De=20Keersmaeker?=
 <francois.dekeersmaeker@uclouvain.be>
Date: Thu, 19 Dec 2024 14:59:15 +0100
Subject: [PATCH] Fixed bugs: TP-Link SH + packet rebuild

---
 pcap_anonymize/app_layer/__init__.py |  2 +-
 pcap_anonymize/app_layer/http.py     | 22 +++++++++++++++-------
 pcap_anonymize/cli.py                | 15 +++++++++++++++
 pcap_anonymize/pcap_anonymize.py     | 22 +++++++++++++---------
 test/app_layer/test_tplink.py        |  1 +
 5 files changed, 45 insertions(+), 17 deletions(-)
 create mode 100644 pcap_anonymize/cli.py

diff --git a/pcap_anonymize/app_layer/__init__.py b/pcap_anonymize/app_layer/__init__.py
index f5f408e..667ee0f 100644
--- a/pcap_anonymize/app_layer/__init__.py
+++ b/pcap_anonymize/app_layer/__init__.py
@@ -36,6 +36,6 @@ def anonymize_app_layer(packet: Packet) -> None:
         sport = tcp.getfieldval("sport")
         dport = tcp.getfieldval("dport")
         if sport == 9999 or dport == 9999:
-            anonymize_tplink(packet)
+            anonymize_tplink(tcp)
     except:
         pass
diff --git a/pcap_anonymize/app_layer/http.py b/pcap_anonymize/app_layer/http.py
index 36cfbd4..7a418c3 100644
--- a/pcap_anonymize/app_layer/http.py
+++ b/pcap_anonymize/app_layer/http.py
@@ -40,14 +40,22 @@ def get_http_layer(packet: Packet) -> HTTP:
     
     # HTTP layer could not be retrieved directly.
     # Try to get it from the Raw layer.
-    raw_load = packet.getlayer(Raw).getfieldval("load")
-    http = HTTPRequest(raw_load)
-    if http.haslayer(HTTPRequest):
-        return http
-    http = HTTPResponse(raw_load)
-    if http.haslayer(HTTPResponse):
-        return http
     
+    raw_load = packet.getlayer(Raw).getfieldval("load")
+    try:
+        http = HTTPRequest(raw_load)
+        if http.haslayer(HTTPRequest):
+            return http
+    except ValueError:
+        pass
+
+    try:
+        http = HTTPResponse(raw_load)
+        if http.haslayer(HTTPResponse):
+            return http
+    except ValueError:
+        pass
+ 
     raise AttributeError(f"HTTP layer not found in packet {packet.summary()}")
 
 
diff --git a/pcap_anonymize/cli.py b/pcap_anonymize/cli.py
new file mode 100644
index 0000000..dcdbb33
--- /dev/null
+++ b/pcap_anonymize/cli.py
@@ -0,0 +1,15 @@
+import os
+import argparse
+from .pcap_anonymize import anonymize_pcap
+
+
+def main() -> None:
+    """
+    Main function for the CLI.
+    """
+    parser = argparse.ArgumentParser(description="Anonymize a PCAP traffic capture.")
+    parser.add_argument("input", type=os.PathLike, help="Path to the input PCAP file.")
+    parser.add_argument("-o", "--output", type=os.PathLike, help="Path to the output PCAP file.")
+    args = parser.parse_args()
+
+    anonymize_pcap(args.input, args.output)
diff --git a/pcap_anonymize/pcap_anonymize.py b/pcap_anonymize/pcap_anonymize.py
index 873987c..81c78cc 100644
--- a/pcap_anonymize/pcap_anonymize.py
+++ b/pcap_anonymize/pcap_anonymize.py
@@ -17,21 +17,25 @@ packets = []
 
 ### FUNCTIONS ###
 
-def recompute_checksums(packet: Packet) -> Packet:
+def rebuild_packet(packet: Packet) -> Packet:
     """
-    Recompute a given packet's checksums.
+    Rebuild a packet:
+    recompute its lengths and checksums.
 
     Args:
-        packet (scapy.Packet): scapy packet to recompute checksums for
+        packet (scapy.Packet): scapy packet to rebuild
     Returns:
-        (scapy.Packet): packet with recomputed checksums
+        scapy.Packet: rebuilt packet
     """
+    fields_to_delete = ["len", "chksum"]
+
     for layer_class in packet.layers():
         layer = packet.getlayer(layer_class)
-        try:
-            delattr(layer, "chksum")
-        except AttributeError:
-            pass
+        for field in fields_to_delete:
+            try:
+                delattr(layer, field)
+            except AttributeError:
+                pass
         
     return packet.__class__(bytes(packet))
 
@@ -53,7 +57,7 @@ def anonymize_packet(packet: Packet) -> None:
     anonymize_app_layer(packet)
 
     # Recompute packet checksums
-    packet = recompute_checksums(packet)
+    packet = rebuild_packet(packet)
 
     packets.append(packet)
 
diff --git a/test/app_layer/test_tplink.py b/test/app_layer/test_tplink.py
index 35afc45..a71099d 100644
--- a/test/app_layer/test_tplink.py
+++ b/test/app_layer/test_tplink.py
@@ -17,5 +17,6 @@ def test_anonymize_tplink() -> None:
     anonymize_tplink(packet)
 
     # Check if payload was correctly deleted
+    assert packet.haslayer(TCP)
     assert not packet.haslayer(Raw)
     assert not hasattr(packet, "load")
-- 
GitLab