regular delta
This commit is contained in:
parent
33d42e49a2
commit
20c916077a
3
.gitignore
vendored
3
.gitignore
vendored
@ -19,3 +19,6 @@ plugins_install/
|
|||||||
peasoup_executable*/
|
peasoup_executable*/
|
||||||
|
|
||||||
/programs/Makefile*
|
/programs/Makefile*
|
||||||
|
|
||||||
|
|
||||||
|
*_plugin_import.cpp
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,4 +0,0 @@
|
|||||||
[submodule "qtbase"]
|
|
||||||
path = qtbase
|
|
||||||
url = https://code.qt.io/qt/qtbase.git
|
|
||||||
branch = v6.9.0
|
|
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"cstdlib": "c",
|
||||||
|
"memory": "cpp",
|
||||||
|
"semaphore": "cpp",
|
||||||
|
"stop_token": "cpp",
|
||||||
|
"iostream": "cpp"
|
||||||
|
}
|
||||||
|
}
|
15
DOC.md
Normal file
15
DOC.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
## `GetOpenFileNameA`
|
||||||
|
|
||||||
|
- Remove function call
|
||||||
|
- Copy custom file name into ofn->lpstrFile, ensure null termination
|
||||||
|
- Set return value to 1
|
||||||
|
|
||||||
|
## `QFileDialog::getOpenFileName`
|
||||||
|
|
||||||
|
- Remove function call
|
||||||
|
- Grab `QString` constructor from `qt6core.dll` and call it with custom file name
|
||||||
|
|
||||||
|
## `QFileDialog::getOpenFileNames`
|
||||||
|
|
||||||
|
- Remove function call
|
||||||
|
- Grab `QString` constructor from `qt6core.dll` and call it with custom file name
|
@ -2,11 +2,12 @@
|
|||||||
|
|
||||||
## DLL methods
|
## DLL methods
|
||||||
|
|
||||||
- [x] `GetOpenFileNameA`
|
- [x] `GetOpenFileNameA` (ANSI)
|
||||||
- [ ] `IFileOpenDialog`
|
- [x] `GetOpenFileNameW` (UTF-16)
|
||||||
|
- [x] `IFileOpenDialog`
|
||||||
- [x] `QFileDialog::getOpenFileName`
|
- [x] `QFileDialog::getOpenFileName`
|
||||||
- [ ] `QFileDialog::getOpenFileNames`
|
- [ ] `QFileDialog::getOpenFileNames`
|
||||||
- [ ] `QFileDialog::getOpenFileUrl`
|
- [x] `QFileDialog::getOpenFileUrl`
|
||||||
- [ ] `QFileDialog::getOpenFileUrls`
|
- [ ] `QFileDialog::getOpenFileUrls`
|
||||||
- [ ] `QFileDialog::getOpenFileContent`
|
- [ ] `QFileDialog::getOpenFileContent`
|
||||||
- [ ] `wxFileDialog`
|
- [ ] `wxFileDialog`
|
||||||
|
@ -5,12 +5,8 @@ project(CustomClient)
|
|||||||
find_package(DynamoRIO REQUIRED)
|
find_package(DynamoRIO REQUIRED)
|
||||||
|
|
||||||
add_library(CustomClient SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/client.c")
|
add_library(CustomClient SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/client.c")
|
||||||
|
target_link_libraries(CustomClient drwrap drmgr)
|
||||||
add_definitions(-DCC_QTLIB_DLL_PATH="${CMAKE_CURRENT_SOURCE_DIR}/lib/build/release/CC_QTLib.dll")
|
|
||||||
|
|
||||||
target_include_directories(CustomClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib")
|
|
||||||
target_link_directories(CustomClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib/build/release")
|
|
||||||
|
|
||||||
target_link_libraries(CustomClient drwrap drmgr CC_QTLib)
|
|
||||||
|
|
||||||
configure_DynamoRIO_client(CustomClient)
|
configure_DynamoRIO_client(CustomClient)
|
||||||
|
use_DynamoRIO_extension(CustomClient drwrap)
|
||||||
|
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#include <QtCore/qglobal.h>
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QList>
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QString_insert(QString **ptr, const char *str) {
|
|
||||||
*ptr = new QString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT QString *CC_QString_create(const char *str) {
|
|
||||||
return new QString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QString_destroy(QString *str) {
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QUrl_insert(QUrl **ptr, const char *str) {
|
|
||||||
*ptr = new QUrl(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT QUrl *CC_QUrl_create(const char *str) {
|
|
||||||
return new QUrl(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QUrl_destroy(QUrl *str) {
|
|
||||||
delete str;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT QList<QString> *CC_QStringList_create() {
|
|
||||||
return new QList<QString>();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QStringList_destroy(QList<QString> *lst) {
|
|
||||||
delete lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QStringList_append(QList<QString> *lst, QString *el) {
|
|
||||||
lst->append(*el);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT QList<QUrl> *CC_QUrlList_create() {
|
|
||||||
return new QList<QUrl>();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QUrlList_destroy(QList<QUrl> *lst) {
|
|
||||||
delete lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" Q_DECL_EXPORT void CC_QUrlList_append(QList<QUrl> *lst, QUrl *el) {
|
|
||||||
lst->append(*el);
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
void CC_QString_insert(void *ptr, const char *str);
|
|
||||||
void *CC_QString_create(const char *str);
|
|
||||||
void CC_QString_destroy(void *str);
|
|
||||||
|
|
||||||
// QUrl
|
|
||||||
void CC_QUrl_insert(void *ptr, const char *str);
|
|
||||||
void *CC_QUrl_create(const char *str);
|
|
||||||
void CC_QUrl_destroy(void *str);
|
|
||||||
|
|
||||||
// QStringList
|
|
||||||
void *CC_QStringList_create();
|
|
||||||
void CC_QStringList_destroy(void *lst);
|
|
||||||
void CC_QStringList_append(void *lst, void *el);
|
|
||||||
|
|
||||||
// QUrlList
|
|
||||||
void *CC_QUrlList_create(const char *str);
|
|
||||||
void CC_QUrlList_destroy(void *lst);
|
|
||||||
void CC_QUrlList_append(void *lst, void *el);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// QString
|
|
||||||
void (*CC_QString_insert)(void *ptr, const char *str);
|
|
||||||
void *(*CC_QString_create)(const char *str);
|
|
||||||
void (*CC_QString_destroy)(void *str);
|
|
||||||
|
|
||||||
// QUrl
|
|
||||||
void (*CC_QUrl_insert)(void *ptr, const char *str);
|
|
||||||
void *(*CC_QUrl_create)(const char *str);
|
|
||||||
void (*CC_QUrl_destroy)(void *str);
|
|
||||||
|
|
||||||
// QStringList
|
|
||||||
void *(*CC_QStringList_create)();
|
|
||||||
void (*CC_QStringList_destroy)(void *lst);
|
|
||||||
void (*CC_QStringList_append)(void *lst, void *el);
|
|
||||||
|
|
||||||
// QUrlList
|
|
||||||
void *(*CC_QUrlList_create)(const char *str);
|
|
||||||
void (*CC_QUrlList_destroy)(void *lst);
|
|
||||||
void (*CC_QUrlList_append)(void *lst, void *el);
|
|
||||||
|
|
||||||
inline void CC_QTLib_load() {
|
|
||||||
#ifndef CC_QTLIB_DLL_PATH
|
|
||||||
#error "CC_QTLIB_DLL_PATH not defined"
|
|
||||||
#else
|
|
||||||
|
|
||||||
HMODULE hDLL;
|
|
||||||
|
|
||||||
// hDLL = LoadLibrary("C:\\Qt\\6.9.0\\msvc2022_64\\bin\\Qt6Core.dll");
|
|
||||||
// if (!hDLL) {
|
|
||||||
// dr_printf("failed to load %s\n", "C:\\Qt\\6.9.0\\msvc2022_64\\bin\\Qt6Core.dll");
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
hDLL = LoadLibrary(CC_QTLIB_DLL_PATH);
|
|
||||||
if (!hDLL) {
|
|
||||||
dr_printf("failed to load %s\n", CC_QTLIB_DLL_PATH);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CC_QTLIB_LOAD(name) name = GetProcAddress(hDLL, #name);
|
|
||||||
|
|
||||||
CC_QTLIB_LOAD(CC_QString_insert);
|
|
||||||
CC_QTLIB_LOAD(CC_QString_create);
|
|
||||||
CC_QTLIB_LOAD(CC_QString_destroy);
|
|
||||||
|
|
||||||
CC_QTLIB_LOAD(CC_QUrl_insert);
|
|
||||||
CC_QTLIB_LOAD(CC_QUrl_create);
|
|
||||||
CC_QTLIB_LOAD(CC_QUrl_destroy);
|
|
||||||
|
|
||||||
CC_QTLIB_LOAD(CC_QStringList_create);
|
|
||||||
CC_QTLIB_LOAD(CC_QStringList_destroy);
|
|
||||||
CC_QTLIB_LOAD(CC_QStringList_append);
|
|
||||||
|
|
||||||
CC_QTLIB_LOAD(CC_QUrlList_create);
|
|
||||||
CC_QTLIB_LOAD(CC_QUrlList_destroy);
|
|
||||||
CC_QTLIB_LOAD(CC_QUrlList_append);
|
|
||||||
|
|
||||||
dr_printf("%s loaded!\n", CC_QTLIB_DLL_PATH);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
@ -1,5 +0,0 @@
|
|||||||
QT += core widgets
|
|
||||||
TEMPLATE = lib
|
|
||||||
TARGET = CC_QTLib
|
|
||||||
SOURCES += CC_QTLib.cpp
|
|
||||||
CONFIG += staticlib
|
|
@ -1,153 +1,236 @@
|
|||||||
#include "dr_api.h"
|
#include "dr_api.h"
|
||||||
|
#include "dr_tools.h"
|
||||||
|
#include "drwrap.h"
|
||||||
#include "dr_ir_opnd.h"
|
#include "dr_ir_opnd.h"
|
||||||
#include "dr_ir_instr.h"
|
#include "dr_ir_instr.h"
|
||||||
#include "dr_ir_opcodes_x86.h"
|
|
||||||
#include "dr_ir_macros_x86.h"
|
|
||||||
|
|
||||||
#include "CC_QTLib.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
|
||||||
|
// Note: Some Qt mangled names might vary slightly by compiler version.
|
||||||
|
// These are typical for MSVC.
|
||||||
|
const char *MANGLED_QString_const = "??0QString@@QEAA@PEBD@Z";
|
||||||
|
const char *MANGLED_QUrl_const = "??0QUrl@@QEAA@AEBVQString@@W4ParsingMode@0@@Z";
|
||||||
|
const char *MANGLED_QFileDialog_getOpenFileName = "?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z";
|
||||||
|
const char *MANGLED_QFileDialog_getOpenFileNames = "?getOpenFileNames@QFileDialog@@SA?AV?$QList@VQString@@@@PEAVQWidget@@AEBVQString@@11PEAV4@V?$QFlags@W4Option@QFileDialog@@@@@Z";
|
||||||
|
const char *MANGLED_QFileDialog_getOpenFileUrl = "?getOpenFileUrl@QFileDialog@@SA?AVQUrl@@PEAVQWidget@@AEBVQString@@AEBV2@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z";
|
||||||
|
const char *MANGLED_QFileDialog_getOpenFileUrls = "?getOpenFileUrls@QFileDialog@@SA?AV?$QList@VQUrl@@@@PEAVQWidget@@AEBVQString@@AEBVQUrl@@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z";
|
||||||
|
const char *MANGLED_QFileDialog_getOpenFileContent = "?getOpenFileContent@QFileDialog@@SAXAEBVQString@@AEBV?$function@$$A6AXAEBVQString@@AEBVQByteArray@@@Z@std@@PEAVQWidget@@@Z";
|
||||||
|
|
||||||
char *CUSTOM_FILE = "C:\\Users\\vboxuser\\Downloads\\spoofed_number.txt";
|
char *CUSTOM_FILE = "C:\\Users\\vboxuser\\Downloads\\spoofed_number.txt";
|
||||||
|
|
||||||
static app_pc pc_GetOpenFileNameA = NULL;
|
// Function pointers for functions we need to call ourselves
|
||||||
|
static void (*fn_QString_const)(void *qstring, const char *str) = NULL;
|
||||||
|
static void (*fn_QUrl_const)(void *qurl, void *qstring, int parsing_mode) = NULL;
|
||||||
|
static LPVOID (*fn_CoTaskMemAlloc)(size_t cb) = NULL;
|
||||||
|
static HRESULT (*fn_SHCreateItemFromParsingName)(PWSTR, void *, void *, void **);
|
||||||
|
|
||||||
void (*QString_const)(void *, char *) = NULL;
|
// --- drwrap Callbacks for IFileOpenDialog (COM) ---
|
||||||
void (*QArray_allocate)(void *, int64_t, int64_t, int64_t, int64_t) = NULL;
|
|
||||||
static app_pc pc_QUrl_const = NULL;
|
|
||||||
static app_pc pc_QList_const = NULL;
|
|
||||||
|
|
||||||
static app_pc pc_QFileDialog_getOpenFileName = NULL;
|
struct per_thread_info
|
||||||
static app_pc pc_QFileDialog_getOpenFileNames = NULL;
|
{
|
||||||
static app_pc pc_QFileDialog_getOpenFileUrl = NULL;
|
// Information needed for COM hooking
|
||||||
static app_pc pc_QFileDialog_getOpenFileUrls = NULL;
|
IShellItem *sitem_to_wrap;
|
||||||
static app_pc pc_QFileDialog_getOpenFileContent = NULL;
|
};
|
||||||
|
|
||||||
static void intercept_GetOpenFileNameA() {
|
static void pre_CoCreateInstance(void *wrapctx, void **user_data);
|
||||||
void *drcontext = dr_get_current_drcontext();
|
static void post_CoCreateInstance(void *wrapctx, void *user_data);
|
||||||
|
static void post_IFileOpenDialog_GetResult(void *wrapctx, void *user_data);
|
||||||
|
static void pre_IShellItem_GetDisplayName(void *wrapctx, void **user_data);
|
||||||
|
static void pre_IFileOpenDialog_GetResult(void *wrapctx, void **user_data);
|
||||||
|
static void pre_IFileOpenDialog_Show(void *wrapctx, void **user_data);
|
||||||
|
|
||||||
dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
|
static HRESULT custom_IFileDialog_Show(void *, void *);
|
||||||
dr_get_mcontext(drcontext, &mcontext);
|
static HRESULT custom_IFileDialog_GetResult(void *, IShellItem **ppsitem);
|
||||||
|
|
||||||
OPENFILENAME *ofn = (OPENFILENAME *)mcontext.rcx;
|
struct IFileOpenDialogVtbl customFODVtbl = {};
|
||||||
|
|
||||||
for (int i = 0; i < strlen(CUSTOM_FILE); i++) ofn->lpstrFile[i] = CUSTOM_FILE[i];
|
// --- drwrap Callbacks for WinAPI Functions ---
|
||||||
ofn->lpstrFile[strlen(CUSTOM_FILE)] = 0;
|
|
||||||
|
|
||||||
mcontext.rax = 1;
|
static void pre_GetOpenFileNameA(void *wrapctx, void **user_data)
|
||||||
|
{
|
||||||
dr_set_mcontext(drcontext, &mcontext);
|
OPENFILENAMEA *ofn = (OPENFILENAMEA *)drwrap_get_arg(wrapctx, 0);
|
||||||
}
|
if (ofn && ofn->lpstrFile)
|
||||||
|
{
|
||||||
static void intercept_QFileDialog_getOpenFileName() {
|
strncpy(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1);
|
||||||
void *drcontext = dr_get_current_drcontext();
|
ofn->lpstrFile[ofn->nMaxFile - 1] = '\0';
|
||||||
|
|
||||||
dr_printf("intercept_QFileDialog_getOpenFileName\n");
|
|
||||||
|
|
||||||
dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
|
|
||||||
dr_get_mcontext(drcontext, &mcontext);
|
|
||||||
|
|
||||||
CC_QString_insert((void *)mcontext.rcx, CUSTOM_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void intercept_QFileDialog_getOpenFileNames() {
|
|
||||||
void *drcontext = dr_get_current_drcontext();
|
|
||||||
|
|
||||||
dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
|
|
||||||
dr_get_mcontext(drcontext, &mcontext);
|
|
||||||
|
|
||||||
// make use of QString constructor to construct return value
|
|
||||||
// void *QArray = (void *)mcontext.rcx;
|
|
||||||
|
|
||||||
// char QString[24];
|
|
||||||
// QString_const(QString, CUSTOM_FILE);
|
|
||||||
|
|
||||||
// QArray_allocate(QArray, 0x18, 8, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void event_exit(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static void event_module_load(void *drcontext, const module_data_t *mod, bool loaded) {
|
|
||||||
char lowerpath[MAX_PATH];
|
|
||||||
strcpy(lowerpath, mod->full_path);
|
|
||||||
for (int i = 0; i < strlen(lowerpath); i++) {
|
|
||||||
lowerpath[i] = tolower(lowerpath[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(lowerpath, "qt6core.dll")) {
|
drwrap_skip_call(wrapctx, (void *)1, 0);
|
||||||
QString_const = (app_pc)dr_get_proc_address(mod->handle, "??0QString@@QEAA@PEBD@Z");
|
}
|
||||||
QArray_allocate = (app_pc)dr_get_proc_address(mod->handle, "?allocate@QArrayData@@SAPEAXPEAPEAU1@_J11W4AllocationOption@1@@Z");
|
|
||||||
// pc_QStringList_const = (app_pc)dr_get_proc_address(mod->handle, "??0QString@@QEAA@PEBD@Z");
|
static void pre_GetOpenFileNameW(void *wrapctx, void **user_data)
|
||||||
// if (pc_QString_const) dr_printf("Found QString::QString at %p\n", pc_QString_const);
|
{
|
||||||
}
|
OPENFILENAMEW *ofn = (OPENFILENAMEW *)drwrap_get_arg(wrapctx, 0);
|
||||||
if (strstr(lowerpath, "qt6widgets.dll")) {
|
if (ofn && ofn->lpstrFile)
|
||||||
pc_QFileDialog_getOpenFileName = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z");
|
{
|
||||||
pc_QFileDialog_getOpenFileNames = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileNames@QFileDialog@@SA?AV?$QList@VQString@@@@PEAVQWidget@@AEBVQString@@11PEAV4@V?$QFlags@W4Option@QFileDialog@@@@@Z");
|
mbstowcs(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1);
|
||||||
pc_QFileDialog_getOpenFileUrl = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileUrl@QFileDialog@@SA?AVQUrl@@PEAVQWidget@@AEBVQString@@AEBV2@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z");
|
ofn->lpstrFile[ofn->nMaxFile - 1] = L'\0';
|
||||||
pc_QFileDialog_getOpenFileUrls = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileUrls@QFileDialog@@SA?AV?$QList@VQUrl@@@@PEAVQWidget@@AEBVQString@@AEBVQUrl@@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z");
|
|
||||||
pc_QFileDialog_getOpenFileContent = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileContent@QFileDialog@@SAXAEBVQString@@AEBV?$function@$$A6AXAEBVQString@@AEBVQByteArray@@@Z@std@@PEAVQWidget@@@Z");
|
|
||||||
// if (pc_QFileDialog_getOpenFileName) dr_printf("Found QFileDialog::getOpenFileName at %p\n", pc_QFileDialog_getOpenFileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(lowerpath, "comdlg32.dll")) {
|
drwrap_skip_call(wrapctx, (void *)1, 0);
|
||||||
pc_GetOpenFileNameA = (app_pc)dr_get_proc_address(mod->handle, "GetOpenFileNameA");
|
}
|
||||||
// if (pc_GetOpenFileNameA) dr_printf("Found GetOpenFileNameA at %p\n", pc_GetOpenFileNameA);
|
|
||||||
|
// --- drwrap Callbacks for Qt Functions ---
|
||||||
|
|
||||||
|
static void pre_QFileDialog_getOpenFileName(void *wrapctx, void **user_data)
|
||||||
|
{
|
||||||
|
if (fn_QString_const == NULL)
|
||||||
|
return;
|
||||||
|
// The return value is passed as a pointer in the first argument (sret)
|
||||||
|
void *qstring_ret_ptr = (void *)drwrap_get_arg(wrapctx, 0);
|
||||||
|
fn_QString_const(qstring_ret_ptr, CUSTOM_FILE);
|
||||||
|
drwrap_skip_call(wrapctx, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pre_QFileDialog_getOpenFileUrl(void *wrapctx, void **user_data)
|
||||||
|
{
|
||||||
|
if (fn_QString_const == NULL || fn_QUrl_const == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *prefix = "file:///";
|
||||||
|
char urlbuf[MAX_PATH + 10];
|
||||||
|
snprintf(urlbuf, sizeof(urlbuf), "%s%s", prefix, CUSTOM_FILE);
|
||||||
|
// Replace backslashes for URL format
|
||||||
|
for (char *p = urlbuf; *p; ++p)
|
||||||
|
{
|
||||||
|
if (*p == '\\')
|
||||||
|
*p = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a temporary QString for the URL
|
||||||
|
char local_qstring[24]; // Allocate space for a QString object on the stack
|
||||||
|
fn_QString_const(local_qstring, urlbuf);
|
||||||
|
|
||||||
|
// Get the return QUrl object pointer (sret)
|
||||||
|
void *qurl_ret_ptr = (void *)drwrap_get_arg(wrapctx, 0);
|
||||||
|
fn_QUrl_const(qurl_ret_ptr, local_qstring, 0); // 0 is TolerantMode
|
||||||
|
|
||||||
|
drwrap_skip_call(wrapctx, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- COM Wrapping Logic ---
|
||||||
|
|
||||||
|
static void pre_CoCreateInstance(void *wrapctx, void **user_data)
|
||||||
|
{
|
||||||
|
// Arguments: rclsid, pUnkOuter, dwClsContext, riid, ppv
|
||||||
|
const IID *riid = (const IID *)drwrap_get_arg(wrapctx, 3);
|
||||||
|
const CLSID *rclsid = (const CLSID *)drwrap_get_arg(wrapctx, 0);
|
||||||
|
|
||||||
|
// We are only interested in the creation of a FileOpenDialog
|
||||||
|
if (rclsid != NULL && IsEqualIID(rclsid, &CLSID_FileOpenDialog) &&
|
||||||
|
riid != NULL && IsEqualIID(riid, &IID_IFileOpenDialog))
|
||||||
|
{
|
||||||
|
|
||||||
|
dr_printf("drwrap: Intercepting CoCreateInstance for FileOpenDialog\n");
|
||||||
|
// Pass the pointer to the output interface pointer (ppv) to the post-hook
|
||||||
|
*user_data = drwrap_get_arg(wrapctx, 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*user_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void post_CoCreateInstance(void *wrapctx, void *user_data)
|
||||||
|
{
|
||||||
|
// If user_data is NULL, this wasn't the CoCreateInstance we cared about
|
||||||
|
if (!user_data)
|
||||||
|
return;
|
||||||
|
|
||||||
static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) {
|
HRESULT hr = (HRESULT)drwrap_get_retval(wrapctx);
|
||||||
instr_t *to_remove = NULL, *instr = instrlist_first(bb);
|
if (SUCCEEDED(hr))
|
||||||
while (instr) {
|
{
|
||||||
instr_t *next = instr_get_next(instr);
|
// The user_data is the ppv argument from the pre-hook
|
||||||
|
IFileOpenDialog **ppv = (IFileOpenDialog **)user_data;
|
||||||
|
if (ppv && *ppv)
|
||||||
|
{
|
||||||
|
IFileOpenDialog *fod = *ppv;
|
||||||
|
|
||||||
app_pc target = NULL;
|
customFODVtbl = *fod->lpVtbl;
|
||||||
|
customFODVtbl.Show = custom_IFileDialog_Show;
|
||||||
|
customFODVtbl.GetResult = custom_IFileDialog_GetResult;
|
||||||
|
|
||||||
if (instr_is_call_direct(instr)) {
|
fod->lpVtbl = &customFODVtbl;
|
||||||
app_pc target = instr_get_branch_target_pc(instr);
|
|
||||||
} else if (instr_is_call_indirect(instr)) {
|
|
||||||
opnd_t opnd = instr_get_src(instr, 0);
|
|
||||||
if (opnd_is_memory_reference(opnd)) {
|
|
||||||
app_pc addr = opnd_compute_address(opnd, drcontext);
|
|
||||||
if (addr) dr_safe_read(addr, sizeof(app_pc), &target, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target) {
|
|
||||||
instr = next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target == pc_GetOpenFileNameA) {
|
|
||||||
// dr_printf("Call to GetOpenFileNameA detected at %p\n", instr_get_app_pc(instr));
|
|
||||||
dr_insert_clean_call(drcontext, bb, instr, (void *)intercept_GetOpenFileNameA, false, 0);
|
|
||||||
instrlist_remove(bb, instr);
|
|
||||||
instr_destroy(drcontext, instr);
|
|
||||||
}
|
|
||||||
else if (target == pc_QFileDialog_getOpenFileName) {
|
|
||||||
// dr_printf("Call to QFileDialog::getOpenFileName detected at %p\n", instr_get_app_pc(instr));
|
|
||||||
dr_insert_clean_call(drcontext, bb, instr, (void *)intercept_QFileDialog_getOpenFileName, false, 0);
|
|
||||||
instrlist_remove(bb, instr);
|
|
||||||
instr_destroy(drcontext, instr);
|
|
||||||
}
|
|
||||||
|
|
||||||
instr = next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DR_EMIT_DEFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) {
|
static HRESULT custom_IFileDialog_Show(void *self, void *b) {
|
||||||
dr_set_client_name("Custom DynamoRIO client", "https://gitea.cloud.lehnert.dev/ludwig/windows-binary-fuzzing");
|
return S_OK;
|
||||||
dr_register_exit_event(event_exit);
|
}
|
||||||
|
|
||||||
|
static HRESULT custom_IFileDialog_GetResult(void *self, IShellItem **ppsitem) {
|
||||||
|
WCHAR file[MAX_PATH];
|
||||||
|
mbstowcs(file, CUSTOM_FILE, MAX_PATH);
|
||||||
|
file[MAX_PATH - 1] = L'\0';
|
||||||
|
|
||||||
|
return fn_SHCreateItemFromParsingName(file, NULL, &IID_IShellItem, (void **)ppsitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Main Events ---
|
||||||
|
|
||||||
|
static void event_module_load(void *drcontext, const module_data_t *mod, bool loaded)
|
||||||
|
{
|
||||||
|
// Wrap functions as their modules are loaded.
|
||||||
|
// This is much more efficient than iterating every basic block.
|
||||||
|
|
||||||
|
#define WRAP_FUNCTION(name, pre_hook, post_hook) \
|
||||||
|
{ \
|
||||||
|
app_pc addr = (app_pc)dr_get_proc_address(mod->handle, name); \
|
||||||
|
if (addr != NULL) \
|
||||||
|
{ \
|
||||||
|
drwrap_wrap(addr, pre_hook, post_hook); \
|
||||||
|
dr_printf("Wrapped %s!%s at %p\n", dr_module_preferred_name(mod), name, addr); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_FUNCTION_POINTER(var, name) \
|
||||||
|
{ \
|
||||||
|
if (var == NULL) \
|
||||||
|
{ \
|
||||||
|
var = (void *)dr_get_proc_address(mod->handle, name); \
|
||||||
|
if (var != NULL) \
|
||||||
|
dr_printf("Found function pointer %s in %s\n", name, dr_module_preferred_name(mod)); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
// WinAPI Hooks
|
||||||
|
WRAP_FUNCTION("GetOpenFileNameA", pre_GetOpenFileNameA, NULL);
|
||||||
|
WRAP_FUNCTION("GetOpenFileNameW", pre_GetOpenFileNameW, NULL);
|
||||||
|
WRAP_FUNCTION("CoCreateInstance", pre_CoCreateInstance, post_CoCreateInstance);
|
||||||
|
|
||||||
|
// Qt Hooks
|
||||||
|
WRAP_FUNCTION(MANGLED_QFileDialog_getOpenFileName, pre_QFileDialog_getOpenFileName, NULL);
|
||||||
|
WRAP_FUNCTION(MANGLED_QFileDialog_getOpenFileUrl, pre_QFileDialog_getOpenFileUrl, NULL);
|
||||||
|
|
||||||
|
// Get pointers to functions we need to call ourselves
|
||||||
|
GET_FUNCTION_POINTER(fn_QString_const, MANGLED_QString_const);
|
||||||
|
GET_FUNCTION_POINTER(fn_QUrl_const, MANGLED_QUrl_const);
|
||||||
|
GET_FUNCTION_POINTER(fn_CoTaskMemAlloc, "CoTaskMemAlloc");
|
||||||
|
GET_FUNCTION_POINTER(fn_SHCreateItemFromParsingName, "SHCreateItemFromParsingName");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void event_exit(void)
|
||||||
|
{
|
||||||
|
drwrap_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[])
|
||||||
|
{
|
||||||
|
dr_set_client_name("File Dialog Interceptor", "http://example.com/");
|
||||||
|
|
||||||
|
if (!drwrap_init())
|
||||||
|
{
|
||||||
|
DR_ASSERT_MSG(false, "drwrap_init failed");
|
||||||
|
}
|
||||||
|
|
||||||
dr_register_module_load_event(event_module_load);
|
dr_register_module_load_event(event_module_load);
|
||||||
dr_register_bb_event(event_basic_block);
|
dr_register_exit_event(event_exit);
|
||||||
|
}
|
||||||
// CC_QTLib_load();
|
|
||||||
}
|
|
@ -2,6 +2,8 @@ cl /Fe:compiled\Foo.exe source\Foo.c /Zi /Od /link /MACHINE:X64
|
|||||||
|
|
||||||
cl /Fe:compiled\GetOpenFileNameA.exe comdlg32.lib source\GetOpenFileNameA.c /Zi /Od /link /MACHINE:X64
|
cl /Fe:compiled\GetOpenFileNameA.exe comdlg32.lib source\GetOpenFileNameA.c /Zi /Od /link /MACHINE:X64
|
||||||
|
|
||||||
|
cl /Fe:compiled\GetOpenFileNameW.exe comdlg32.lib source\GetOpenFileNameA.c /Zi /Od /link /MACHINE:X64
|
||||||
|
|
||||||
cl /Fe:compiled\IFileDialog.exe uuid.lib ole32.lib source\IFileDialog.c /Zi /Od /link /MACHINE:X64
|
cl /Fe:compiled\IFileDialog.exe uuid.lib ole32.lib source\IFileDialog.c /Zi /Od /link /MACHINE:X64
|
||||||
|
|
||||||
qmake source\QT_getOpenFileContent.pro
|
qmake source\QT_getOpenFileContent.pro
|
||||||
|
Binary file not shown.
Binary file not shown.
BIN
programs/compiled/GetOpenFileNameW.exe
Normal file
BIN
programs/compiled/GetOpenFileNameW.exe
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -15,9 +15,10 @@ int main() {
|
|||||||
.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST
|
.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST
|
||||||
};
|
};
|
||||||
|
|
||||||
int res = GetOpenFileName(&ofn);
|
int res = GetOpenFileNameA(&ofn);
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
puts("GetOpenFileName(...) failed!");
|
puts("GetOpenFileNameA(...) failed!");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
programs/source/GetOpenFileNameW.c
Normal file
42
programs/source/GetOpenFileNameW.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <commdlg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
wchar_t file[MAX_PATH] = {0};
|
||||||
|
|
||||||
|
OPENFILENAME ofn = {
|
||||||
|
.lStructSize = sizeof(ofn),
|
||||||
|
.lpstrFilter = "All Files\0*.*\0",
|
||||||
|
.lpstrFile = file,
|
||||||
|
.nMaxFile = MAX_PATH,
|
||||||
|
.lpstrTitle = "Select File",
|
||||||
|
.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST
|
||||||
|
};
|
||||||
|
|
||||||
|
int res = GetOpenFileNameW(&ofn);
|
||||||
|
if (!res) {
|
||||||
|
puts("GetOpenFileNameW(...) failed!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char ansiFile[MAX_PATH];
|
||||||
|
wcstombs(ansiFile, ofn.lpstrFile, MAX_PATH);
|
||||||
|
|
||||||
|
FILE *f = fopen(ansiFile, "r");
|
||||||
|
if (!f) {
|
||||||
|
perror("fopen(...)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
long input;
|
||||||
|
if (fscanf(f, "%ld", &input) != 1) {
|
||||||
|
puts("fscanf(...) failed to scan input number");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%ld\n", 2 * input);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -9,16 +9,9 @@
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
QSemaphore sem(1);
|
auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) {
|
||||||
sem.acquire();
|
|
||||||
|
|
||||||
int returnCode = -1;
|
|
||||||
|
|
||||||
auto fileContentReady = [&returnCode, &sem](const QString &fileName, const QByteArray &fileContent) {
|
|
||||||
if (fileName.isEmpty() || !QFile(fileName).exists()) {
|
if (fileName.isEmpty() || !QFile(fileName).exists()) {
|
||||||
std::cerr << "Failed to open file" << std::endl;
|
std::cerr << "Failed to open file" << std::endl;
|
||||||
returnCode = 1;
|
|
||||||
sem.release();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,28 +23,11 @@ int main(int argc, char *argv[]) {
|
|||||||
int number = line.toInt(&ok);
|
int number = line.toInt(&ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
std::cerr << "Failed to read integer from file content" << std::endl;
|
std::cerr << "Failed to read integer from file content" << std::endl;
|
||||||
returnCode = 1;
|
|
||||||
sem.release();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << number * 2 << std::endl;
|
std::cout << number * 2 << std::endl;
|
||||||
returnCode = 0;
|
|
||||||
sem.release();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QFileDialog::getOpenFileContent("All Files (*.*)", fileContentReady);
|
QFileDialog::getOpenFileContent("All Files (*.*)", fileContentReady);
|
||||||
|
|
||||||
QThread *thread = QThread::create([&sem, &returnCode] () {
|
|
||||||
sem.acquire();
|
|
||||||
if (returnCode == -1) {
|
|
||||||
std::cerr << "Failed to open file dialog" << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnCode;
|
|
||||||
});
|
|
||||||
thread->start();
|
|
||||||
|
|
||||||
// TODO: currently does not work
|
|
||||||
}
|
}
|
1
qtbase
1
qtbase
@ -1 +0,0 @@
|
|||||||
Subproject commit 25986746947798e1a22d0830d3bcb11a55fcd3ae
|
|
57
setup.bat
57
setup.bat
@ -3,62 +3,7 @@
|
|||||||
if not exist "qtbase" git submodule update --init
|
if not exist "qtbase" git submodule update --init
|
||||||
|
|
||||||
cd qtbase
|
cd qtbase
|
||||||
.\configure.bat ^
|
.\configure.bat -static -release -platform win32-msvc -prefix .\build -opensource -confirm-license -nomake tests -nomake examples
|
||||||
-platform win32-msvc ^
|
|
||||||
-prefix .\build ^
|
|
||||||
-opensource ^
|
|
||||||
-static ^
|
|
||||||
-release ^
|
|
||||||
-confirm-license ^
|
|
||||||
-no-openssl ^
|
|
||||||
-no-ssl ^
|
|
||||||
-no-opengl ^
|
|
||||||
-skip qtcharts ^
|
|
||||||
-skip qtwebengine ^
|
|
||||||
-skip qtconnectivity ^
|
|
||||||
-skip qttools ^
|
|
||||||
-skip qtlottie ^
|
|
||||||
-skip qtimageformats ^
|
|
||||||
-skip qtdeclarative ^
|
|
||||||
-skip qtsvg ^
|
|
||||||
-skip qtwayland ^
|
|
||||||
-nomake examples ^
|
|
||||||
-nomake tests ^
|
|
||||||
-optimize-size ^
|
|
||||||
-skip qdoc ^
|
|
||||||
-skip qtactiveqt ^
|
|
||||||
-skip qtcharts ^
|
|
||||||
-skip qtcoap ^
|
|
||||||
-skip qtdatavis3d ^
|
|
||||||
-skip qtfeedback ^
|
|
||||||
-skip qtgamepad ^
|
|
||||||
-skip qtgraphicaleffects ^
|
|
||||||
-skip qtgrpc ^
|
|
||||||
-skip qthttpserver ^
|
|
||||||
-skip qtlocation ^
|
|
||||||
-skip qtlottie ^
|
|
||||||
-skip qtmultimedia ^
|
|
||||||
-skip qtnetworkauth ^
|
|
||||||
-skip qtpim ^
|
|
||||||
-skip qtpositioning ^
|
|
||||||
-skip qtquick3d ^
|
|
||||||
-skip qtremoteobjects ^
|
|
||||||
-skip qtscxml ^
|
|
||||||
-skip qtsensors ^
|
|
||||||
-skip qtserialbus ^
|
|
||||||
-skip qtserialport ^
|
|
||||||
-skip qtspeech ^
|
|
||||||
-skip qtsvg ^
|
|
||||||
-skip qttools ^
|
|
||||||
-skip qttranslations ^
|
|
||||||
-skip qtvirtualkeyboard ^
|
|
||||||
-skip qtwebchannel ^
|
|
||||||
-skip qtwebengine ^
|
|
||||||
-skip qtwebsockets ^
|
|
||||||
-skip qtwebview ^
|
|
||||||
-skip qtx11extras ^
|
|
||||||
-skip qtxmlpatterns
|
|
||||||
#.\configure.bat -release -platform win32-msvc -prefix .\build -opensource -confirm-license -nomake tests -nomake examples
|
|
||||||
|
|
||||||
cmake --build . --parallel
|
cmake --build . --parallel
|
||||||
cmake --install .
|
cmake --install .
|
||||||
|
Loading…
x
Reference in New Issue
Block a user