diff --git a/x64_dbg_bridge/bridgemain.cpp b/x64_dbg_bridge/bridgemain.cpp index 6af58fcb..3d405a22 100644 --- a/x64_dbg_bridge/bridgemain.cpp +++ b/x64_dbg_bridge/bridgemain.cpp @@ -1120,6 +1120,26 @@ BRIDGE_IMPEXP void GuiShowCpu() _gui_sendmessage(GUI_SHOW_CPU, 0, 0); } +BRIDGE_IMPEXP void GuiAddQWidgetTab(void* qWidget) +{ + _gui_sendmessage(GUI_ADD_QWIDGET_TAB, qWidget, nullptr); +} + +BRIDGE_IMPEXP void GuiShowQWidgetTab(void* qWidget) +{ + _gui_sendmessage(GUI_SHOW_QWIDGET_TAB, qWidget, nullptr); +} + +BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget) +{ + _gui_sendmessage(GUI_CLOSE_QWIDGET_TAB, qWidget, nullptr); +} + +BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread) +{ + _gui_sendmessage(GUI_EXECUTE_ON_GUI_THREAD, cbGuiThread, nullptr); +} + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; diff --git a/x64_dbg_bridge/bridgemain.h b/x64_dbg_bridge/bridgemain.h index dc5a72a2..67ea4784 100644 --- a/x64_dbg_bridge/bridgemain.h +++ b/x64_dbg_bridge/bridgemain.h @@ -761,9 +761,16 @@ typedef enum GUI_LOAD_SOURCE_FILE, // param1=const char* path, param2=line GUI_MENU_SET_ICON, // param1=int hMenu, param2=ICONINFO* GUI_MENU_SET_ENTRY_ICON, // param1=int hEntry, param2=ICONINFO* - GUI_SHOW_CPU // param1=unused, param2=unused + GUI_SHOW_CPU, // param1=unused, param2=unused + GUI_ADD_QWIDGET_TAB, // param1=QWidget*, param2=unused + GUI_SHOW_QWIDGET_TAB, // param1=QWidget*, param2=unused + GUI_CLOSE_QWIDGET_TAB, // param1=QWidget*, param2=unused + GUI_EXECUTE_ON_GUI_THREAD // param1=GUICALLBACK, param2=unused } GUIMSG; +//GUI Typedefs +typedef void (*GUICALLBACK)(); + //GUI structures typedef struct { @@ -848,6 +855,10 @@ BRIDGE_IMPEXP void GuiLoadSourceFile(const char* path, int line); BRIDGE_IMPEXP void GuiMenuSetIcon(int hMenu, const ICONDATA* icon); BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon); BRIDGE_IMPEXP void GuiShowCpu(); +BRIDGE_IMPEXP void GuiAddQWidgetTab(void* qWidget); +BRIDGE_IMPEXP void GuiShowQWidgetTab(void* qWidget); +BRIDGE_IMPEXP void GuiCloseQWidgetTab(void* qWidget); +BRIDGE_IMPEXP void GuiExecuteOnGuiThread(GUICALLBACK cbGuiThread); #ifdef __cplusplus } diff --git a/x64_dbg_bridge/x64_dbg_bridge.vcxproj b/x64_dbg_bridge/x64_dbg_bridge.vcxproj index 6340c198..a1eb095a 100644 --- a/x64_dbg_bridge/x64_dbg_bridge.vcxproj +++ b/x64_dbg_bridge/x64_dbg_bridge.vcxproj @@ -109,7 +109,7 @@ BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreadedDebugDLL Level3 ProgramDatabase MaxSpeed @@ -139,7 +139,7 @@ BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreadedDebugDLL Level3 ProgramDatabase diff --git a/x64_dbg_dbg/_global.h b/x64_dbg_dbg/_global.h index b872a29f..80b2ad44 100644 --- a/x64_dbg_dbg/_global.h +++ b/x64_dbg_dbg/_global.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/x64_dbg_dbg/_scriptapi_assembler.cpp b/x64_dbg_dbg/_scriptapi_assembler.cpp new file mode 100644 index 00000000..3bce70b5 --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_assembler.cpp @@ -0,0 +1,22 @@ +#include "_scriptapi_assembler.h" +#include "assemble.h" + +SCRIPT_EXPORT bool Script::Assembler::Assemble(duint addr, unsigned char* dest, int* size, const char* instruction) +{ + return assemble(addr, dest, size, instruction, nullptr); +} + +SCRIPT_EXPORT bool Script::Assembler::AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error) +{ + return assemble(addr, dest, size, instruction, error); +} + +SCRIPT_EXPORT bool Script::Assembler::AssembleMem(duint addr, const char* instruction) +{ + return assembleat(addr, instruction, nullptr, nullptr, false); +} + +SCRIPT_EXPORT bool Script::Assembler::AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop) +{ + return assembleat(addr, instruction, size, error, fillnop); +} \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_assembler.h b/x64_dbg_dbg/_scriptapi_assembler.h new file mode 100644 index 00000000..f731724e --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_assembler.h @@ -0,0 +1,17 @@ +#ifndef _SCRIPTAPI_ASSEMBLER_H +#define _SCRIPTAPI_ASSEMBLER_H + +#include "_scriptapi.h" + +namespace Script +{ +namespace Assembler +{ +SCRIPT_EXPORT bool Assemble(duint addr, unsigned char* dest, int* size, const char* instruction); //dest[16] +SCRIPT_EXPORT bool AssembleEx(duint addr, unsigned char* dest, int* size, const char* instruction, char* error); //dest[16], error[MAX_ERROR_SIZE] +SCRIPT_EXPORT bool AssembleMem(duint addr, const char* instruction); +SCRIPT_EXPORT bool AssembleMemEx(duint addr, const char* instruction, int* size, char* error, bool fillnop); //error[MAX_ERROR_SIZE] +}; //Assembler +}; //Script + +#endif //_SCRIPTAPI_ASSEMBLER_H \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_gui.cpp b/x64_dbg_dbg/_scriptapi_gui.cpp index 480b3259..018b9267 100644 --- a/x64_dbg_dbg/_scriptapi_gui.cpp +++ b/x64_dbg_dbg/_scriptapi_gui.cpp @@ -1,51 +1,5 @@ #include "_scriptapi_gui.h" - -static inline int windowToBridge(Script::Gui::Window window) -{ - switch(window) - { - case Script::Gui::DisassemblyWindow: - return GUI_DISASSEMBLY; - case Script::Gui::DumpWindow: - return GUI_DUMP; - case Script::Gui::StackWindow: - return GUI_STACK; - default: - return GUI_DISASSEMBLY; - } -} - -SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end) -{ - SELECTIONDATA selection; - if(!GuiSelectionGet(windowToBridge(window), &selection)) - return false; - if(start) - *start = selection.start; - if(end) - *end = selection.end; - return true; -} - -SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end) -{ - SELECTIONDATA selection; - selection.start = start; - selection.end = end; - return GuiSelectionSet(windowToBridge(window), &selection); -} - -SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window) -{ - duint start; - return Gui::SelectionGet(window, &start, nullptr) ? start : 0; -} - -SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window) -{ - duint end; - return Gui::SelectionGet(window, nullptr, &end) ? end : 0; -} +#include "_scriptapi_misc.h" SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end) { @@ -105,4 +59,94 @@ SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetStart() SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd() { return Gui::SelectionGetEnd(StackWindow); +} + +static inline int windowToBridge(Script::Gui::Window window) +{ + switch(window) + { + case Script::Gui::DisassemblyWindow: + return GUI_DISASSEMBLY; + case Script::Gui::DumpWindow: + return GUI_DUMP; + case Script::Gui::StackWindow: + return GUI_STACK; + default: + return GUI_DISASSEMBLY; + } +} + +SCRIPT_EXPORT bool Script::Gui::SelectionGet(Script::Gui::Window window, duint* start, duint* end) +{ + SELECTIONDATA selection; + if(!GuiSelectionGet(windowToBridge(window), &selection)) + return false; + if(start) + *start = selection.start; + if(end) + *end = selection.end; + return true; +} + +SCRIPT_EXPORT bool Script::Gui::SelectionSet(Script::Gui::Window window, duint start, duint end) +{ + SELECTIONDATA selection; + selection.start = start; + selection.end = end; + return GuiSelectionSet(windowToBridge(window), &selection); +} + +SCRIPT_EXPORT duint Script::Gui::SelectionGetStart(Script::Gui::Window window) +{ + duint start; + return Gui::SelectionGet(window, &start, nullptr) ? start : 0; +} + +SCRIPT_EXPORT duint Script::Gui::SelectionGetEnd(Script::Gui::Window window) +{ + duint end; + return Gui::SelectionGet(window, nullptr, &end) ? end : 0; +} + +SCRIPT_EXPORT void Script::Gui::Message(const char* message) +{ + GuiScriptMessage(message); +} + +SCRIPT_EXPORT bool Script::Gui::MessageYesNo(const char* message) +{ + return !!GuiScriptMsgyn(message); +} + +SCRIPT_EXPORT bool Script::Gui::InputLine(const char* title, char* text) +{ + return GuiGetLineWindow(title, text); +} + +SCRIPT_EXPORT bool Script::Gui::InputValue(const char* title, duint* value) +{ + Memory line(GUI_MAX_LINE_SIZE); + if(!GuiGetLineWindow(title, line())) + return false; + return Misc::ParseExpression(line(), value); +} + +SCRIPT_EXPORT void Script::Gui::Refresh() +{ + GuiUpdateAllViews(); +} + +SCRIPT_EXPORT void Script::Gui::AddQWidgetTab(void* qWidget) +{ + GuiAddQWidgetTab(qWidget); +} + +SCRIPT_EXPORT void Script::Gui::ShowQWidgetTab(void* qWidget) +{ + GuiShowQWidgetTab(qWidget); +} + +SCRIPT_EXPORT void Script::Gui::CloseQWidgetTab(void* qWidget) +{ + GuiCloseQWidgetTab(qWidget); } \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_gui.h b/x64_dbg_dbg/_scriptapi_gui.h index 0e78cfb5..1b353ec4 100644 --- a/x64_dbg_dbg/_scriptapi_gui.h +++ b/x64_dbg_dbg/_scriptapi_gui.h @@ -7,18 +7,6 @@ namespace Script { namespace Gui { -enum Window -{ - DisassemblyWindow, - DumpWindow, - StackWindow -}; - -SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end); -SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end); -SCRIPT_EXPORT duint SelectionGetStart(Window window); -SCRIPT_EXPORT duint SelectionGetEnd(Window window); - namespace Disassembly { SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end); @@ -42,6 +30,30 @@ SCRIPT_EXPORT bool SelectionSet(duint start, duint end); SCRIPT_EXPORT duint SelectionGetStart(); SCRIPT_EXPORT duint SelectionGetEnd(); }; //Stack +}; //Gui + +namespace Gui +{ +enum Window +{ + DisassemblyWindow, + DumpWindow, + StackWindow +}; + +SCRIPT_EXPORT bool SelectionGet(Window window, duint* start, duint* end); +SCRIPT_EXPORT bool SelectionSet(Window window, duint start, duint end); +SCRIPT_EXPORT duint SelectionGetStart(Window window); +SCRIPT_EXPORT duint SelectionGetEnd(Window window); +SCRIPT_EXPORT void Message(const char* message); +SCRIPT_EXPORT bool MessageYesNo(const char* message); +SCRIPT_EXPORT bool InputLine(const char* title, char* text); //text[GUI_MAX_LINE_SIZE] +SCRIPT_EXPORT bool InputValue(const char* title, duint* value); +SCRIPT_EXPORT void Refresh(); +SCRIPT_EXPORT void AddQWidgetTab(void* qWidget); +SCRIPT_EXPORT void ShowQWidgetTab(void* qWidget); +SCRIPT_EXPORT void CloseQWidgetTab(void* qWidget); + }; //Gui }; //Script diff --git a/x64_dbg_dbg/_scriptapi_memory.cpp b/x64_dbg_dbg/_scriptapi_memory.cpp index 93e3e461..dbc1e735 100644 --- a/x64_dbg_dbg/_scriptapi_memory.cpp +++ b/x64_dbg_dbg/_scriptapi_memory.cpp @@ -11,6 +11,21 @@ SCRIPT_EXPORT bool Script::Memory::Write(duint addr, const void* data, duint siz return MemWrite((void*)addr, (void*)data, size, sizeWritten); } +SCRIPT_EXPORT bool Script::Memory::IsValidPtr(duint addr) +{ + return MemIsValidReadPtr(addr); +} + +SCRIPT_EXPORT duint Script::Memory::RemoteAlloc(duint addr, duint size) +{ + return (duint)MemAllocRemote(addr, size, PAGE_EXECUTE_READWRITE); +} + +SCRIPT_EXPORT bool Script::Memory::RemoteFree(duint addr) +{ + return MemFreeRemote(addr); +} + SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr) { unsigned char data; diff --git a/x64_dbg_dbg/_scriptapi_memory.h b/x64_dbg_dbg/_scriptapi_memory.h index ab512ecc..5e1a5ea7 100644 --- a/x64_dbg_dbg/_scriptapi_memory.h +++ b/x64_dbg_dbg/_scriptapi_memory.h @@ -9,6 +9,9 @@ namespace Memory { SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead); SCRIPT_EXPORT bool Write(duint addr, const void* data, duint size, duint* sizeWritten); +SCRIPT_EXPORT bool IsValidPtr(duint addr); +SCRIPT_EXPORT duint RemoteAlloc(duint addr, duint size); +SCRIPT_EXPORT bool RemoteFree(duint addr); SCRIPT_EXPORT unsigned char ReadByte(duint addr); SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data); diff --git a/x64_dbg_dbg/_scriptapi_misc.cpp b/x64_dbg_dbg/_scriptapi_misc.cpp new file mode 100644 index 00000000..c0e10891 --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_misc.cpp @@ -0,0 +1,33 @@ +#include "_scriptapi_misc.h" +#include "value.h" + +SCRIPT_EXPORT bool Script::Misc::ParseExpression(const char* expression, duint* value) +{ + return valfromstring(expression, value); +} + +SCRIPT_EXPORT duint Script::Misc::RemoteGetProcAddress(const char* module, const char* api) +{ + duint value; + if(!ParseExpression(StringUtils::sprintf("%s:%s", module, api).c_str(), &value)) + return 0; + return value; +} + +SCRIPT_EXPORT duint Script::Misc::ResolveLabel(const char* label) +{ + duint value; + if(!ParseExpression(label, &value)) + return 0; + return value; +} + +SCRIPT_EXPORT void* Script::Misc::Alloc(duint size) +{ + return emalloc(size, "Script::Misc::Alloc"); +} + +SCRIPT_EXPORT void Script::Misc::Free(void* ptr) +{ + return efree(ptr, "Script::Misc::Free"); +} \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_misc.h b/x64_dbg_dbg/_scriptapi_misc.h new file mode 100644 index 00000000..d57911b9 --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_misc.h @@ -0,0 +1,18 @@ +#ifndef _SCRIPTAPI_MISC_H +#define _SCRIPTAPI_MISC_H + +#include "_scriptapi.h" + +namespace Script +{ +namespace Misc +{ +SCRIPT_EXPORT bool ParseExpression(const char* expression, duint* value); +SCRIPT_EXPORT duint RemoteGetProcAddress(const char* module, const char* api); +SCRIPT_EXPORT duint ResolveLabel(const char* label); +SCRIPT_EXPORT void* Alloc(duint size); +SCRIPT_EXPORT void Free(void* ptr); +}; //Misc +}; //Script + +#endif //_SCRIPTAPI_MISC_H \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_register.cpp b/x64_dbg_dbg/_scriptapi_register.cpp index 2abfab96..a005619b 100644 --- a/x64_dbg_dbg/_scriptapi_register.cpp +++ b/x64_dbg_dbg/_scriptapi_register.cpp @@ -9,6 +9,7 @@ static const char* regTable[] = "DR3", "DR6", "DR7", + "EAX", "AX", "AH", @@ -34,7 +35,7 @@ static const char* regTable[] = "ESP", "SP", "EIP", - "CIP", + #ifdef _WIN64 "RAX", "RBX", @@ -80,7 +81,15 @@ static const char* regTable[] = "R15", "R15D", "R15W", - "R15" + "R15", +#endif //_WIN64 + +#ifdef _WIN64 + "RIP", + "RSP" +#else //x32 + "EIP", + "ESP" #endif //_WIN64 }; @@ -96,6 +105,11 @@ SCRIPT_EXPORT bool Script::Register::Set(Script::Register::RegisterEnum reg, dui return setregister(regTable[reg], value); } +SCRIPT_EXPORT int Script::Register::Size() +{ + return (int)sizeof(duint); +} + SCRIPT_EXPORT duint Script::Register::GetDR0() { return Get(DR0); @@ -406,16 +420,6 @@ SCRIPT_EXPORT bool Script::Register::SetEIP(unsigned int value) return Set(EIP, value); } -SCRIPT_EXPORT duint Script::Register::GetCIP() -{ - return Get(CIP); -} - -SCRIPT_EXPORT bool Script::Register::SetCIP(duint value) -{ - return Set(CIP, value); -} - #ifdef _WIN64 SCRIPT_EXPORT unsigned long long Script::Register::GetRAX() { @@ -866,4 +870,24 @@ SCRIPT_EXPORT bool Script::Register::SetR15B(unsigned char value) { return Set(R15B, value); } -#endif //_WIN64 \ No newline at end of file +#endif //_WIN64 + +SCRIPT_EXPORT duint Script::Register::GetCIP() +{ + return Get(CIP); +} + +SCRIPT_EXPORT bool Script::Register::SetCIP(duint value) +{ + return Set(CIP, value); +} + +SCRIPT_EXPORT duint Script::Register::GetCSP() +{ + return Get(CSP); +} + +SCRIPT_EXPORT bool Script::Register::SetCSP(duint value) +{ + return Set(CSP, value); +} \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_register.h b/x64_dbg_dbg/_scriptapi_register.h index 1838ba75..657b24b0 100644 --- a/x64_dbg_dbg/_scriptapi_register.h +++ b/x64_dbg_dbg/_scriptapi_register.h @@ -15,6 +15,7 @@ enum RegisterEnum DR3, DR6, DR7, + EAX, AX, AH, @@ -40,7 +41,7 @@ enum RegisterEnum ESP, SP, EIP, - CIP, + #ifdef _WIN64 RAX, RBX, @@ -86,12 +87,16 @@ enum RegisterEnum R15, R15D, R15W, - R15B + R15B, #endif //_WIN64 + + CIP, + CSP, }; //RegisterEnum SCRIPT_EXPORT duint Get(RegisterEnum reg); SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value); +SCRIPT_EXPORT int Size(); //gets architecture register size in bytes SCRIPT_EXPORT duint GetDR0(); SCRIPT_EXPORT bool SetDR0(duint value); @@ -105,6 +110,7 @@ SCRIPT_EXPORT duint GetDR6(); SCRIPT_EXPORT bool SetDR6(duint value); SCRIPT_EXPORT duint GetDR7(); SCRIPT_EXPORT bool SetDR7(duint value); + SCRIPT_EXPORT unsigned int GetEAX(); SCRIPT_EXPORT bool SetEAX(unsigned int value); SCRIPT_EXPORT unsigned short GetAX(); @@ -155,8 +161,7 @@ SCRIPT_EXPORT unsigned short GetSP(); SCRIPT_EXPORT bool SetSP(unsigned short value); SCRIPT_EXPORT unsigned int GetEIP(); SCRIPT_EXPORT bool SetEIP(unsigned int value); -SCRIPT_EXPORT duint GetCIP(); -SCRIPT_EXPORT bool SetCIP(duint value); + #ifdef _WIN64 SCRIPT_EXPORT unsigned long long GetRAX(); SCRIPT_EXPORT bool SetRAX(unsigned long long value); @@ -249,6 +254,11 @@ SCRIPT_EXPORT bool SetR15W(unsigned short value); SCRIPT_EXPORT unsigned char GetR15B(); SCRIPT_EXPORT bool SetR15B(unsigned char value); #endif //_WIN64 + +SCRIPT_EXPORT duint GetCIP(); +SCRIPT_EXPORT bool SetCIP(duint value); +SCRIPT_EXPORT duint GetCSP(); +SCRIPT_EXPORT bool SetCSP(duint value); }; //Register }; //Script diff --git a/x64_dbg_dbg/_scriptapi_stack.cpp b/x64_dbg_dbg/_scriptapi_stack.cpp new file mode 100644 index 00000000..528d8137 --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_stack.cpp @@ -0,0 +1,24 @@ +#include "_scriptapi_stack.h" +#include "_scriptapi_memory.h" +#include "_scriptapi_register.h" + +SCRIPT_EXPORT duint Script::Stack::Pop() +{ + duint csp = Register::GetCSP(); + duint top = Memory::ReadPtr(csp); + Register::SetCSP(csp + sizeof(duint)); + return top; +} + +SCRIPT_EXPORT duint Script::Stack::Push(duint value) +{ + duint csp = Register::GetCSP(); + Register::SetCSP(csp - sizeof(duint)); + Memory::WritePtr(csp, value); + return Memory::ReadPtr(csp); +} + +SCRIPT_EXPORT duint Script::Stack::Peek(int offset) +{ + return Memory::ReadPtr(Register::GetCSP() + offset * sizeof(duint)); +} \ No newline at end of file diff --git a/x64_dbg_dbg/_scriptapi_stack.h b/x64_dbg_dbg/_scriptapi_stack.h new file mode 100644 index 00000000..47d714de --- /dev/null +++ b/x64_dbg_dbg/_scriptapi_stack.h @@ -0,0 +1,16 @@ +#ifndef _SCRIPTAPI_STACK_H +#define _SCRIPTAPI_STACK_H + +#include "_scriptapi.h" + +namespace Script +{ +namespace Stack +{ +SCRIPT_EXPORT duint Pop(); +SCRIPT_EXPORT duint Push(duint value); //returns the previous top, equal to Peek(1) +SCRIPT_EXPORT duint Peek(int offset = 0); //offset is in multiples of Register::Size(), for easy x32/x64 portability +}; //Stack +}; //Script + +#endif //_SCRIPTAPI_STACK_H \ No newline at end of file diff --git a/x64_dbg_dbg/analysis.cpp b/x64_dbg_dbg/analysis.cpp new file mode 100644 index 00000000..c3a3c8de --- /dev/null +++ b/x64_dbg_dbg/analysis.cpp @@ -0,0 +1,25 @@ +#include "analysis.h" +#include "memory.h" + +Analysis::Analysis(uint base, uint size) +{ + _base = base; + _size = size; + _data = new unsigned char[_size + MAX_DISASM_BUFFER]; + MemRead((void*)_base, _data, _size, 0); +} + +Analysis::~Analysis() +{ + delete[] _data; +} + +bool Analysis::IsValidAddress(uint addr) +{ + return addr >= _base && addr < _base + _size; +} + +const unsigned char* Analysis::TranslateAddress(uint addr) +{ + return IsValidAddress(addr) ? _data + (addr - _base) : nullptr; +} \ No newline at end of file diff --git a/x64_dbg_dbg/analysis.h b/x64_dbg_dbg/analysis.h new file mode 100644 index 00000000..4f3a9169 --- /dev/null +++ b/x64_dbg_dbg/analysis.h @@ -0,0 +1,26 @@ +#ifndef _ANALYSIS_H +#define _ANALYSIS_H + +#include "_global.h" +#include "capstone_wrapper.h" + +class Analysis +{ +public: + explicit Analysis(uint base, uint size); + Analysis(const Analysis & that) = delete; + ~Analysis(); + virtual void Analyse() = 0; + virtual void SetMarkers() = 0; + +protected: + uint _base; + uint _size; + unsigned char* _data; + Capstone _cp; + + bool IsValidAddress(uint addr); + const unsigned char* TranslateAddress(uint addr); +}; + +#endif //_ANALYSIS_H \ No newline at end of file diff --git a/x64_dbg_dbg/capstone_wrapper.cpp b/x64_dbg_dbg/capstone_wrapper.cpp index d8136662..ef2770b1 100644 --- a/x64_dbg_dbg/capstone_wrapper.cpp +++ b/x64_dbg_dbg/capstone_wrapper.cpp @@ -86,7 +86,7 @@ String Capstone::OperandText(int opindex) case X86_OP_IMM: { - if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL)) + if(InGroup(CS_GRP_JUMP) || InGroup(CS_GRP_CALL) || IsLoop()) sprintf_s(temp, "%"fext"X", op.imm + mInstr->size); else sprintf_s(temp, "%"fext"X", op.imm); @@ -163,8 +163,27 @@ const cs_x86 & Capstone::x86() bool Capstone::IsFilling() { - uint8_t opcode = x86().opcode[0]; - return opcode == 0x90 || opcode == 0xCC; + switch(GetId()) + { + case X86_INS_NOP: + case X86_INS_INT3: + return true; + default: + return false; + } +} + +bool Capstone::IsLoop() +{ + switch(GetId()) + { + case X86_INS_LOOP: + case X86_INS_LOOPE: + case X86_INS_LOOPNE: + return true; + default: + return false; + } } x86_insn Capstone::GetId() diff --git a/x64_dbg_dbg/capstone_wrapper.h b/x64_dbg_dbg/capstone_wrapper.h index 00fcfbf7..5e1cb9a3 100644 --- a/x64_dbg_dbg/capstone_wrapper.h +++ b/x64_dbg_dbg/capstone_wrapper.h @@ -24,6 +24,7 @@ public: const uint Address(); const cs_x86 & x86(); bool IsFilling(); + bool IsLoop(); x86_insn GetId(); String InstructionText(); diff --git a/x64_dbg_dbg/controlflowanalysis.cpp b/x64_dbg_dbg/controlflowanalysis.cpp new file mode 100644 index 00000000..0e51fc88 --- /dev/null +++ b/x64_dbg_dbg/controlflowanalysis.cpp @@ -0,0 +1,168 @@ +#include "controlflowanalysis.h" +#include "memory.h" +#include "console.h" + +ControlFlowAnalysis::ControlFlowAnalysis(uint base, uint size) : Analysis(base, size) +{ +} + +void ControlFlowAnalysis::Analyse() +{ + dputs("Starting analysis..."); + DWORD ticks = GetTickCount(); + + BasicBlockStarts(); + BasicBlocks(); + + dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks); +} + +void ControlFlowAnalysis::SetMarkers() +{ + dprintf("digraph ControlFlow {\n"); + int i = 0; + std::map nodeMap; + for(auto block : _blocks) + { + nodeMap.insert({ block.start, i }); + dprintf(" node%u [label=\"start=%p, end=%p\"];\n", i, block.start, block.end); + i++; + } + for(auto block : _blocks) + { + int startNode = nodeMap[block.start]; + if(block.left) + { + if(nodeMap.count(block.left)) + dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.left]); + } + else + { + dprintf(" node%u [shape=point];\n", i); + dprintf(" node%u -> node%u;\n", startNode, i); + i++; + } + if(block.right) + { + if(nodeMap.count(block.right)) + dprintf(" node%u -> node%u;\n", startNode, nodeMap[block.right]); + } + else + { + dprintf(" node%u [shape=point];\n", i); + dprintf(" node%u -> node%u;\n", startNode, i); + i++; + } + } + dprintf("}\n"); +} + +void ControlFlowAnalysis::BasicBlockStarts() +{ + _blockStarts.insert(_base); + bool bSkipFilling = false; + for(uint i = 0; i < _size;) + { + uint addr = _base + i; + if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER)) + { + if(bSkipFilling) //handle filling skip mode + { + if(!_cp.IsFilling()) //do nothing until the filling stopped + { + bSkipFilling = false; + _blockStarts.insert(addr); + } + } + else if(_cp.InGroup(CS_GRP_RET) || _cp.InGroup(CS_GRP_INT)) //RET/INT break control flow + { + bSkipFilling = true; //skip INT3/NOP/whatever filling bytes (those are not part of the control flow) + } + else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //branches + { + uint dest1 = GetBranchOperand(); + uint dest2 = 0; + if(_cp.GetId() != X86_INS_JMP) //unconditional jump + dest2 = addr + _cp.Size(); + + if(!dest1 && !dest2) //TODO: better code for this (make sure absolutely no filling is inserted) + bSkipFilling = true; + if(dest1) + _blockStarts.insert(dest1); + if(dest2) + _blockStarts.insert(dest2); + } + else if(_cp.InGroup(CS_GRP_CALL)) + { + uint dest1 = GetBranchOperand(); + if(dest1) + _blockStarts.insert(dest1); + } + else + { + uint dest1 = GetBranchOperand(); + if(dest1) + _blockStarts.insert(dest1); + } + i += _cp.Size(); + } + else + i++; + } +} + +void ControlFlowAnalysis::BasicBlocks() +{ + for(auto i = _blockStarts.begin(); i != _blockStarts.end(); i++) + { + uint start = *i; + if(!IsValidAddress(start)) + continue; + uint nextStart = _base + _size; + auto next = std::next(i); + if(next != _blockStarts.end()) + nextStart = *next; + for(uint addr = start, prevaddr = 0; addr < _base + _size;) + { + prevaddr = addr; + if(_cp.Disassemble(addr, TranslateAddress(addr), MAX_DISASM_BUFFER)) + { + if(_cp.InGroup(CS_GRP_RET)) + { + _blocks.push_back(BasicBlock(start, addr, 0, 0)); //leaf block + break; + } + else if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) + { + uint dest1 = GetBranchOperand(); + uint dest2 = _cp.GetId() != X86_INS_JMP ? addr + _cp.Size() : 0; + _blocks.push_back(BasicBlock(start, addr, dest1, dest2)); + break; + } + addr += _cp.Size(); + } + else + addr++; + if(addr == nextStart) //special case handling overlapping blocks + { + _blocks.push_back(BasicBlock(start, prevaddr, 0, nextStart)); + break; + } + } + } +} + +uint ControlFlowAnalysis::GetBranchOperand() +{ + for(int i = 0; i < _cp.x86().op_count; i++) + { + const cs_x86_op & operand = _cp.x86().operands[i]; + if(operand.type == X86_OP_IMM) + { + uint dest = (uint)operand.imm; + if(dest >= _base && dest < _base + _size) + return dest; + } + } + return 0; +} \ No newline at end of file diff --git a/x64_dbg_dbg/controlflowanalysis.h b/x64_dbg_dbg/controlflowanalysis.h new file mode 100644 index 00000000..5d4545d8 --- /dev/null +++ b/x64_dbg_dbg/controlflowanalysis.h @@ -0,0 +1,48 @@ +#ifndef _CONTROLFLOWANALYSIS_H +#define _CONTROLFLOWANALYSIS_H + +#include "_global.h" +#include "capstone_wrapper.h" +#include "analysis.h" + +class ControlFlowAnalysis : public Analysis +{ +public: + explicit ControlFlowAnalysis(uint base, uint size); + void Analyse(); + void SetMarkers(); + +private: + struct BasicBlock + { + uint start; + uint end; + uint left; + uint right; + + BasicBlock() + { + this->start = 0; + this->end = 0; + this->left = 0; + this->right = 0; + } + + BasicBlock(uint start, uint end, uint left, uint right) + { + this->start = start; + this->end = end; + this->left = min(left, right); + this->right = max(left, right); + } + }; + + std::set _blockStarts; + std::vector _blocks; + + void BasicBlockStarts(); + void BasicBlocks(); + uint GetBranchOperand(); +}; + +#endif //_CONTROLFLOWANALYSIS_H \ No newline at end of file diff --git a/x64_dbg_dbg/debugger.cpp b/x64_dbg_dbg/debugger.cpp index ee57cdfd..029cd2ca 100644 --- a/x64_dbg_dbg/debugger.cpp +++ b/x64_dbg_dbg/debugger.cpp @@ -776,14 +776,16 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread) static void cbSystemBreakpoint(void* ExceptionData) { hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId); + + uint cip = GetContextDataEx(hActiveThread, UE_CIP); + GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere + //log message if(bIsAttached) dputs("Attach breakpoint reached!"); else dputs("System breakpoint reached!"); bSkipExceptions = false; //we are not skipping first-chance exceptions - uint cip = GetContextDataEx(hActiveThread, UE_CIP); - GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere //plugin callbacks PLUG_CB_SYSTEMBREAKPOINT callbackInfo; diff --git a/x64_dbg_dbg/disasm_fast.cpp b/x64_dbg_dbg/disasm_fast.cpp index b60f999b..e665243a 100644 --- a/x64_dbg_dbg/disasm_fast.cpp +++ b/x64_dbg_dbg/disasm_fast.cpp @@ -38,7 +38,7 @@ void fillbasicinfo(Capstone* cp, BASIC_INSTRUCTION_INFO* basicinfo) basicinfo->branch = true; basicinfo->call = true; } - else if(cp->InGroup(CS_GRP_JUMP)) + else if(cp->InGroup(CS_GRP_JUMP) || cp->IsLoop()) { basicinfo->branch = true; } diff --git a/x64_dbg_dbg/disasm_helper.cpp b/x64_dbg_dbg/disasm_helper.cpp index 1e37b6fd..3af16346 100644 --- a/x64_dbg_dbg/disasm_helper.cpp +++ b/x64_dbg_dbg/disasm_helper.cpp @@ -204,7 +204,7 @@ void disasmget(unsigned char* buffer, uint addr, DISASM_INSTR* instr) sprintf_s(instr->instruction, "%s %s", cp.GetInstr()->mnemonic, cp.GetInstr()->op_str); const cs_x86 & x86 = cp.GetInstr()->detail->x86; instr->instr_size = cp.GetInstr()->size; - if(cp.InGroup(CS_GRP_JUMP) || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL)) + if(cp.InGroup(CS_GRP_JUMP) || cp.IsLoop() || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL)) instr->type = instr_branch; else if(strstr(cp.GetInstr()->op_str, "sp") || strstr(cp.GetInstr()->op_str, "bp")) instr->type = instr_stack; diff --git a/x64_dbg_dbg/functionanalysis.cpp b/x64_dbg_dbg/functionanalysis.cpp index bf205be0..d3c0ec1b 100644 --- a/x64_dbg_dbg/functionanalysis.cpp +++ b/x64_dbg_dbg/functionanalysis.cpp @@ -3,31 +3,20 @@ #include "memory.h" #include "function.h" -#include "module.h" -#include "LinearPass.h" - -FunctionAnalysis::FunctionAnalysis(uint base, uint size) +FunctionAnalysis::FunctionAnalysis(uint base, uint size) : Analysis(base, size) { - _base = base; - _size = size; - _data = new unsigned char[_size + MAX_DISASM_BUFFER]; - MemRead((void*)_base, _data, _size, 0); } -FunctionAnalysis::~FunctionAnalysis() -{ - delete[] _data; -} - -const unsigned char* FunctionAnalysis::TranslateAddress(uint addr) -{ - return (addr >= _base && addr < _base + _size) ? _data + (addr - _base) : nullptr; -} - -void Derp(uint _base); void FunctionAnalysis::Analyse() { - Derp(_base); + dputs("Starting analysis..."); + DWORD ticks = GetTickCount(); + + PopulateReferences(); + dprintf("%u called functions populated\n", _functions.size()); + AnalyseFunctions(); + + dprintf("Analysis finished in %ums!\n", GetTickCount() - ticks); } void FunctionAnalysis::SetMarkers() @@ -109,7 +98,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr) break; const cs_x86_op & operand = _cp.x86().operands[0]; - if(_cp.InGroup(CS_GRP_JUMP) && operand.type == X86_OP_IMM) //jump + if((_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) && operand.type == X86_OP_IMM) //jump { uint dest = (uint)operand.imm; @@ -121,7 +110,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr) { fardest = dest; } - else if(end && dest < end && _cp.GetId() == X86_INS_JMP) //save the last JMP backwards + else if(end && dest < end && (_cp.GetId() == X86_INS_JMP || _cp.GetId() == X86_INS_LOOP)) //save the last JMP backwards { jumpback = addr; } @@ -146,7 +135,7 @@ uint FunctionAnalysis::GetReferenceOperand() for(int i = 0; i < _cp.x86().op_count; i++) { const cs_x86_op & operand = _cp.x86().operands[i]; - if(_cp.InGroup(CS_GRP_JUMP)) //skip jumps + if(_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) //skip jumps/loops continue; if(operand.type == X86_OP_IMM) //we are looking for immediate references { diff --git a/x64_dbg_dbg/functionanalysis.h b/x64_dbg_dbg/functionanalysis.h index 5fa7354b..96a22460 100644 --- a/x64_dbg_dbg/functionanalysis.h +++ b/x64_dbg_dbg/functionanalysis.h @@ -3,17 +3,16 @@ #include "_global.h" #include "capstone_wrapper.h" +#include "analysis.h" -class FunctionAnalysis +class FunctionAnalysis : public Analysis { public: explicit FunctionAnalysis(uint base, uint size); - FunctionAnalysis(const FunctionAnalysis & that) = delete; - ~FunctionAnalysis(); - const unsigned char* TranslateAddress(uint addr); void Analyse(); void SetMarkers(); +private: struct FunctionInfo { uint start; @@ -30,12 +29,7 @@ public: } }; -private: - uint _base; - uint _size; - unsigned char* _data; std::vector _functions; - Capstone _cp; void SortCleanup(); void PopulateReferences(); diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index b1a48055..21be2c64 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -26,6 +26,8 @@ #include "module.h" #include "stringformat.h" #include "filereader.h" +#include "functionanalysis.h" +#include "controlflowanalysis.h" static bool bRefinit = false; @@ -1877,8 +1879,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[]) return STATUS_CONTINUE; } -#include "functionanalysis.h" - CMDRESULT cbInstrAnalyse(int argc, char* argv[]) { SELECTIONDATA sel; @@ -1892,6 +1892,19 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[]) return STATUS_CONTINUE; } +CMDRESULT cbInstrCfanalyse(int argc, char* argv[]) +{ + SELECTIONDATA sel; + GuiSelectionGet(GUI_DISASSEMBLY, &sel); + uint size = 0; + uint base = MemFindBaseAddr(sel.start, &size); + ControlFlowAnalysis anal(base, size); + anal.Analyse(); + anal.SetMarkers(); + GuiUpdateAllViews(); + return STATUS_CONTINUE; +} + CMDRESULT cbInstrVisualize(int argc, char* argv[]) { if(argc < 3) @@ -1950,7 +1963,7 @@ CMDRESULT cbInstrVisualize(int argc, char* argv[]) break; const cs_x86_op & operand = _cp.x86().operands[0]; - if(_cp.InGroup(CS_GRP_JUMP) && operand.type == X86_OP_IMM) //jump + if((_cp.InGroup(CS_GRP_JUMP) || _cp.IsLoop()) && operand.type == X86_OP_IMM) //jump { uint dest = (uint)operand.imm; diff --git a/x64_dbg_dbg/instruction.h b/x64_dbg_dbg/instruction.h index ca0ea4bf..8cafb549 100644 --- a/x64_dbg_dbg/instruction.h +++ b/x64_dbg_dbg/instruction.h @@ -70,5 +70,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[]); CMDRESULT cbInstrAnalyse(int argc, char* argv[]); CMDRESULT cbInstrVisualize(int argc, char* argv[]); CMDRESULT cbInstrMeminfo(int argc, char* argv[]); +CMDRESULT cbInstrCfanalyse(int argc, char* argv[]); #endif // _INSTRUCTIONS_H diff --git a/x64_dbg_dbg/memory.cpp b/x64_dbg_dbg/memory.cpp index 6db4e5cd..18746ebd 100644 --- a/x64_dbg_dbg/memory.cpp +++ b/x64_dbg_dbg/memory.cpp @@ -312,7 +312,7 @@ void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect) return VirtualAllocEx(fdProcessInfo->hProcess, (void*)Address, Size, MEM_RESERVE | MEM_COMMIT, Protect); } -void MemFreeRemote(uint Address) +bool MemFreeRemote(uint Address) { - VirtualFreeEx(fdProcessInfo->hProcess, (void*)Address, 0, MEM_RELEASE); + return !!VirtualFreeEx(fdProcessInfo->hProcess, (void*)Address, 0, MEM_RELEASE); } \ No newline at end of file diff --git a/x64_dbg_dbg/memory.h b/x64_dbg_dbg/memory.h index f1635cd4..666f614e 100644 --- a/x64_dbg_dbg/memory.h +++ b/x64_dbg_dbg/memory.h @@ -14,4 +14,4 @@ bool MemPatch(void* BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfByte bool MemIsValidReadPtr(uint Address); bool MemIsCanonicalAddress(uint Address); void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect); -void MemFreeRemote(uint Address); \ No newline at end of file +bool MemFreeRemote(uint Address); \ No newline at end of file diff --git a/x64_dbg_dbg/x64_dbg.cpp b/x64_dbg_dbg/x64_dbg.cpp index 83f76111..b8d0e109 100644 --- a/x64_dbg_dbg/x64_dbg.cpp +++ b/x64_dbg_dbg/x64_dbg.cpp @@ -203,6 +203,7 @@ static void registercommands() dbgcmdnew("capstone", cbInstrCapstone, true); //disassemble using capstone dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs + dbgcmdnew("cfanal\1cfanalyse\1cfanalyze", cbInstrCfanalyse, true); //control flow analysis } static bool cbCommandProvider(char* cmd, int maxlen) diff --git a/x64_dbg_dbg/x64_dbg_dbg.vcxproj b/x64_dbg_dbg/x64_dbg_dbg.vcxproj index d1d426ff..074fa32a 100644 --- a/x64_dbg_dbg/x64_dbg_dbg.vcxproj +++ b/x64_dbg_dbg/x64_dbg_dbg.vcxproj @@ -32,6 +32,7 @@ + @@ -72,12 +73,15 @@ + + + @@ -103,6 +107,7 @@ + @@ -187,12 +192,15 @@ + + + {E6548308-401E-3A8A-5819-905DB90522A6} diff --git a/x64_dbg_exe/x64_dbg_exe.vcxproj b/x64_dbg_exe/x64_dbg_exe.vcxproj index 2472ef77..a4f49b51 100644 --- a/x64_dbg_exe/x64_dbg_exe.vcxproj +++ b/x64_dbg_exe/x64_dbg_exe.vcxproj @@ -123,7 +123,7 @@ WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreadedDebugDLL Level3 ProgramDatabase @@ -160,7 +160,7 @@ WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreadedDebugDLL Level3 ProgramDatabase diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp index 4b48e20e..53657fea 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.cpp @@ -410,6 +410,27 @@ void Bridge::emitShowCpu() emit showCpu(); } +void Bridge::emitAddQWidgetTab(QWidget* qWidget) +{ + emit addQWidgetTab(qWidget); +} + +void Bridge::emitShowQWidgetTab(QWidget* qWidget) +{ + emit showQWidgetTab(qWidget); +} + +void Bridge::emitCloseQWidgetTab(QWidget* qWidget) +{ + emit closeQWidgetTab(qWidget); +} + +void Bridge::emitExecuteOnGuiThread(void* cbGuiThread) +{ + GuiAddLogMessage(QString().sprintf("thread id (bridge) %X\n", GetCurrentThreadId()).toUtf8().constData()); + emit executeOnGuiThread(cbGuiThread); +} + /************************************************************************************ Static Functions ************************************************************************************/ @@ -824,6 +845,30 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa } break; + case GUI_ADD_QWIDGET_TAB: + { + Bridge::getBridge()->emitAddQWidgetTab((QWidget*)param1); + } + break; + + case GUI_SHOW_QWIDGET_TAB: + { + Bridge::getBridge()->emitShowQWidgetTab((QWidget*)param1); + } + break; + + case GUI_CLOSE_QWIDGET_TAB: + { + Bridge::getBridge()->emitCloseQWidgetTab((QWidget*)param1); + } + break; + + case GUI_EXECUTE_ON_GUI_THREAD: + { + Bridge::getBridge()->emitExecuteOnGuiThread(param1); + } + break; + default: { diff --git a/x64_dbg_gui/Project/Src/Bridge/Bridge.h b/x64_dbg_gui/Project/Src/Bridge/Bridge.h index f663a9f5..f024fa1b 100644 --- a/x64_dbg_gui/Project/Src/Bridge/Bridge.h +++ b/x64_dbg_gui/Project/Src/Bridge/Bridge.h @@ -3,6 +3,7 @@ #include #include +#include #include #include "Imports.h" #include "NewTypes.h" @@ -87,6 +88,10 @@ public: void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon); void emitSetMenuIcon(int hMenu, const ICONDATA* icon); void emitShowCpu(); + void emitAddQWidgetTab(QWidget* qWidget); + void emitShowQWidgetTab(QWidget* qWidget); + void emitCloseQWidgetTab(QWidget* qWidget); + void emitExecuteOnGuiThread(void* cbGuiThread); //Public variables void* winId; @@ -156,6 +161,10 @@ signals: void setIconMenuEntry(int hEntry, QIcon icon); void setIconMenu(int hMenu, QIcon icon); void showCpu(); + void addQWidgetTab(QWidget* qWidget); + void showQWidgetTab(QWidget* qWidget); + void closeQWidgetTab(QWidget* qWidget); + void executeOnGuiThread(void* cbGuiThread); private: QMutex* mBridgeMutex; diff --git a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp index 5f995981..47e26404 100644 --- a/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp +++ b/x64_dbg_gui/Project/Src/Gui/MainWindow.cpp @@ -31,6 +31,10 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi connect(Bridge::getBridge(), SIGNAL(setIconMenu(int, QIcon)), this, SLOT(setIconMenu(int, QIcon))); connect(Bridge::getBridge(), SIGNAL(setIconMenuEntry(int, QIcon)), this, SLOT(setIconMenuEntry(int, QIcon))); connect(Bridge::getBridge(), SIGNAL(showCpu()), this, SLOT(displayCpuWidget())); + connect(Bridge::getBridge(), SIGNAL(addQWidgetTab(QWidget*)), this, SLOT(addQWidgetTab(QWidget*))); + connect(Bridge::getBridge(), SIGNAL(showQWidgetTab(QWidget*)), this, SLOT(showQWidgetTab(QWidget*))); + connect(Bridge::getBridge(), SIGNAL(closeQWidgetTab(QWidget*)), this, SLOT(closeQWidgetTab(QWidget*))); + connect(Bridge::getBridge(), SIGNAL(executeOnGuiThread(void*)), this, SLOT(executeOnGuiThread(void*))); //setup menu api initMenuApi(); @@ -130,17 +134,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mTabWidget = new MHTabWidget(NULL); //Setup tabs - mTabWidget->addTab(mCpuWidget, mCpuWidget->windowIcon(), mCpuWidget->windowTitle()); - mTabWidget->addTab(mLogView, mLogView->windowIcon(), mLogView->windowTitle()); - mTabWidget->addTab(mBreakpointsView, mBreakpointsView->windowIcon(), mBreakpointsView->windowTitle()); - mTabWidget->addTab(mMemMapView, mMemMapView->windowIcon(), mMemMapView->windowTitle()); - mTabWidget->addTab(mCallStackView, mCallStackView->windowIcon(), mCallStackView->windowTitle()); - mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle()); - mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle()); - mTabWidget->addTab(mSourceViewManager, mSourceViewManager->windowIcon(), mSourceViewManager->windowTitle()); - mTabWidget->addTab(mReferenceManager, mReferenceManager->windowIcon(), mReferenceManager->windowTitle()); - mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle()); - mTabWidget->addTab(mSnowmanView, mSnowmanView->windowIcon(), mSnowmanView->windowTitle()); + addQWidgetTab(mCpuWidget); + addQWidgetTab(mLogView); + addQWidgetTab(mBreakpointsView); + addQWidgetTab(mMemMapView); + addQWidgetTab(mCallStackView); + addQWidgetTab(mScriptView); + addQWidgetTab(mSymbolView); + addQWidgetTab(mSourceViewManager); + addQWidgetTab(mReferenceManager); + addQWidgetTab(mThreadView); + addQWidgetTab(mSnowmanView); setCentralWidget(mTabWidget); @@ -237,6 +241,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi mCloseDialog = new CloseDialog(this); mCpuWidget->mDisas->setFocus(); + + GuiAddLogMessage(QString().sprintf("thread id (GUI thread) %X\n", GetCurrentThreadId()).toUtf8().constData()); } void MainWindow::closeEvent(QCloseEvent* event) @@ -343,7 +349,7 @@ void MainWindow::loadMRUList(int maxItems) mMaxMRU = maxItems; for(int i = 0; i < mMaxMRU; i++) { - char currentFile[MAX_PATH] = ""; + char currentFile[MAX_SETTING_SIZE] = ""; if(!BridgeSettingGet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), currentFile)) break; if(QString(currentFile).size() && QFile(currentFile).exists()) @@ -488,23 +494,17 @@ void MainWindow::execRtr() void MainWindow::displayMemMapWidget() { - mMemMapView->show(); - mMemMapView->setFocus(); - setTab(mMemMapView); + showQWidgetTab(mMemMapView); } void MainWindow::displayLogWidget() { - mLogView->show(); - mLogView->setFocus(); - setTab(mLogView); + showQWidgetTab(mLogView); } void MainWindow::displayScriptWidget() { - mScriptView->show(); - mScriptView->setFocus(); - setTab(mScriptView); + showQWidgetTab(mScriptView); } void MainWindow::displayAboutWidget() @@ -607,9 +607,7 @@ void MainWindow::restartDebugging() void MainWindow::displayBreakpointWidget() { - mBreakpointsView->show(); - mBreakpointsView->setFocus(); - setTab(mBreakpointsView); + showQWidgetTab(mBreakpointsView); } void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent) @@ -667,44 +665,32 @@ void MainWindow::execSkip() void MainWindow::displayCpuWidget() { - mCpuWidget->show(); - mCpuWidget->setFocus(); - setTab(mCpuWidget); + showQWidgetTab(mCpuWidget); } void MainWindow::displaySymbolWidget() { - mSymbolView->show(); - mSymbolView->setFocus(); - setTab(mSymbolView); + showQWidgetTab(mSymbolView); } void MainWindow::displaySourceViewWidget() { - mSourceViewManager->show(); - mSourceViewManager->setFocus(); - setTab(mSourceViewManager); + showQWidgetTab(mSourceViewManager); } void MainWindow::displayReferencesWidget() { - mReferenceManager->show(); - mReferenceManager->setFocus(); - setTab(mReferenceManager); + showQWidgetTab(mReferenceManager); } void MainWindow::displayThreadsWidget() { - mThreadView->show(); - mThreadView->setFocus(); - setTab(mThreadView); + showQWidgetTab(mThreadView); } void MainWindow::displaySnowmanWidget() { - mSnowmanView->show(); - mSnowmanView->setFocus(); - setTab(mSnowmanView); + showQWidgetTab(mSnowmanView); } void MainWindow::openSettings() @@ -1025,9 +1011,7 @@ void MainWindow::checkUpdates() void MainWindow::displayCallstack() { - mCallStackView->show(); - mCallStackView->setFocus(); - setTab(mCallStackView); + showQWidgetTab(mCallStackView); } void MainWindow::donate() @@ -1122,3 +1106,30 @@ void MainWindow::canClose() bCanClose = true; close(); } + +void MainWindow::addQWidgetTab(QWidget* qWidget) +{ + mTabWidget->addTab(qWidget, qWidget->windowIcon(), qWidget->windowTitle()); +} + +void MainWindow::showQWidgetTab(QWidget* qWidget) +{ + qWidget->show(); + qWidget->setFocus(); + setTab(qWidget); +} + +void MainWindow::closeQWidgetTab(QWidget* qWidget) +{ + for(int i = 0; i < mTabWidget->count(); i++) + if(mTabWidget->widget(i) == qWidget) + { + mTabWidget->DeleteTab(i); + break; + } +} + +void MainWindow::executeOnGuiThread(void* cbGuiThread) +{ + ((GUICALLBACK)cbGuiThread)(); +} diff --git a/x64_dbg_gui/Project/Src/Gui/MainWindow.h b/x64_dbg_gui/Project/Src/Gui/MainWindow.h index dba22c03..6dc3dfdc 100644 --- a/x64_dbg_gui/Project/Src/Gui/MainWindow.h +++ b/x64_dbg_gui/Project/Src/Gui/MainWindow.h @@ -104,6 +104,10 @@ public slots: void changeCommandLine(); void decompileAt(int_t start, int_t end); void canClose(); + void addQWidgetTab(QWidget* qWidget); + void showQWidgetTab(QWidget* qWidget); + void closeQWidgetTab(QWidget* qWidget); + void executeOnGuiThread(void* cbGuiThread); private: Ui::MainWindow* ui; diff --git a/x64_dbg_gui/Project/Src/Gui/ScriptView.cpp b/x64_dbg_gui/Project/Src/Gui/ScriptView.cpp index e76ffa77..a8c59eba 100644 --- a/x64_dbg_gui/Project/Src/Gui/ScriptView.cpp +++ b/x64_dbg_gui/Project/Src/Gui/ScriptView.cpp @@ -579,7 +579,7 @@ void ScriptView::cmdExec() void ScriptView::message(QString message) { - QMessageBox msg(QMessageBox::Information, "Information", message); + QMessageBox msg(QMessageBox::Information, "Message", message); msg.setWindowIcon(QIcon(":/icons/images/information.png")); msg.setParent(this, Qt::Dialog); msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint)); diff --git a/x64_dbg_launcher/x64_dbg_launcher.vcxproj b/x64_dbg_launcher/x64_dbg_launcher.vcxproj index 45bae506..b2b2f0ac 100644 --- a/x64_dbg_launcher/x64_dbg_launcher.vcxproj +++ b/x64_dbg_launcher/x64_dbg_launcher.vcxproj @@ -80,7 +80,7 @@ WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreadedDLL + MultiThreadedDebugDLL Level3 ProgramDatabase