fuck
This commit is contained in:
commit
32b895afe2
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build/
|
||||
.vscode/
|
||||
tests/
|
16
CMakeLists.txt
Normal file
16
CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(ip_reporter)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Gui REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
add_executable(ip_reporter src/main.cpp)
|
||||
|
||||
target_link_libraries(ip_reporter Qt5::Widgets Qt5::Core Qt5::Gui Qt5::Network pcap)
|
100
README.md
Normal file
100
README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# IP Reporter (I copied this from my python project)
|
||||
|
||||
IP Reporter is a ~Python~ C++-based tool for network administrators to monitor and capture IP and MAC addresses of network devices. It provides a simple graphical user interface (GUI) to display and export the captured data. The tool is useful for managing network devices, especially in environments like mining farms where multiple devices need to be tracked. Currently this only works on Antminer machines as it's what I have access to.
|
||||
|
||||
## Features
|
||||
|
||||
- **Network Packet Sniffing**: Captures network packets to extract IP and MAC addresses.
|
||||
- **Graphical User Interface**: Provides a clean and simple GUI using Tkinter.
|
||||
- **Start/Stop Functionality**: Easily start or stop packet sniffing with a button click.
|
||||
- **Data Export**: Export captured data to a text file.
|
||||
- **Click to Open**: Double-click on an IP address to open it in the default web browser with pre-filled login credentials.
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Python 3.x
|
||||
- Scapy
|
||||
- Tkinter (comes with standard Python installations)
|
||||
- Webbrowser (comes with standard Python installations)
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Python 3.x**: Ensure you have Python 3.x installed on your system. You can download it from [python.org](https://www.python.org/).
|
||||
|
||||
2. **Scapy**: Install Scapy using pip.
|
||||
|
||||
```sh
|
||||
pip install scapy
|
||||
```
|
||||
|
||||
3. **Set Capabilities** (Optional): If you want to run the script without root privileges, set capabilities on your Python interpreter.
|
||||
```sh
|
||||
sudo setcap cap_net_raw,cap_net_admin=eip $(readlink -f $(which python3))
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. **Clone the Repository**:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/ampersandcastles/ip-reporter.git
|
||||
cd ip-reporter
|
||||
```
|
||||
|
||||
2. **Run the Script**:
|
||||
|
||||
```sh
|
||||
python3 reporter.py
|
||||
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
python3 gui.py
|
||||
|
||||
```
|
||||
|
||||
3. **GUI Interface**:
|
||||
- Click "Start" to begin packet sniffing.
|
||||
- Captured IP and MAC addresses will be displayed in the table.
|
||||
- Double-click on an IP address to open it in your default web browser.
|
||||
- Click "Export" to save the captured data to a text file.
|
||||
|
||||
## Code Overview
|
||||
|
||||
- `reporter.py`: Main script containing the GUI and packet sniffing functionality.
|
||||
|
||||
### Packet Sniffing
|
||||
|
||||
The script uses Scapy to sniff network packets and extract the IP and MAC addresses of devices.
|
||||
|
||||
### CLI version
|
||||
|
||||
Works very similarly to GUI version, just command line. All properties still apply minus the autologin.
|
||||
|
||||
### Graphical User Interface
|
||||
|
||||
The GUI is built using Tkinter, providing a table to display captured data, and buttons to start/stop sniffing and export data.
|
||||
|
||||
### Open in Browser
|
||||
|
||||
Double-clicking on an IP address in the table opens it in the default web browser with the login credentials (`root/root`) pre-filled in the URL.
|
||||
|
||||
## Security Note
|
||||
|
||||
While the tool attempts to simplify device management by allowing auto-login to devices via URLs with embedded credentials, this method is generally insecure and should be used with caution. It's recommended to use more secure methods of authentication and avoid embedding credentials in URLs where possible.
|
||||
|
||||
## Contributing
|
||||
|
||||
Feel free to contribute to this project by submitting issues or pull requests. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- The developers and maintainers of [Scapy](https://scapy.net/).
|
||||
- The Python community for providing excellent libraries and support.
|
||||
- Honestly, ChatGPT.
|
6
include/ip-reporter/example.h
Normal file
6
include/ip-reporter/example.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef IP-REPORTER_EXAMPLE_H
|
||||
#define IP-REPORTER_EXAMPLE_H
|
||||
|
||||
void exampleFunction();
|
||||
|
||||
#endif // IP-REPORTER_EXAMPLE_H
|
300
src/main.cpp
Normal file
300
src/main.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QTreeView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QFileDialog>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
#include <pcap.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
const char *DESTINATION_IP = "255.255.255.255";
|
||||
const uint16_t SOURCE_PORT = 14236;
|
||||
const uint16_t DESTINATION_PORT = 14235;
|
||||
|
||||
struct PacketInfo
|
||||
{
|
||||
std::string source_ip;
|
||||
std::string source_mac;
|
||||
|
||||
bool operator==(const PacketInfo &other) const
|
||||
{
|
||||
return source_ip == other.source_ip && source_mac == other.source_mac;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<PacketInfo>
|
||||
{
|
||||
size_t operator()(const PacketInfo &pi) const
|
||||
{
|
||||
return hash<string>()(pi.source_ip) ^ hash<string>()(pi.source_mac);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class IPReporter : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IPReporter(QWidget *parent = nullptr);
|
||||
~IPReporter();
|
||||
|
||||
private slots:
|
||||
void on_start_button_clicked();
|
||||
void on_export_button_clicked();
|
||||
void on_tree_view_double_clicked(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
void capture_packets();
|
||||
void update_tree_view(const PacketInfo &info);
|
||||
PacketInfo extract_packet_info(const u_char *packet, struct pcap_pkthdr packet_header);
|
||||
|
||||
QWidget *centralWidget;
|
||||
QVBoxLayout *vboxLayout;
|
||||
QTreeView *treeView;
|
||||
QStandardItemModel *model;
|
||||
QPushButton *startButton;
|
||||
QPushButton *exportButton;
|
||||
QLabel *statusLabel;
|
||||
|
||||
std::thread captureThread;
|
||||
std::mutex mtx;
|
||||
bool listening;
|
||||
std::vector<PacketInfo> packets;
|
||||
std::unordered_set<PacketInfo> unique_packets;
|
||||
};
|
||||
|
||||
IPReporter::IPReporter(QWidget *parent)
|
||||
: QMainWindow(parent), listening(false)
|
||||
{
|
||||
centralWidget = new QWidget(this);
|
||||
vboxLayout = new QVBoxLayout(centralWidget);
|
||||
|
||||
model = new QStandardItemModel(0, 2, this);
|
||||
model->setHeaderData(0, Qt::Horizontal, "IP Address");
|
||||
model->setHeaderData(1, Qt::Horizontal, "MAC Address");
|
||||
|
||||
treeView = new QTreeView(this);
|
||||
treeView->setModel(model);
|
||||
connect(treeView, &QTreeView::doubleClicked, this, &IPReporter::on_tree_view_double_clicked);
|
||||
|
||||
startButton = new QPushButton("Start", this);
|
||||
exportButton = new QPushButton("Export", this);
|
||||
statusLabel = new QLabel("Stopped", this);
|
||||
|
||||
vboxLayout->addWidget(treeView);
|
||||
vboxLayout->addWidget(startButton);
|
||||
vboxLayout->addWidget(exportButton);
|
||||
vboxLayout->addWidget(statusLabel);
|
||||
|
||||
setCentralWidget(centralWidget);
|
||||
|
||||
connect(startButton, &QPushButton::clicked, this, &IPReporter::on_start_button_clicked);
|
||||
connect(exportButton, &QPushButton::clicked, this, &IPReporter::on_export_button_clicked);
|
||||
}
|
||||
|
||||
IPReporter::~IPReporter()
|
||||
{
|
||||
listening = false;
|
||||
if (captureThread.joinable())
|
||||
{
|
||||
captureThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void IPReporter::on_start_button_clicked()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
if (!listening)
|
||||
{
|
||||
listening = true;
|
||||
startButton->setText("Stop");
|
||||
statusLabel->setText("Listening...");
|
||||
captureThread = std::thread(&IPReporter::capture_packets, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
listening = false;
|
||||
startButton->setText("Start");
|
||||
statusLabel->setText("Stopped");
|
||||
}
|
||||
}
|
||||
|
||||
void IPReporter::on_export_button_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this, "Save File", "", "Text Files (*.txt);;All Files (*)");
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::ofstream file(fileName.toStdString());
|
||||
for (const auto &info : packets)
|
||||
{
|
||||
file << "IP Address: " << info.source_ip << ", MAC Address: " << info.source_mac << "\n";
|
||||
}
|
||||
statusLabel->setText("Data exported.");
|
||||
}
|
||||
}
|
||||
|
||||
void IPReporter::on_tree_view_double_clicked(const QModelIndex &index)
|
||||
{
|
||||
QString ipAddress = model->data(model->index(index.row(), 0)).toString();
|
||||
QString url = QString("http://root:root@%1").arg(ipAddress);
|
||||
QDesktopServices::openUrl(QUrl(url));
|
||||
}
|
||||
|
||||
void IPReporter::capture_packets()
|
||||
{
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
pcap_if_t *alldevs;
|
||||
pcap_if_t *device;
|
||||
|
||||
if (pcap_findalldevs(&alldevs, errbuf) == -1)
|
||||
{
|
||||
std::cerr << "Error finding devices: " << errbuf << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Print available devices
|
||||
for (device = alldevs; device != nullptr; device = device->next)
|
||||
{
|
||||
std::cout << "Device: " << device->name << " - " << (device->description ? device->description : "No description") << std::endl;
|
||||
}
|
||||
|
||||
device = alldevs; // Use the first device, update this to use the correct device if needed
|
||||
std::cout << "Using device: " << device->name << std::endl;
|
||||
|
||||
pcap_t *handle = pcap_open_live(device->name, BUFSIZ, 1, 1000, errbuf);
|
||||
if (handle == nullptr)
|
||||
{
|
||||
std::cerr << "Error opening device: " << errbuf << std::endl;
|
||||
pcap_freealldevs(alldevs);
|
||||
return;
|
||||
}
|
||||
|
||||
while (listening)
|
||||
{
|
||||
struct pcap_pkthdr header;
|
||||
const u_char *packet = pcap_next(handle, &header);
|
||||
if (packet != nullptr)
|
||||
{
|
||||
std::cout << "Packet captured: length = " << header.len << std::endl;
|
||||
PacketInfo info = extract_packet_info(packet, header);
|
||||
if (!info.source_ip.empty() && !info.source_mac.empty())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
if (unique_packets.insert(info).second)
|
||||
{
|
||||
packets.push_back(info);
|
||||
update_tree_view(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pcap_close(handle);
|
||||
pcap_freealldevs(alldevs);
|
||||
}
|
||||
|
||||
PacketInfo IPReporter::extract_packet_info(const u_char *packet, struct pcap_pkthdr packet_header)
|
||||
{
|
||||
PacketInfo info;
|
||||
|
||||
struct ether_header *eth_header;
|
||||
eth_header = (struct ether_header *)packet;
|
||||
|
||||
// Check if it's an IP packet
|
||||
if (ntohs(eth_header->ether_type) != ETHERTYPE_IP)
|
||||
{
|
||||
std::cerr << "Not an IP packet" << std::endl;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Extract source MAC address
|
||||
char mac_addr[18];
|
||||
snprintf(mac_addr, sizeof(mac_addr), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
eth_header->ether_shost[0],
|
||||
eth_header->ether_shost[1],
|
||||
eth_header->ether_shost[2],
|
||||
eth_header->ether_shost[3],
|
||||
eth_header->ether_shost[4],
|
||||
eth_header->ether_shost[5]);
|
||||
info.source_mac = mac_addr;
|
||||
|
||||
struct ip *ip_header;
|
||||
ip_header = (struct ip *)(packet + sizeof(struct ether_header));
|
||||
|
||||
// Check if the packet's destination IP matches the specified destination IP
|
||||
char ip_addr[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &(ip_header->ip_dst), ip_addr, INET_ADDRSTRLEN);
|
||||
if (strcmp(ip_addr, DESTINATION_IP) != 0)
|
||||
{
|
||||
std::cerr << "Destination IP does not match" << std::endl;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Check if the packet is a UDP packet
|
||||
if (ip_header->ip_p != IPPROTO_UDP)
|
||||
{
|
||||
std::cerr << "Not a UDP packet" << std::endl;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Extract the UDP header
|
||||
struct udphdr *udp_header;
|
||||
udp_header = (struct udphdr *)(packet + sizeof(struct ether_header) + sizeof(struct ip));
|
||||
|
||||
// Check if the source and destination ports match
|
||||
if (ntohs(udp_header->source) != SOURCE_PORT || ntohs(udp_header->dest) != DESTINATION_PORT)
|
||||
{
|
||||
std::cerr << "Ports do not match" << std::endl;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Extract source IP address
|
||||
inet_ntop(AF_INET, &(ip_header->ip_src), ip_addr, INET_ADDRSTRLEN);
|
||||
info.source_ip = ip_addr;
|
||||
|
||||
// Debug output
|
||||
std::cout << "Source IP: " << info.source_ip << std::endl;
|
||||
std::cout << "Source MAC: " << info.source_mac << std::endl;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void IPReporter::update_tree_view(const PacketInfo &info)
|
||||
{
|
||||
QStandardItem *ipItem = new QStandardItem(QString::fromStdString(info.source_ip));
|
||||
QStandardItem *macItem = new QStandardItem(QString::fromStdString(info.source_mac));
|
||||
QList<QStandardItem *> items = {ipItem, macItem};
|
||||
model->appendRow(items);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
IPReporter reporter;
|
||||
reporter.setWindowTitle("IP Reporter");
|
||||
reporter.resize(600, 400);
|
||||
reporter.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#include "main.moc"
|
Reference in New Issue
Block a user