diff --git a/.gitignore b/.gitignore index 5bbe957..1d13f7e 100755 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ plugins_install/ peasoup_executable*/ /programs/Makefile* + + +*_plugin_import.cpp \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index cba3133..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "qtbase"] - path = qtbase - url = https://code.qt.io/qt/qtbase.git - branch = v6.9.0 \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d6278f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.associations": { + "cstdlib": "c", + "memory": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "iostream": "cpp" + } +} \ No newline at end of file diff --git a/DOC.md b/DOC.md new file mode 100644 index 0000000..4b0e3f5 --- /dev/null +++ b/DOC.md @@ -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 diff --git a/README.md b/README.md index 0f94e30..4895d5c 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,12 @@ ## DLL methods -- [x] `GetOpenFileNameA` -- [ ] `IFileOpenDialog` +- [x] `GetOpenFileNameA` (ANSI) +- [x] `GetOpenFileNameW` (UTF-16) +- [x] `IFileOpenDialog` - [x] `QFileDialog::getOpenFileName` - [ ] `QFileDialog::getOpenFileNames` -- [ ] `QFileDialog::getOpenFileUrl` +- [x] `QFileDialog::getOpenFileUrl` - [ ] `QFileDialog::getOpenFileUrls` - [ ] `QFileDialog::getOpenFileContent` - [ ] `wxFileDialog` diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ace1cce..5617e55 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -5,12 +5,8 @@ project(CustomClient) find_package(DynamoRIO REQUIRED) add_library(CustomClient SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/client.c") - -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) +target_link_libraries(CustomClient drwrap drmgr) configure_DynamoRIO_client(CustomClient) +use_DynamoRIO_extension(CustomClient drwrap) + diff --git a/client/lib/CC_QTLib.cpp b/client/lib/CC_QTLib.cpp deleted file mode 100644 index 474b783..0000000 --- a/client/lib/CC_QTLib.cpp +++ /dev/null @@ -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); -} diff --git a/client/lib/CC_QTLib.h b/client/lib/CC_QTLib.h deleted file mode 100644 index 0f8f8b1..0000000 --- a/client/lib/CC_QTLib.h +++ /dev/null @@ -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 - -} -*/ diff --git a/client/lib/CC_QTLib.pro b/client/lib/CC_QTLib.pro deleted file mode 100644 index ca59a9c..0000000 --- a/client/lib/CC_QTLib.pro +++ /dev/null @@ -1,5 +0,0 @@ -QT += core widgets -TEMPLATE = lib -TARGET = CC_QTLib -SOURCES += CC_QTLib.cpp -CONFIG += staticlib diff --git a/client/src/client.c b/client/src/client.c index dc33abc..804f9f2 100644 --- a/client/src/client.c +++ b/client/src/client.c @@ -1,153 +1,236 @@ #include "dr_api.h" +#include "dr_tools.h" +#include "drwrap.h" #include "dr_ir_opnd.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 <string.h> #include <windows.h> #include <commdlg.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"; -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; -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; +// --- drwrap Callbacks for IFileOpenDialog (COM) --- -static app_pc pc_QFileDialog_getOpenFileName = NULL; -static app_pc pc_QFileDialog_getOpenFileNames = NULL; -static app_pc pc_QFileDialog_getOpenFileUrl = NULL; -static app_pc pc_QFileDialog_getOpenFileUrls = NULL; -static app_pc pc_QFileDialog_getOpenFileContent = NULL; +struct per_thread_info +{ + // Information needed for COM hooking + IShellItem *sitem_to_wrap; +}; -static void intercept_GetOpenFileNameA() { - void *drcontext = dr_get_current_drcontext(); +static void pre_CoCreateInstance(void *wrapctx, void **user_data); +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 }; - dr_get_mcontext(drcontext, &mcontext); +static HRESULT custom_IFileDialog_Show(void *, void *); +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]; - ofn->lpstrFile[strlen(CUSTOM_FILE)] = 0; +// --- drwrap Callbacks for WinAPI Functions --- - mcontext.rax = 1; - - dr_set_mcontext(drcontext, &mcontext); -} - -static void intercept_QFileDialog_getOpenFileName() { - void *drcontext = dr_get_current_drcontext(); - - 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]); +static void pre_GetOpenFileNameA(void *wrapctx, void **user_data) +{ + OPENFILENAMEA *ofn = (OPENFILENAMEA *)drwrap_get_arg(wrapctx, 0); + if (ofn && ofn->lpstrFile) + { + strncpy(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1); + ofn->lpstrFile[ofn->nMaxFile - 1] = '\0'; } - if (strstr(lowerpath, "qt6core.dll")) { - 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"); - // if (pc_QString_const) dr_printf("Found QString::QString at %p\n", pc_QString_const); - } - if (strstr(lowerpath, "qt6widgets.dll")) { - 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"); - 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"); - 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); + drwrap_skip_call(wrapctx, (void *)1, 0); +} + +static void pre_GetOpenFileNameW(void *wrapctx, void **user_data) +{ + OPENFILENAMEW *ofn = (OPENFILENAMEW *)drwrap_get_arg(wrapctx, 0); + if (ofn && ofn->lpstrFile) + { + mbstowcs(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1); + ofn->lpstrFile[ofn->nMaxFile - 1] = L'\0'; } - if (strstr(lowerpath, "comdlg32.dll")) { - pc_GetOpenFileNameA = (app_pc)dr_get_proc_address(mod->handle, "GetOpenFileNameA"); - // if (pc_GetOpenFileNameA) dr_printf("Found GetOpenFileNameA at %p\n", pc_GetOpenFileNameA); + drwrap_skip_call(wrapctx, (void *)1, 0); +} + +// --- 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) { - instr_t *to_remove = NULL, *instr = instrlist_first(bb); - while (instr) { - instr_t *next = instr_get_next(instr); + HRESULT hr = (HRESULT)drwrap_get_retval(wrapctx); + if (SUCCEEDED(hr)) + { + // 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)) { - 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); - } + fod->lpVtbl = &customFODVtbl; } - - 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[]) { - dr_set_client_name("Custom DynamoRIO client", "https://gitea.cloud.lehnert.dev/ludwig/windows-binary-fuzzing"); - dr_register_exit_event(event_exit); +static HRESULT custom_IFileDialog_Show(void *self, void *b) { + return S_OK; +} + +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_bb_event(event_basic_block); - - // CC_QTLib_load(); -} + dr_register_exit_event(event_exit); +} \ No newline at end of file diff --git a/programs/build.bat b/programs/build.bat index ac1802c..60b4a41 100644 --- a/programs/build.bat +++ b/programs/build.bat @@ -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\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 qmake source\QT_getOpenFileContent.pro diff --git a/programs/compiled/Foo.exe b/programs/compiled/Foo.exe index 84dc300..1533ecd 100644 Binary files a/programs/compiled/Foo.exe and b/programs/compiled/Foo.exe differ diff --git a/programs/compiled/GetOpenFileNameA.exe b/programs/compiled/GetOpenFileNameA.exe index a2eadc4..92624bb 100644 Binary files a/programs/compiled/GetOpenFileNameA.exe and b/programs/compiled/GetOpenFileNameA.exe differ diff --git a/programs/compiled/GetOpenFileNameW.exe b/programs/compiled/GetOpenFileNameW.exe new file mode 100644 index 0000000..b29a566 Binary files /dev/null and b/programs/compiled/GetOpenFileNameW.exe differ diff --git a/programs/compiled/IFileDialog.exe b/programs/compiled/IFileDialog.exe index 62e52c7..9ecf569 100644 Binary files a/programs/compiled/IFileDialog.exe and b/programs/compiled/IFileDialog.exe differ diff --git a/programs/compiled/QT_TestLib.exe b/programs/compiled/QT_TestLib.exe index 49d8c06..11d00b7 100644 Binary files a/programs/compiled/QT_TestLib.exe and b/programs/compiled/QT_TestLib.exe differ diff --git a/programs/compiled/QT_getOpenFileContent.exe b/programs/compiled/QT_getOpenFileContent.exe index 1fda529..3d37422 100644 Binary files a/programs/compiled/QT_getOpenFileContent.exe and b/programs/compiled/QT_getOpenFileContent.exe differ diff --git a/programs/compiled/QT_getOpenFileName.exe b/programs/compiled/QT_getOpenFileName.exe index 870758f..00e2a38 100644 Binary files a/programs/compiled/QT_getOpenFileName.exe and b/programs/compiled/QT_getOpenFileName.exe differ diff --git a/programs/compiled/QT_getOpenFileNames.exe b/programs/compiled/QT_getOpenFileNames.exe index 6e8b15c..69bb7d6 100644 Binary files a/programs/compiled/QT_getOpenFileNames.exe and b/programs/compiled/QT_getOpenFileNames.exe differ diff --git a/programs/compiled/QT_getOpenFileUrl.exe b/programs/compiled/QT_getOpenFileUrl.exe index 8659993..490c8e1 100644 Binary files a/programs/compiled/QT_getOpenFileUrl.exe and b/programs/compiled/QT_getOpenFileUrl.exe differ diff --git a/programs/compiled/QT_getOpenFileUrls.exe b/programs/compiled/QT_getOpenFileUrls.exe index cd46915..7d4ddbe 100644 Binary files a/programs/compiled/QT_getOpenFileUrls.exe and b/programs/compiled/QT_getOpenFileUrls.exe differ diff --git a/programs/source/GetOpenFileNameA.c b/programs/source/GetOpenFileNameA.c index cfb6b1f..28ca4ea 100644 --- a/programs/source/GetOpenFileNameA.c +++ b/programs/source/GetOpenFileNameA.c @@ -15,9 +15,10 @@ int main() { .Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST }; - int res = GetOpenFileName(&ofn); + int res = GetOpenFileNameA(&ofn); + if (!res) { - puts("GetOpenFileName(...) failed!"); + puts("GetOpenFileNameA(...) failed!"); exit(1); } diff --git a/programs/source/GetOpenFileNameW.c b/programs/source/GetOpenFileNameW.c new file mode 100644 index 0000000..082c60c --- /dev/null +++ b/programs/source/GetOpenFileNameW.c @@ -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; +} diff --git a/programs/source/QT_getOpenFileContent.cpp b/programs/source/QT_getOpenFileContent.cpp index ccdb171..4d786ad 100644 --- a/programs/source/QT_getOpenFileContent.cpp +++ b/programs/source/QT_getOpenFileContent.cpp @@ -9,16 +9,9 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - QSemaphore sem(1); - sem.acquire(); - - int returnCode = -1; - - auto fileContentReady = [&returnCode, &sem](const QString &fileName, const QByteArray &fileContent) { + auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) { if (fileName.isEmpty() || !QFile(fileName).exists()) { std::cerr << "Failed to open file" << std::endl; - returnCode = 1; - sem.release(); return; } @@ -30,28 +23,11 @@ int main(int argc, char *argv[]) { int number = line.toInt(&ok); if (!ok) { std::cerr << "Failed to read integer from file content" << std::endl; - returnCode = 1; - sem.release(); return; } std::cout << number * 2 << std::endl; - returnCode = 0; - sem.release(); }; 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 } \ No newline at end of file diff --git a/qtbase b/qtbase deleted file mode 160000 index 2598674..0000000 --- a/qtbase +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 25986746947798e1a22d0830d3bcb11a55fcd3ae diff --git a/setup.bat b/setup.bat index 4f0b687..e1cbc4b 100644 --- a/setup.bat +++ b/setup.bat @@ -3,62 +3,7 @@ if not exist "qtbase" git submodule update --init cd qtbase -.\configure.bat ^ - -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 +.\configure.bat -static -release -platform win32-msvc -prefix .\build -opensource -confirm-license -nomake tests -nomake examples cmake --build . --parallel cmake --install .