We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近在研究windows GUI程序的fuzz问题,为了提高一些效率,测试了各种办法,虽然最终没有帮助到我目前需要测试的程序,但是还是把最近折腾的技术记录一下,以后可能还会继续做一些延申的研究,到时可能会持续更新
windows GUI
fuzz
Dynamorio是一整套的动态执行框架,其中包含了很多功能,目前windows下最流行的winafl就是用它做的代码覆盖率监控。最近也研究了不少它的东西,这次是想用它的wrap api对GUI程序的部分函数进行更改,或者替代,以提高fuzz的效率,先来看一下wrap涉及到最主要的两个的API
Dynamorio
windows
winafl
wrap api
GUI
wrap
API
generic_func_t dr_get_proc_address( module_handle_t lib, /* 导出函数的module */ const char *name /* 需要wrap的导出函数 */ )
得到导出函数后,对其进行wrap
DR_EXPORT bool drwrap_wrap( app_pc func, /* dr_get_proc_address 返回值 */ void(*)(void *wrapcxt, OUT void **user_data) pre_func_cb, /* 导出函数前向处理 */ void(*)(void *wrapcxt, void *user_data) post_func_cb /* 导出函数后向处理 */ )
有了这两个函数,比如我们来编写一下,记录程序堆分配过程中用到malloc和free的情况
malloc
free
#include "stdafx.h" #include <fstream> #include "dr_api.h" #include "drmgr.h" #include "drwrap.h" using namespace std; static void event_exit(void); static void wrap_malloc_pre(void *wrapcxt, OUT void **user_data); static void wrap_malloc_post(void *wrapcxt, void *user_data); static void wrap_free_pre(void *wrapcxt, OUT void **user_data); ofstream LogFile; #define MALLOC_ROUTINE_NAME "malloc" #define FREE_ROUTINE_NAME "free" static void module_load_event(void *drcontext, const module_data_t *mod, bool loaded) { app_pc towrap = (app_pc)dr_get_proc_address(mod->handle, MALLOC_ROUTINE_NAME); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_malloc_pre, wrap_malloc_post); if (!ok) { dr_fprintf(STDERR, "[-] Could not wrap 'malloc': already wrapped?\n"); DR_ASSERT(ok); } } towrap = (app_pc)dr_get_proc_address(mod->handle, FREE_ROUTINE_NAME); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_free_pre, NULL); if (!ok) { dr_fprintf(STDERR, "[-] Could not wrap 'free': already wrapped?\n"); DR_ASSERT(ok); } } } DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) { LogFile.open("memprofile.out"); dr_set_client_name("DynamoRIO Sample Client 'wrap'", "http://dynamorio.org/issues"); dr_log(NULL, LOG_ALL, 1, "Client 'wrap' initializing\n"); if (dr_is_notify_on()) { dr_enable_console_printing(); dr_fprintf(STDERR, "[*] Client wrap is running\n"); } drmgr_init(); drwrap_init(); dr_register_exit_event(event_exit); drmgr_register_module_load_event(module_load_event); } static void event_exit(void) { drwrap_exit(); drmgr_exit(); } static void wrap_malloc_pre(void *wrapcxt, OUT void **user_data) { /* malloc(size) or HeapAlloc(heap, flags, size) */ //size_t sz = (size_t)drwrap_get_arg(wrapcxt, 2); // HeapAlloc size_t sz = (size_t)drwrap_get_arg(wrapcxt, 0); // malloc LogFile << "[*] malloc(" << dec << sz << ")"; // log the malloc size } static void wrap_malloc_post(void *wrapcxt, void *user_data) { int actual_read = (int)(ptr_int_t)drwrap_get_retval(wrapcxt); LogFile << "\t\t= 0x" << hex << actual_read << endl; } static void wrap_free_pre(void *wrapcxt, OUT void **user_data) { int addr = (int)drwrap_get_arg(wrapcxt, 0); LogFile << "[*] free(0x" << hex << addr << ")" << endl; }
编译之后测试
D:\tmp\DynamoRIO\bin32\drrun.exe -c .\Debug\WrapMallocFree.dll -- calc.exe
效果
记录了calc进程启动过程中malloc和free的使用。
这种运用在fuzz GUI程序可能会经常用到,比如我们wrap
fuzz GUI
MessageBox 禁止弹出MessageBox ShowWindow 不显示窗口 CreateWindow 在post过程中返回创建失败
为了提高fuzz的效率,我们可能会用到更多的控制窗口的程序,以提高窗口fuzz的效率
SetWindowsHookExA是windows官方提供的可以hook windows消息的API
SetWindowsHookExA
语法
HHOOK SetWindowsHookExA( int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId );
我们可以通过载入特定的dll,在需要hook的位置hook特定的windows消息
hook
// dllmain.cpp : Defines the entry point for the DLL application. #include "pch.h" #include <fstream> #include <iostream> #include <exception> #include <ctime> #define _CRT_SECURE_NO_WARNINGS std::ofstream LogFile; HMODULE hinst; HHOOK hhk = NULL; LRESULT CALLBACK WNDProc(int code, WPARAM wParam, LPARAM lParam) { if (code >= 0) { char time_buffer[4096]; __time64_t long_time; struct tm new_time; _time64(&long_time); localtime_s(&new_time, &long_time); snprintf(time_buffer, 4096, "%02d/%02d/%02d %02d:%02d:%02d", new_time.tm_mon + 1, new_time.tm_mday, new_time.tm_year % 100, new_time.tm_hour, new_time.tm_min, new_time.tm_sec); LogFile << "------" << time_buffer << "------" << std::endl; PCWPSTRUCT wnd_stru = (PCWPSTRUCT)lParam; LogFile << " [-] window: " << wnd_stru->hwnd << std::endl; LogFile << " [-] message: " << wnd_stru->message << std::endl; LogFile << " [-] wParam: " << wnd_stru->wParam << std::endl; LogFile << " [-] lParam: " << wnd_stru->lParam << std::endl; // return CallNextHookEx(hhk, code, wParam, lParam); } return CallNextHookEx(hhk, code, wParam, lParam); } extern "C" __declspec(dllexport) void HookInstall(unsigned long threadID) { hhk = SetWindowsHookEx(WH_CALLWNDPROC, WNDProc, hinst, threadID); LogFile << "install hook done" << std::endl; } extern "C" __declspec(dllexport) void HookUninstall() { UnhookWindowsHookEx(hhk); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { LogFile.open("Hook.out"); hinst = hModule; return TRUE; }
在创建进程时,可以利用widnows detours载入dll
widnows detours
dll
const char* dll_path = "D:\\Dropbox\\code\\xfuzzer\\xdb\\Debug\\MessageHook.dll"; if (!DetourCreateProcessWithDllExA(NULL, cmd, NULL, NULL, inherit_handles, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | CREATE_SUSPENDED, NULL, NULL, &si, &pi, dll_path, NULL)) { FATAL("CreateProcess failed, GLE=%d.\n", GetLastError()); } ResumeThread(pi.hThread);
在进程的入口点,安装钩子
void OnEntrypoint() { HMODULE *module_handles = NULL; DWORD num_modules = GetLoadedModules(&module_handles); for (DWORD i = 0; i < num_modules; i++) { char base_name[MAX_PATH]; GetModuleBaseNameA(child_handle, module_handles[i], (LPSTR)(&base_name), sizeof(base_name)); if (trace_debug_events) printf("Debugger: Loaded module %s at %p\n", base_name, (void *)module_handles[i]); if (strcmp(base_name, "MessageHook.dll") == 0) { HMODULE hHook = LoadLibraryA("D:\\Dropbox\\code\\xfuzzer\\xdb\\Debug\\MessageHook.dll"); Install install = (Install)GetProcAddress(hHook, "HookInstall"); // 安装钩子 if (install == NULL) { FATAL("Get CallWndProc failed!\n"); } install(child_thread_id); printf("install done\n"); } OnModuleLoaded((void *)module_handles[i], base_name); } if (module_handles) free(module_handles); child_entrypoint_reached = true; if (trace_debug_events) printf("Debugger: Process entrypoint reached\n"); }
来看看效果
记录的窗口过程消息
在fuzz GUI程序时,如果我们能够直接block消息的传递,就可以减少很多的麻烦,提升不少的效率。
block
暂时就这么多,里面有很多细节来不及写,有兴趣的可以联系我
Function Wrapping and Replacing Extension
Dynamic Binary Instrumentation Primer
The text was updated successfully, but these errors were encountered:
No branches or pull requests
GUI Fuzz相关研究
最近在研究
windows GUI
程序的fuzz
问题,为了提高一些效率,测试了各种办法,虽然最终没有帮助到我目前需要测试的程序,但是还是把最近折腾的技术记录一下,以后可能还会继续做一些延申的研究,到时可能会持续更新Dynamorio wrap研究
Dynamorio
是一整套的动态执行框架,其中包含了很多功能,目前windows
下最流行的winafl
就是用它做的代码覆盖率监控。最近也研究了不少它的东西,这次是想用它的wrap api
对GUI
程序的部分函数进行更改,或者替代,以提高fuzz
的效率,先来看一下wrap
涉及到最主要的两个的API
得到导出函数后,对其进行
wrap
有了这两个函数,比如我们来编写一下,记录程序堆分配过程中用到
malloc
和free
的情况编译之后测试
效果
记录了calc进程启动过程中
malloc
和free
的使用。这种运用在
fuzz GUI
程序可能会经常用到,比如我们wrap
为了提高
fuzz
的效率,我们可能会用到更多的控制窗口的程序,以提高窗口fuzz
的效率SetWindowsHookExA消息阻断研究
SetWindowsHookExA
是windows官方提供的可以hook windows消息的API语法
我们可以通过载入特定的dll,在需要
hook
的位置hook
特定的windows
消息在创建进程时,可以利用
widnows detours
载入dll
在进程的入口点,安装钩子
来看看效果
记录的窗口过程消息
在
fuzz GUI
程序时,如果我们能够直接block
消息的传递,就可以减少很多的麻烦,提升不少的效率。暂时就这么多,里面有很多细节来不及写,有兴趣的可以联系我
参考
Function Wrapping and Replacing Extension
Dynamic Binary Instrumentation Primer
The text was updated successfully, but these errors were encountered: