init
This commit is contained in:
commit
a9506ab74d
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
upper/build
|
||||
upper/upper.pro.*
|
||||
80
log.h
Normal file
80
log.h
Normal 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
|
||||
53
testScripts/frida_hook_libusb_basic_Version2.js
Executable file
53
testScripts/frida_hook_libusb_basic_Version2.js
Executable 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,且符号可见。");
|
||||
}
|
||||
84
testScripts/frida_hook_libusb_modify_data_Version2.js
Executable file
84
testScripts/frida_hook_libusb_modify_data_Version2.js
Executable 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,且符号可见。");
|
||||
}
|
||||
83
testScripts/frida_hook_libusb_replay_Version2.js
Executable file
83
testScripts/frida_hook_libusb_replay_Version2.js
Executable 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
12
upper/main.cpp
Normal 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
20
upper/mainwindow.cpp
Normal 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
27
upper/mainwindow.h
Normal 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
67
upper/mainwindow.ui
Normal 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
26
upper/upper.pro
Normal 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
11
usbFilter.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "usbFilter.h"
|
||||
|
||||
|
||||
usbFilter::usbFilter(/* args */)
|
||||
{
|
||||
}
|
||||
|
||||
usbFilter::~usbFilter()
|
||||
{
|
||||
}
|
||||
|
||||
14
usbFilter.h
Normal file
14
usbFilter.h
Normal file
@ -0,0 +1,14 @@
|
||||
#include "log.h"
|
||||
|
||||
class usbFilter
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
usbFilter(/* args */);
|
||||
~usbFilter();
|
||||
void StarSrv();
|
||||
void StopSrv();
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user