commit d7a257af0826a3d6cae0254880b294dfa7c93ba5 Author: Stanislav Mykhailenko Date: Fri Aug 30 16:48:01 2024 +0300 First version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28db11b --- /dev/null +++ b/.gitignore @@ -0,0 +1,75 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* +CMakeLists.txt.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + +build diff --git a/NG_2024_PacketAnalyzer.pro b/NG_2024_PacketAnalyzer.pro new file mode 100644 index 0000000..d6a0986 --- /dev/null +++ b/NG_2024_PacketAnalyzer.pro @@ -0,0 +1,28 @@ +QT += core gui network + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++17 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + packetanalyzer.cpp + +HEADERS += \ + packetanalyzer.h + +FORMS += \ + packetanalyzer.ui + +INCLUDEPATH += /usr/include/pcapplusplus/ + +LIBS += -L/usr/lib/pcapplusplus -lPcap++ -lPacket++ -lCommon++ + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/README.md b/README.md new file mode 100644 index 0000000..e80320b --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# New Generation 2024 Packet Analyzer + +Graphical packet analyzer. + +Features: +- Reading and writing .pcapng files. +- Using LLM to pretend it can detect anomalies. +- Selecting network interfaces. +- Packet sorting. + +This program is Unlicensed, see UNLICENSE. diff --git a/UNLICENSE b/UNLICENSE new file mode 100644 index 0000000..68a49da --- /dev/null +++ b/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f70724b --- /dev/null +++ b/main.cpp @@ -0,0 +1,11 @@ +#include "packetanalyzer.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + PacketAnalyzer w; + w.show(); + return a.exec(); +} diff --git a/packetanalyzer.cpp b/packetanalyzer.cpp new file mode 100644 index 0000000..e413557 --- /dev/null +++ b/packetanalyzer.cpp @@ -0,0 +1,338 @@ +#include "packetanalyzer.h" +#include "ui_packetanalyzer.h" + +PacketAnalyzer::PacketAnalyzer(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::PacketAnalyzer) +{ + ui->setupUi(this); + + connect(ui->cb_interfaces, &QComboBox::currentTextChanged, this, &PacketAnalyzer::changeInterface); + connect(ui->b_refresh, &QPushButton::clicked, this, &PacketAnalyzer::refresh); + connect(ui->t_packets, &QTableWidget::itemSelectionChanged, this, &PacketAnalyzer::packetSelected); + connect(ui->b_start, &QPushButton::clicked, this, &PacketAnalyzer::start); + connect(ui->b_stop, &QPushButton::clicked, this, &PacketAnalyzer::stop); + connect(ui->b_save, &QPushButton::clicked, this, &PacketAnalyzer::save); + connect(ui->b_load, &QPushButton::clicked, this, &PacketAnalyzer::load); + connect(ui->b_llm, &QPushButton::clicked, this, &PacketAnalyzer::llmRequest); + connect (m_manager, &QNetworkAccessManager::finished, this, &PacketAnalyzer::llmResponse); + + QList interfaces = QNetworkInterface::allInterfaces(); + + for (QNetworkInterface &interface : interfaces) + ui->cb_interfaces->addItem(interface.name()); +} + +PacketAnalyzer::~PacketAnalyzer() +{ + delete ui; + + stop(); +} + +void PacketAnalyzer::changeInterface(QString) +{ + stop(); + + clear(); + m_packets.clear(); + m_dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(ui->cb_interfaces->currentText().toStdString()); +} + +void PacketAnalyzer::clear() +{ + ui->t_packets->setRowCount(0); + ui->e_selected->clear(); +} + +void PacketAnalyzer::refresh() +{ + clear(); + for (pcpp::RawPacketVector::ConstVectorIterator iter = m_packets.begin(); iter != m_packets.end(); iter++) { + pcpp::Packet parsedPacket(*iter); + ui->t_packets->insertRow( ui->t_packets->rowCount() ); + for (pcpp::Layer* curLayer = parsedPacket.getFirstLayer(); curLayer != NULL; curLayer = curLayer->getNextLayer()) + { + QTableWidgetItem* numberItem = new QTableWidgetItem(); + numberItem->setData(Qt::DisplayRole, ui->t_packets->rowCount()); + ui->t_packets->setItem( ui->t_packets->rowCount()-1, + 0, + numberItem); + ui->t_packets->setItem( ui->t_packets->rowCount()-1, + 3, + new QTableWidgetItem(getProtocolTypeAsString(curLayer->getProtocol()))); + ui->t_packets->setItem( ui->t_packets->rowCount()-1, + 4, + new QTableWidgetItem(QString::number((int)curLayer->getDataLen()))); + + QString sourceIP = "Unknown"; + QString destinationIP = "Unknown"; + + pcpp::IPv4Layer* ipv4Layer = parsedPacket.getLayerOfType(); + if (ipv4Layer != NULL) + { + sourceIP = QString::fromStdString(ipv4Layer->getSrcIPAddress().toString()); + destinationIP = QString::fromStdString(ipv4Layer->getSrcIPAddress().toString()); + } + + pcpp::IPv6Layer* ipv6Layer = parsedPacket.getLayerOfType(); + if (ipv6Layer != NULL) + { + sourceIP = QString::fromStdString(ipv6Layer->getSrcIPAddress().toString()); + destinationIP = QString::fromStdString(ipv6Layer->getSrcIPAddress().toString()); + } + + ui->t_packets->setItem( ui->t_packets->rowCount()-1, + 1, + new QTableWidgetItem(sourceIP)); + ui->t_packets->setItem( ui->t_packets->rowCount()-1, + 2, + new QTableWidgetItem(destinationIP)); + } + } +} + +void PacketAnalyzer::packetSelected() +{ + int packetId = ui->t_packets->selectedItems()[0]->text().toInt(); + pcpp::RawPacket* packet = m_packets.at(packetId-1); + ui->e_selected->setText(QString::fromStdString(pcpp::byteArrayToHexString(packet->getRawData(), packet->getRawDataLen()))); + ui->b_llm->setEnabled(true); +} + +void PacketAnalyzer::start() +{ + if (!m_dev->open()) + { + QMessageBox::critical( + this, + tr("Error"), + tr("Cannot open device.") ); + return; + } + clear(); + m_packets.clear(); + m_dev->startCapture(m_packets); + ui->b_start->setEnabled(false); + ui->b_stop->setEnabled(true); + ui->b_save->setEnabled(false); +} + +void PacketAnalyzer::stop() +{ + if (m_dev == NULL || !m_dev->captureActive()) + return; + m_dev->stopCapture(); + ui->b_start->setEnabled(true); + ui->b_stop->setEnabled(false); + ui->b_save->setEnabled(true); +} + +void PacketAnalyzer::save() +{ + QString fileName = QFileDialog::getSaveFileName(this, "Select file", "", "pcap-ng files (*.pcapng)"); + + if (fileName.isEmpty()) + return; + + pcpp::PcapNgFileWriterDevice writer(fileName.toStdString()); + + if (!writer.open()) + { + QMessageBox::critical( + this, + tr("Error"), + tr("Cannot open output file for writing.") ); + return; + } + + writer.writePackets(m_packets); + + writer.close(); +} + +void PacketAnalyzer::load() +{ + QString fileName = QFileDialog::getOpenFileName(this, "Select file", "", "pcap-ng files (*.pcapng)"); + + if (fileName.isEmpty()) + return; + + pcpp::PcapNgFileReaderDevice reader(fileName.toStdString()); + + if (!reader.open()) + { + QMessageBox::critical( + this, + tr("Error"), + tr("Cannot open input file for reading.") ); + return; + } + + stop(); + clear(); + m_packets.clear(); + + reader.getNextPackets(m_packets); + + reader.close(); + + refresh(); +} + +void PacketAnalyzer::llmRequest() +{ + QNetworkRequest request(QUrl("http://127.0.0.1:11434/api/generate")); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + + QJsonObject json; + json["model"] = "llama3.1:8b"; + json["prompt"] = "Please analyze the following packet for anomalies.\n" + ui->e_selected->toPlainText(); + json["stream"] = false; + + m_manager->post(request, QJsonDocument(json).toJson()); + + ui->b_llm->setEnabled(false); + ui->b_load->setEnabled(false); + ui->b_refresh->setEnabled(false); + if (m_dev == NULL || !m_dev->captureActive()) + ui->b_start->setEnabled(false); + else + ui->b_stop->setEnabled(false); + ui->cb_interfaces->setEnabled(false); + ui->t_packets->setSelectionMode(QAbstractItemView::NoSelection); +} + + +void PacketAnalyzer::llmResponse(QNetworkReply *reply) +{ + if (reply->error() == QNetworkReply::NoError) { + QByteArray textReply = reply->readAll(); + QString responseText = QJsonDocument::fromJson(textReply).object().value("response").toString(); + QMessageBox::information( + this, + tr("LLM response"), + responseText ); + } else { + QMessageBox::critical( + this, + tr("Error"), + tr("Could not connect to LLM.") ); + } + ui->b_llm->setEnabled(true); + ui->b_load->setEnabled(true); + ui->b_refresh->setEnabled(true); + if (m_dev == NULL || !m_dev->captureActive()) + ui->b_start->setEnabled(true); + else + ui->b_stop->setEnabled(true); + ui->cb_interfaces->setEnabled(true); + ui->t_packets->setSelectionMode(QAbstractItemView::SingleSelection); +} + +QString PacketAnalyzer::getProtocolTypeAsString(pcpp::ProtocolType protocolType) +{ + switch (protocolType) + { + case pcpp::Ethernet: + return "Ethernet"; + case pcpp::IPv4: + return "IPv4"; + case pcpp::IPv6: + return "IPv6"; + case pcpp::TCP: + return "TCP"; + case pcpp::UDP: + return "UDP"; + case pcpp::HTTPRequest: + case pcpp::HTTPResponse: + return "HTTP"; + case pcpp::ARP: + return "ARP"; + case pcpp::VLAN: + return "VLAN"; + case pcpp::ICMP: + return "ICMP"; + case pcpp::PPPoESession: + case pcpp::PPPoEDiscovery: + return "PPPoE"; + case pcpp::DNS: + return "DNS"; + case pcpp::MPLS: + return "MPLS"; + case pcpp::GREv0: + case pcpp::GREv1: + return "GRE"; + case pcpp::PPP_PPTP: + return "PPP_PPTP"; + case pcpp::SSL: + return "SSL"; + case pcpp::SLL: + return "SLL"; + case pcpp::DHCP: + return "DHCP"; + case pcpp::NULL_LOOPBACK: + return "NULL_LOOPBACK"; + case pcpp::IGMPv1: + case pcpp::IGMPv2: + case pcpp::IGMPv3: + return "IGMP"; + case pcpp::GenericPayload: + return "GenericPayload"; + case pcpp::VXLAN: + return "VXLAN"; + case pcpp::SIPRequest: + case pcpp::SIPResponse: + return "SIP"; + case pcpp::SDP: + return "SDP"; + case pcpp::PacketTrailer: + return "PacketTrailer"; + case pcpp::Radius: + return "Radius"; + case pcpp::GTPv1: + return "GTP"; + case pcpp::EthernetDot3: + return "EthernetDot3"; + case pcpp::BGP: + return "BGP"; + case pcpp::SSH: + return "SSH"; + case pcpp::AuthenticationHeader: + case pcpp::ESP: + return "IPsec"; + case pcpp::DHCPv6: + return "DHCPv6"; + case pcpp::NTP: + return "NTP"; + case pcpp::Telnet: + return "Telnet"; + case pcpp::FTP: + return "FTP"; + case pcpp::ICMPv6: + return "ICMPv6"; + case pcpp::STP: + return "STP"; + case pcpp::LLC: + return "LLC"; + case pcpp::SomeIP: + return "SomeIP"; + case pcpp::WakeOnLan: + return "WakeOnLan"; + case pcpp::NFLOG: + return "NFLOG"; + case pcpp::TPKT: + return "TPKT"; + case pcpp::VRRPv2: + case pcpp::VRRPv3: + return "VRRP"; + case pcpp::COTP: + return "COTP"; + case pcpp::SLL2: + return "SLL2"; + case pcpp::S7COMM: + return "S7COMM"; + default: + return "Unknown"; + } +} diff --git a/packetanalyzer.h b/packetanalyzer.h new file mode 100644 index 0000000..9caeac2 --- /dev/null +++ b/packetanalyzer.h @@ -0,0 +1,52 @@ +#ifndef PACKETANALYZER_H +#define PACKETANALYZER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { +class PacketAnalyzer; +} +QT_END_NAMESPACE + +class PacketAnalyzer : public QMainWindow +{ + Q_OBJECT + +public: + PacketAnalyzer(QWidget *parent = nullptr); + ~PacketAnalyzer(); + +private slots: + void changeInterface(QString); + void refresh(); + void packetSelected(); + void start(); + void stop(); + void save(); + void load(); + void llmRequest(); + void llmResponse(QNetworkReply *); + +private: + Ui::PacketAnalyzer *ui; + pcpp::PcapLiveDevice* m_dev = nullptr; + pcpp::RawPacketVector m_packets; + QNetworkAccessManager *m_manager = new QNetworkAccessManager(); + QString getProtocolTypeAsString(pcpp::ProtocolType); + void clear(); +}; +#endif // PACKETANALYZER_H diff --git a/packetanalyzer.ui b/packetanalyzer.ui new file mode 100644 index 0000000..c3e7b43 --- /dev/null +++ b/packetanalyzer.ui @@ -0,0 +1,193 @@ + + + PacketAnalyzer + + + + 0 + 0 + 800 + 600 + + + + PacketAnalyzer + + + + + + + + + true + + + Save + + + + + + + true + + + Load + + + + + + + Refresh + + + + + + + + + + + true + + + Start + + + + + + + false + + + Stop + + + + + + + + + + + Interface: + + + + + + + + + + + + Packets: + + + + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + QAbstractItemView::SelectionMode::SingleSelection + + + QAbstractItemView::SelectionBehavior::SelectRows + + + true + + + 5 + + + true + + + true + + + true + + + true + + + true + + + + No. + + + + + Source + + + + + Destination + + + + + Protocol + + + + + Length + + + + + + + + Selected packet: + + + + + + + true + + + + + + + false + + + Pass to LLM + + + + + + + + + 0 + 0 + 800 + 25 + + + + + + + +