more work on final

This commit is contained in:
David Westgate 2024-06-14 12:40:48 -07:00
parent 4d86bb01f4
commit fa5a30db6e
5 changed files with 70 additions and 73 deletions

3
.gitignore vendored
View File

@ -10,4 +10,5 @@ rag_data
*wordlist* *wordlist*
*dumps* *dumps*
.aider* .aider*
*pcap *pcap
*test.py

View File

@ -1,9 +1,24 @@
###### David Westgate 14 June 2024 ###### David Westgate 14 June 2024
## Final Project for gensec ## Final Project for gensec
This project is an LLM rag chain which intends to help the user with network analysis and forensics.
Tools are provided to assist the user with capturing packets via `tcpdump`, provide summaries of these packet captures,
perform geographic IP lookup, and provide a visual of network traffic.
## Prerequisites ## Prerequisites
This appliction utilized some shell tools and assumes you are on a linux/unix like operating system.
It is necessary to install `tcpdump`. `sudo` permissions are also required
## Setup + Run
Install python3, then
```
cd final
mkdir captures
pip install -r requirements.txt
cp .env.example .env #fill in env file with key
python3 app.py
```
### Setup + Run ## Example tests
*Show a summary of network traffic on enp7s0*
*Show a visual representation of the network traffic on enp7s0*
*Show a list of IP addresses that communicate on enp7s0 and identify the countries of those addresses*

View File

