This commit is contained in:
lumos 2025-06-22 13:42:41 +08:00
commit a9506ab74d
12 changed files with 479 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
upper/build
upper/upper.pro.*

80
log.h Normal file
View File

@ -0,0 +1,80 @@
#ifndef LOG_H
#define LOG_H
#include <ctime> // 使用 std::time 和 std::strftime
#include <cstdio> // 使用 printf
#include <cstdarg> // 使用 va_list 和 va_start
#include <mutex> // 使用 std::mutex
// 定义打印等级
#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_ERROR 3
// 默认日志等级为INFO
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_DEBUG
#endif
// 颜色配置:用户空间启用颜色
#define LOG_COLOR true
// 颜色宏定义
#if LOG_COLOR
#define RESET_COLOR "\033[0m"
#define COLOR_DEBUG "\033[34m" // 蓝色
#define COLOR_INFO "\033[32m" // 绿色
#define COLOR_WARN "\033[33m" // 黄色
#define COLOR_ERROR "\033[31m" // 红色
#else
#define RESET_COLOR ""
#define COLOR_DEBUG ""
#define COLOR_INFO ""
#define COLOR_WARN ""
#define COLOR_ERROR ""
#endif
// 获取当前时间的字符串(用户空间实现)
inline const char* current_time() {
static char buffer[64];
std::time_t now = std::time(nullptr);
std::tm* tm_now = std::localtime(&now);
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_now);
return buffer;
}
// 定义一个静态互斥锁,保证线程安全
static std::mutex log_mutex;
// 定义一个外部 FILE 变量,可以用来切换输出目标
extern FILE* log_output; // 默认为 stdout
// 用户空间打印日志
#define LOG(level, format, ...) do {\
if (level >= LOG_LEVEL) {\
std::lock_guard<std::mutex> lock(log_mutex); /* 自动锁住互斥锁 */\
const char *level_str;\
const char *color;\
switch (level) {\
case LOG_LEVEL_DEBUG: level_str = "[DEBUG]"; color = COLOR_DEBUG; break;\
case LOG_LEVEL_INFO: level_str = "[INFO]"; color = COLOR_INFO; break;\
case LOG_LEVEL_WARN: level_str = "[WARN]"; color = COLOR_WARN; break;\
case LOG_LEVEL_ERROR: level_str = "[ERROR]"; color = COLOR_ERROR; break;\
default: level_str = "[UNKNOWN]"; color = ""; break;\
}\
fprintf(log_output, "%s%s %s %s:%d - ", color, current_time(), level_str, __FILE__, __LINE__);\
fprintf(log_output, format, ##__VA_ARGS__); /* 打印日志信息 */\
fprintf(log_output, "%s\n", RESET_COLOR);\
fflush(log_output); /* 强制刷新到指定输出目标 */\
}\
} while (0)
// 简便宏,用于各个等级的日志
#define LOG_DEBUG(format, ...) LOG(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...) LOG(LOG_LEVEL_INFO, format, ##__VA_ARGS__)
#define LOG_WARN(format, ...) LOG(LOG_LEVEL_WARN, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) LOG(LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
#endif // LOG_H

View File

