diff --git a/.gitignore b/.gitignore index 5397813..e2abb85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ upper/build -upper/upper.pro.* \ No newline at end of file +upper/upper.pro.* +.vscode \ No newline at end of file diff --git a/idapro_90_x64linux.run b/idapro_90_x64linux.run new file mode 100755 index 0000000..fed0f90 Binary files /dev/null and b/idapro_90_x64linux.run differ diff --git a/log.cpp b/log.cpp new file mode 100644 index 0000000..0324e1b --- /dev/null +++ b/log.cpp @@ -0,0 +1,2 @@ +#include "log.h" +FILE* log_output = stdout; // 只定义一次 \ No newline at end of file diff --git a/upper/main.cpp b/upper/main.cpp index 31867f3..5003327 100644 --- a/upper/main.cpp +++ b/upper/main.cpp @@ -1,7 +1,7 @@ #include "mainwindow.h" #include -FILE* log_output=stdout; + int main(int argc, char *argv[]) { diff --git a/upper/mainwindow.cpp b/upper/mainwindow.cpp index e890a47..88dd897 100644 --- a/upper/mainwindow.cpp +++ b/upper/mainwindow.cpp @@ -1,6 +1,5 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include "QDateTime" MainWindow::MainWindow(QWidget *parent) @@ -26,5 +25,19 @@ void MainWindow::on_pushButton_3_clicked() { string tmp =uf->EnumDriversAndDevices(); this->onPrint(QString::fromStdString(tmp)); + auto jsonList = json::parse(tmp); + ui->comboBox->clear(); + for(auto i :jsonList){ + if(i.contains("DevPath")){ + ui->comboBox->addItem(QString::fromStdString(i["DevPath"].get())); + } + } +} + + +void MainWindow::on_pushButton_4_clicked() +{ + QString tmp = ui->comboBox->currentText(); + uf->open(tmp.toStdString()); } diff --git a/upper/mainwindow.h b/upper/mainwindow.h index 9cb6c3a..d5f8e11 100644 --- a/upper/mainwindow.h +++ b/upper/mainwindow.h @@ -4,6 +4,10 @@ #include #include "../usbFilter.h" #include "QDebug" +#include "QDateTime" +#include "../json.hpp" + +using json = nlohmann::json; QT_BEGIN_NAMESPACE namespace Ui { @@ -25,6 +29,8 @@ public slots: private slots: void on_pushButton_3_clicked(); + void on_pushButton_4_clicked(); + private: Ui::MainWindow *ui; usbFilter *uf; diff --git a/upper/mainwindow.ui b/upper/mainwindow.ui index 845c204..c9e5bb2 100644 --- a/upper/mainwindow.ui +++ b/upper/mainwindow.ui @@ -15,21 +15,45 @@ - - + + - Stop Srv + Open - + + + + Start Srv - + + + + Stop Srv + + + + + + + Enum Drivers And Devices + + + + + + + Close + + + + Log @@ -41,13 +65,6 @@ - - - - Enum Drivers And Devices - - - diff --git a/upper/upper.pro b/upper/upper.pro index 0106bda..406d276 100644 --- a/upper/upper.pro +++ b/upper/upper.pro @@ -11,15 +11,19 @@ CONFIG += c++17 SOURCES += \ ../usbFilter.cpp \ main.cpp \ + ../log.cpp \ mainwindow.cpp HEADERS += \ ../json.hpp \ ../usbFilter.h \ - mainwindow.h + mainwindow.h\ + ../log.h FORMS += \ mainwindow.ui + + LIBS += -ludev # Default rules for deployment. diff --git a/usbFilter.cpp b/usbFilter.cpp index 1b99b30..26394df 100644 --- a/usbFilter.cpp +++ b/usbFilter.cpp @@ -99,3 +99,370 @@ string usbFilter::EnumDriversAndDevices() return list.dump(); } + +bool usbFilter::open(const string &devPath) +{ + // 检查设备路径是否为空 + if (devPath.empty()) { + return false; + } + // 检查设备路径是否存在 + string devPathTrans = sysfsToDevPath(devPath); + if (devPathTrans.empty()) { + LOG_ERROR("Device path does not exist" ); + return false; + }else{ + LOG_DEBUG("Opening device: %s", devPathTrans.c_str()); + } + + int pid = getDeviceUserPID(devPathTrans); + if (pid < 0) { + LOG_ERROR("No process is using the device: %s", devPathTrans.c_str()); + return false; + } else { + LOG_DEBUG("Device %s is being used by process with PID: %d", devPathTrans.c_str(), pid); + } + //获取当前目录 + string currendDir = CURRENTDIR; + // string scriptPath = currentDir + "/scripts"; + string scriptPath = currendDir + "/testScripts"; + + + LOG_INFO("Ready to run frida scripts. The scripts are located in %s.",scriptPath.c_str()); + + // 构造命令行 + // string cmd = "frida -p " + to_string(pid) + " -l " + scriptPath + "/frida_hook_libusb_basic_Version2.js &"; + string cmd = "frida -p " + to_string(pid) + " -l " + scriptPath + "/frida_hook_libusb_basic_Version2.js &"; + + LOG_DEBUG("Running command: %s", cmd.c_str()); + // 执行命令 + int result = system(cmd.c_str()); + if (result != 0) { + LOG_ERROR("Failed to run command: %s", cmd.c_str()); + return false; + } + LOG_INFO("Command executed successfully."); + return true; + +} + +string usbFilter::sysfsToDevPath(const string& sysfs_path) { + struct stat st; + + // Check if the sysfs path exists + if (stat(sysfs_path.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) { + return ""; // Path doesn't exist or is not a directory + } + + // Check if this is a USB device path + if (sysfs_path.find("/usb") != string::npos) { + return convertUsbSysfsPath(sysfs_path); + } + + // Check if this is a PCI/PCIe device path + if (sysfs_path.find("/pci") != string::npos) { + return convertPciSysfsPath(sysfs_path); + } + + // Unknown device type + return ""; +} + +// Helper function to convert USB sysfs path +string usbFilter::convertUsbSysfsPath(const string& sysfs_path) { + // Construct paths to busnum and devnum files + string busnum_path = sysfs_path + "/busnum"; + string devnum_path = sysfs_path + "/devnum"; + + // Read bus number + ifstream bus_file(busnum_path); + if (!bus_file.is_open()) { + return ""; + } + + int busnum = 0; + bus_file >> busnum; + bus_file.close(); + + if (busnum <= 0) { + return ""; + } + + // Read device number + ifstream dev_file(devnum_path); + if (!dev_file.is_open()) { + return ""; + } + + int devnum = 0; + dev_file >> devnum; + dev_file.close(); + + if (devnum <= 0) { + return ""; + } + + // Construct the /dev path with proper zero-padding + ostringstream dev_path; + dev_path << "/dev/bus/usb/" + << setfill('0') << setw(3) << busnum + << "/" + << setfill('0') << setw(3) << devnum; + + string result = dev_path.str(); + + // Check if the /dev node actually exists + if (access(result.c_str(), F_OK) != 0) { + return ""; // Device node doesn't exist + } + + return result; +} + +// Helper function to convert PCI/PCIe sysfs path +string usbFilter::convertPciSysfsPath(const string& sysfs_path) { + // First check if there are any special device nodes (e.g., for graphics cards, network cards) + + // 1. Check for graphics card + string device_path = sysfs_path + "/drm"; + DIR* dir = opendir(device_path.c_str()); + if (dir) { + // Found DRM device (likely a graphics card) + closedir(dir); + + // Look for card* entries in /dev/dri/ + dir = opendir("/dev/dri"); + if (dir) { + struct dirent *entry; + regex card_regex("card[0-9]+"); + + while ((entry = readdir(dir)) != NULL) { + string name = entry->d_name; + if (regex_match(name, card_regex)) { + // For each card, check if it corresponds to our PCI device + string cardpath = "/dev/dri/" + name; + + // Need to check if this card corresponds to our PCI device + // One way is to check the device node major/minor numbers against sys/dev entries + struct stat card_stat; + if (stat(cardpath.c_str(), &card_stat) == 0) { + ostringstream dev_path; + dev_path << sysfs_path << "/drm/" << name << "/dev"; + + ifstream dev_file(dev_path.str()); + if (dev_file.is_open()) { + string dev_numbers; + getline(dev_file, dev_numbers); + dev_file.close(); + + // Format is major:minor + size_t colon_pos = dev_numbers.find(':'); + if (colon_pos != string::npos) { + int major = stoi(dev_numbers.substr(0, colon_pos)); + int minor = stoi(dev_numbers.substr(colon_pos + 1)); + + if (major == major(card_stat.st_rdev) && + minor == minor(card_stat.st_rdev)) { + closedir(dir); + return cardpath; + } + } + } + } + } + } + closedir(dir); + } + } + + // 2. Check for network interfaces + device_path = sysfs_path + "/net"; + dir = opendir(device_path.c_str()); + if (dir) { + // Found network interface + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR && + strcmp(entry->d_name, ".") != 0 && + strcmp(entry->d_name, "..") != 0) { + + closedir(dir); + // Network interfaces don't have /dev entries, but we can return the interface name + return "/sys/class/net/" + string(entry->d_name); + } + } + closedir(dir); + } + + // 3. Check for NVMe devices + if (sysfs_path.find("nvme") != string::npos) { + // Extract the NVMe controller number (e.g., nvme0) + regex nvme_regex("nvme([0-9]+)"); + smatch match; + if (regex_search(sysfs_path, match, nvme_regex) && match.size() > 1) { + string nvme_num = match[1].str(); + string nvme_dev = "/dev/nvme" + nvme_num; + + if (access(nvme_dev.c_str(), F_OK) == 0) { + return nvme_dev; + } + } + } + + // 4. Check for SCSI/SATA devices that might be connected via PCIe + string block_path = sysfs_path + "/block"; + dir = opendir(block_path.c_str()); + if (dir) { + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR && + strcmp(entry->d_name, ".") != 0 && + strcmp(entry->d_name, "..") != 0) { + + string dev_name = entry->d_name; + string block_dev = "/dev/" + dev_name; + + if (access(block_dev.c_str(), F_OK) == 0) { + closedir(dir); + return block_dev; + } + } + } + closedir(dir); + } + + // 5. Generic way to find PCI device - try to use the device's resource file + ifstream resource_file(sysfs_path + "/resource"); + if (resource_file.is_open()) { + // This is more complex and would require parsing the resource file + // and checking if it maps to any character device + resource_file.close(); + } + + // 6. Check for udev links in /dev/char/ directory + string dev_content; + ifstream dev_file(sysfs_path + "/dev"); + if (dev_file.is_open()) { + getline(dev_file, dev_content); // Format is "major:minor" + dev_file.close(); + + if (!dev_content.empty()) { + // Check in /dev/char/ directory + string char_dev_path = "/dev/char/" + dev_content; + if (access(char_dev_path.c_str(), F_OK) == 0) { + // This is a character device + return char_dev_path; + } + + // Check in /dev/block/ directory + string block_dev_path = "/dev/block/" + dev_content; + if (access(block_dev_path.c_str(), F_OK) == 0) { + // This is a block device + return block_dev_path; + } + } + } + + // If we reach here, couldn't find a corresponding /dev node + return ""; +} + + + +// 修复getDeviceUserPID函数中的错误和警告 +int usbFilter::getDeviceUserPID(const string& devpath) { + // First check if the device path exists + struct stat st; + if (stat(devpath.c_str(), &st) != 0) { + return -1; // Device path doesn't exist + } + + // Use lsof command to find processes using this device + string cmd = "lsof -t " + devpath + " 2>/dev/null"; + + array buffer; + string result; + unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); + + if (!pipe) { + return -1; // Failed to run command + } + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + + // Trim whitespace and newlines + result.erase(result.find_last_not_of(" \n\r\t") + 1); + + // If result is empty, no process is using the device + if (result.empty()) { + return -1; + } + + // Parse the PID from the result (may have multiple lines if multiple processes) + regex pid_regex("^(\\d+)$", regex::multiline); + smatch match; + + if (regex_search(result, match, pid_regex) && match.size() > 1) { + try { + return stoi(match[1].str()); + } catch (const invalid_argument& e) { + return -1; + } catch (const out_of_range& e) { + return -1; + } + } + + // Alternative approach using /proc filesystem if lsof fails or isn't available + if (access("/proc", F_OK) == 0) { + // Iterate through all processes + string proc_dir = "/proc"; + array cmd; + + // 修复这行错误 + FILE* fp = popen("ls -d /proc/[0-9]*", "r"); + if (fp) { + while (fgets(cmd.data(), cmd.size(), fp) != nullptr) { + string pid_dir = cmd.data(); + pid_dir.erase(pid_dir.find_last_not_of("\n\r") + 1); + + // Check process fd directory + string fd_dir = pid_dir + "/fd"; + FILE* fd_fp = popen(("ls -l " + fd_dir + " 2>/dev/null").c_str(), "r"); + if (fd_fp) { + array fd_info; + bool found = false; + + while (fgets(fd_info.data(), fd_info.size(), fd_fp) != nullptr) { + string line = fd_info.data(); + + // Check if this fd points to our device + if (line.find(devpath) != string::npos) { + found = true; + break; + } + } + + pclose(fd_fp); + + if (found) { + pclose(fp); + // Extract PID from path /proc/[0-9]* + regex proc_regex("/proc/(\\d+)"); + if (regex_search(pid_dir, match, proc_regex) && match.size() > 1) { + try { + return stoi(match[1].str()); + } catch (...) { + return -1; + } + } + } + } + } + pclose(fp); + } + } + + return -1; // No process found using the device +} \ No newline at end of file diff --git a/usbFilter.h b/usbFilter.h index 465300f..371115b 100644 --- a/usbFilter.h +++ b/usbFilter.h @@ -8,6 +8,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#define CURRENTDIR "/home/leo/devCode/outer/USBFilter_30/usbFilter" using namespace std; @@ -23,5 +31,13 @@ public: void StartSrv(); void StopSrv(); string EnumDriversAndDevices(); + bool open(const string &devPath); + +private: + string sysfsToDevPath(const string& sysfs_path); + string convertUsbSysfsPath(const string& sysfs_path); + string convertPciSysfsPath(const string& sysfs_path); + int getDeviceUserPID(const string& devpath); + };