@ -2,13 +2,7 @@ import os
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_react_agent from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import tool from langchain.tools import tool
from tools import ( from tools import dalle, tcp_dump, get_wireless_interface, ip_loc, pcap_summary
dalle,
tcp_dump,
tshark,
get_wireless_interface,
ip_loc
)
from langchain import hub from langchain import hub
from langchain_community.tools import ShellTool from langchain_community.tools import ShellTool
from langsmith import Client from langsmith import Client
@ -28,7 +22,7 @@ client = Client()
shell_tool = ShellTool() shell_tool = ShellTool()
llm = ChatOpenAI(model_name="gpt-4o", temperature=0) llm = ChatOpenAI(model_name="gpt-4o", temperature=0)
tools = [] tools = []
tools.extend([tcp_dump,ip_loc, dalle,get_wireless_interface]) tools.extend([tcp_dump, ip_loc, dalle, pcap_summary, get_wireless_interface])
base_prompt = hub.pull("langchain-ai/react-agent-template") base_prompt = hub.pull("langchain-ai/react-agent-template")
prompt = base_prompt.partial( prompt = base_prompt.partial(
instructions=""" instructions="""
@ -43,7 +37,7 @@ agent_executor = AgentExecutor(
print( print(
"I am a packet analysis an assistant. I can perform various tasks related to packet capture files." "I am a packet analysis an assistant. I can perform various tasks related to packet capture files, including capture, summarization, IP lookups, and visualization."
) )
print(f"I am configured with the following tools") print(f"I am configured with the following tools")

8
final/requirements.txt Normal file
View File

@ -0,0 +1,8 @@
langchain
langchain_community
langchain_core
langchain_openai
langsmith
python-dotenv
Requests
scapy

View File

@ -1,37 +1,23 @@
from datetime import date, datetime from datetime import datetime
import json
import threading
import random
from pyshark import FileCapture, packet as Packet
from langchain_core.pydantic_v1 import BaseModel, Field from langchain_core.pydantic_v1 import BaseModel, Field
from langchain.tools import tool from langchain.tools import tool
from langchain_community.tools import ShellTool from langchain_community.tools import ShellTool
from langchain.chains import LLMChain
from langchain_community.utilities.dalle_image_generator import DallEAPIWrapper from langchain_community.utilities.dalle_image_generator import DallEAPIWrapper
from scapy import * from scapy import *
import requests import requests
from scapy.all import rdpcap, wrpcap from scapy.all import rdpcap, wrpcap
from scapy.layers.inet import IP, TCP, UDP from scapy.layers.inet import IP, TCP, UDP, Packet, PacketList
"""
"""
shell_tool = ShellTool() shell_tool = ShellTool()
""" """
""" """
class TCPDump(BaseModel): class TCPDump(BaseModel):
params: str = Field( interface: str = Field(
description=""" description="""The name of the interface to use with tcpdump. May be 'any'"""
A JSON string including `interface` the network interface name and `flags`, any other additional flags or arguments for tcpdump.
Do not include any indication of duration or output file, as this is handled by the tool
"""
) )
@ -40,70 +26,59 @@ class TCPDump(BaseModel):
args_schema=TCPDump, args_schema=TCPDump,
return_direct=False, return_direct=False,
) )
def tcp_dump(json_params: str) -> str: def tcp_dump(interface: str) -> str:
"""Must pass parameters to `tcpdump` including arguments and flags to perform packet monitoring and analysis""" """Must pass interface name to `tcpdump`"""
json_params = json_params.replace("\\", "").replace("`", "").replace("'", "")
print("params ", json_params)
json_obj = json.loads(json_params)
interface = json_obj.get("interface", "")
flags = json_obj.get("flags", "")
# print('date ',date())
file_name = f'captures/{interface}-{datetime.now().strftime("%Y-%m-%d-%H-%M")}.pcap' file_name = f'captures/{interface}-{datetime.now().strftime("%Y-%m-%d-%H-%M")}.pcap'
shell_tool.run( shell_tool.run(
{ {
"commands": [ "commands": [
f"sudo timeout 10 tcpdump -i {interface} -w {file_name} {flags} " f"sudo timeout 10 tcpdump -i {interface} -w {file_name} ",
"sleep 2s",
] ]
} }
) )
filtered = filter_unique_packets(file_name) filtered: str = filter_unique_packets(file_name)
return filtered return filtered
class TShark(BaseModel):
params: str = Field(
description="""A JSON string including `file` the name of the pcap file to analysize, and `flags` and flags any other additional flags or arguments for tshark"""
)
@tool(
"Perform packet analysis of a pcap file tshark",
args_schema=TShark,
return_direct=False,
)
def tshark(json_params: str) -> str:
"""Must pass all parameters to `tshark` including arguments and flags to perform packet analysis"""
json_params = json_params.replace("\\", "").replace("`", "").replace("'", "")
print("params ", json_params)
json_obj = json.loads(json_params)
file = json_obj.get("file", "")
flags = json_obj.get("flags", "")
class Image(BaseModel): class Image(BaseModel):
params: str = Field( params: str = Field(
description="""A Graphviz decription of network characteristics""" description="""A structured text summary of netowrk information or topology"""
) )
@tool( @tool(
"Create an image of a network", "Create an image of a network. This tool must take as input a summary of packet information, and not a file name",
args_schema=TShark, args_schema=Image,
return_direct=False, return_direct=False,
) )
def dalle(params: str) -> str: def dalle(params: str) -> str:
"""Must provive a Graphviz decription of network characteristics to pass to an image generation tool""" """Must provide a summary of packet information"""
prompt = f""" prompt = f"""
Use the below Graphviz description to create an image of network topology Use the below description to create an image of network topology
``` ```
{params} {params}
``` ```
"""
"""
image_url = DallEAPIWrapper().run(prompt) image_url = DallEAPIWrapper().run(prompt)
return image_url return image_url
class Summary(BaseModel):
interface: str = Field(description="""The name of the pcacp file to be read""")
@tool(
"Summarize a pcap file using scapy, and return the contents",
args_schema=TCPDump,
return_direct=False,
)
def pcap_summary(file: str) -> str:
"""Must pass the path to a pcap file to return a summary of packet information and traffic data"""
cap: PacketList = rdpcap(file)
return cap.summary()
# From hw6 # From hw6
class Iwconfig(BaseModel): class Iwconfig(BaseModel):
params: str = Field( params: str = Field(
@ -122,20 +97,21 @@ def get_wireless_interface(params: str) -> str:
@tool @tool
def ip_loc(address): def ip_loc(address):
"""Get information from an ip address, including geolocation""" """Get information from an ip address, including geolocation. Takes as a paramater an ip address"""
url = f"http://ipwho.is/{address}" url = f"http://ipwho.is/{address}"
response = requests.get(url) response = requests.get(url)
if response.status_code == 200: if response.status_code == 200:
return response.json() return response.json()
# Filter unique packets from a pcap file with pyshark # Filter 'unique' (src,dest,protocol) packets from a pcap file with scapy. Save this as a new capture file and return the name
def filter_unique_packets(pcap_file: str): def filter_unique_packets(pcap_file: str) -> str:
packets = rdpcap(pcap_file) packets = rdpcap(pcap_file)
unique_packets = set() unique_packets = set()
filtered_packets = [] filtered_packets = []
for packet in packets: for p in packets:
packet: Packet = p
try: try:
if IP in packet and (TCP in packet or UDP in packet): if IP in packet and (TCP in packet or UDP in packet):
ip_layer = packet[IP] ip_layer = packet[IP]
@ -158,3 +134,6 @@ def filter_unique_packets(pcap_file: str):
filtered_packets.append(packet) filtered_packets.append(packet)
except AttributeError: except AttributeError:
continue continue
name = pcap_file.replace(".pcap", "-f.pcap")
wrpcap(name, filtered_packets)
return name