@ -0,0 +1,53 @@
const symbol = DebugSymbol.fromName("libusb_bulk_transfer");
console.log("libusb_bulk_transfer symbol info:", symbol);
if (symbol && symbol.address) {
Interceptor.replace(symbol.address, new NativeCallback(function(
dev_handle, endpoint, data, length, transferred, timeout
) {
console.log('[!] libusb_bulk_transfer 被阻断');
console.log('dev_handle:', dev_handle);
console.log('endpoint:', endpoint);
console.log('data pointer:', data);
console.log('length:', length);
console.log('transferred pointer:', transferred);
console.log('timeout:', timeout);
try {
var nLen = length.toInt32 ? length.toInt32() : parseInt(length);
var bytesToPrint = Math.min(nLen, 64); // 只输出前64字节
if (data && nLen > 0) {
console.log("数据十六进制输出(前" + bytesToPrint + "字节):");
// 最原始的读取方法
var hexOutput = "";
for (var i = 0; i < bytesToPrint; i++) {
try {
// 尝试使用ptr对象的属性
var byteValue = data.add(i).readU8();
var hexByte = byteValue.toString(16).padStart(2, "0");
hexOutput += hexByte + " ";
if ((i + 1) % 16 === 0) {
hexOutput += "\n";
}
} catch (readErr) {
console.log("读取字节" + i + "时出错:", readErr);
break;
}
}
console.log(hexOutput);
} else {
console.log('data 指针无效 或 length <= 0');
}
} catch (e) {
console.log('读取data时出错:', e);
console.log('错误详情:', e.stack || e.toString());
}
return -1; // 阻断原函数
}, 'int', ['pointer', 'uchar', 'pointer', 'int', 'pointer', 'uint']));
console.log("已成功 Hook libusb_bulk_transfer at:", symbol.address);
} else {
console.log("找不到符号 libusb_bulk_transfer请确认程序未被 strip且符号可见。");
}

View File

@ -0,0 +1,84 @@
const symbol = DebugSymbol.fromName("libusb_bulk_transfer");
console.log("libusb_bulk_transfer symbol info:", symbol);
if (symbol && symbol.address) {
Interceptor.attach(symbol.address, {
onEnter: function(args) {
this.dev_handle = args[0];
this.endpoint = args[1];
this.data = args[2];
this.length = args[3];
this.transferred = args[4];
this.timeout = args[5];
console.log('[+] libusb_bulk_transfer 被拦截');
console.log('dev_handle:', this.dev_handle);
console.log('endpoint:', this.endpoint);
console.log('data pointer:', this.data);
console.log('length:', this.length);
console.log('transferred pointer:', this.transferred);
console.log('timeout:', this.timeout);
try {
var nLen = parseInt(this.length);
if (this.data && nLen > 0) {
console.log(`[+] 正在修改 ${nLen} 字节数据全部修改为0`);
// 先记录前16个字节用于展示修改前后差异
var previewBytes = 16;
var bytesToPreview = Math.min(nLen, previewBytes);
var originalHex = "";
for (var i = 0; i < bytesToPreview; i++) {
try {
var byteValue = this.data.add(i).readU8();
originalHex += byteValue.toString(16).padStart(2, "0") + " ";
} catch (readErr) {
console.log("读取原始数据时出错:", readErr);
break;
}
}
console.log("修改前前16字节:", originalHex);
// 修改数据为全0
for (var j = 0; j < nLen; j++) {
try {
this.data.add(j).writeU8(0);
} catch (writeErr) {
console.log("写入数据时出错:", writeErr);
break;
}
}
// 校验修改结果
var modifiedHex = "";
for (var k = 0; k < bytesToPreview; k++) {
try {
var newByteValue = this.data.add(k).readU8();
modifiedHex += newByteValue.toString(16).padStart(2, "0") + " ";
} catch (verifyErr) {
console.log("验证修改后数据时出错:", verifyErr);
break;
}
}
console.log("修改后前16字节:", modifiedHex);
console.log('[+] 数据修改完成');
} else {
console.log('[-] data 指针无效 或 length <= 0无法修改数据');
}
} catch (e) {
console.log('[-] 处理数据时出错:', e);
console.log('错误详情:', e.stack || e.toString());
}
},
onLeave: function(retval) {
console.log(`[+] libusb_bulk_transfer 返回值: ${retval}`);
// 如果想修改返回值,可以使用 retval.replace(0)
}
});
console.log("已成功 Hook libusb_bulk_transfer at:", symbol.address);
} else {
console.log("找不到符号 libusb_bulk_transfer请确认程序未被 strip且符号可见。");
}

View File

@ -0,0 +1,83 @@
const symbol = DebugSymbol.fromName("libusb_bulk_transfer");
console.log("libusb_bulk_transfer symbol info:", symbol);
if (symbol && symbol.address) {
Interceptor.attach(symbol.address, {
onEnter: function(args) {
// 保存原始参数
this.dev_handle = args[0];
this.endpoint = parseInt(args[1]); // 转换为整数
this.data = args[2];
this.length = parseInt(args[3]); // 转换为整数
this.transferred = args[4];
this.timeout = parseInt(args[5]); // 转换为整数
// 记录原始函数和参数,以便后续重放
this.original_function = symbol.address;
console.log('[+] libusb_bulk_transfer 被拦截');
console.log('dev_handle:', this.dev_handle);
console.log('endpoint:', this.endpoint, '(', args[1], ')');
console.log('data pointer:', this.data);
console.log('length:', this.length, '(', args[3], ')');
console.log('transferred pointer:', this.transferred);
console.log('timeout:', this.timeout, '(', args[5], ')');
// 显示部分原始数据前16字节
try {
if (this.data && this.length > 0) {
var bytesToPreview = Math.min(this.length, 16);
var originalHex = "";
for (var i = 0; i < bytesToPreview; i++) {
try {
var byteValue = this.data.add(i).readU8();
originalHex += byteValue.toString(16).padStart(2, "0") + " ";
} catch (readErr) {
console.log("读取原始数据时出错:", readErr);
break;
}
}
console.log("数据前16字节:", originalHex);
}
} catch (e) {
console.log('读取数据时出错:', e, e.stack);
}
},
onLeave: function(retval) {
console.log(`[+] libusb_bulk_transfer 原始调用返回值: ${retval}`);
// 重放次数设置
const replayCount = 3; // 设置重放次数这里重放3次
console.log(`[*] 开始重放 libusb_bulk_transfer ${replayCount}`);
// 重放函数
try {
const originalFunction = new NativeFunction(this.original_function, 'int',
['pointer', 'int', 'pointer', 'int', 'pointer', 'int']);
for (let i = 0; i < replayCount; i++) {
console.log(`[*] 正在重放第 ${i + 1}/${replayCount}`);
const replayResult = originalFunction(
this.dev_handle,
this.endpoint,
this.data,
this.length,
this.transferred,
this.timeout
);
console.log(`[+] 重放 #${i + 1} 返回值: ${replayResult}`);
}
console.log('[+] 重放完成');
} catch (err) {
console.log('[!] 重放时发生错误: ', err, err.stack);
}
}
});
console.log("已成功 Hook libusb_bulk_transfer at:", symbol.address);
} else {
console.log("找不到符号 libusb_bulk_transfer请确认程序未被 strip且符号可见。");
}

12
upper/main.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "mainwindow.h"
#include <QApplication>
FILE* log_output=stdout;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

20
upper/mainwindow.cpp Normal file
View File

@ -0,0 +1,20 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QDateTime"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onPrint(QString &msg){
QDateTime cur = QDateTime::currentDateTime();
QString tmp =cur.toString("yyyy-MM-dd HH:mm:ss");
ui->textBrowser->append(tmp+" --> "+msg);
}

27
upper/mainwindow.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void onPrint(QString &msg);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

67
upper/mainwindow.ui Normal file
View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Stop Srv</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Start Srv</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Log</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTextBrowser" name="textBrowser"/>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="pushButton_3">
<property name="text">
<string>Enum Drivers And Devices</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

26
upper/upper.pro Normal file
View File

@ -0,0 +1,26 @@
QT += core gui
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 += \
../usbFilter.cpp \
main.cpp \
mainwindow.cpp
HEADERS += \
../usbFilter.h \
mainwindow.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

11
usbFilter.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "usbFilter.h"
usbFilter::usbFilter(/* args */)
{
}
usbFilter::~usbFilter()
{
}

14
usbFilter.h Normal file
View File

@ -0,0 +1,14 @@
#include "log.h"
class usbFilter
{
private:
/* data */
public:
usbFilter(/* args */);
~usbFilter();
void StarSrv();
void StopSrv();
};