Merge branch 'master' of https://github.com/x64dbg/x64dbg
Conflicts: x64_dbg_dbg/functionanalysis.cpp x64_dbg_dbg/x64_dbg_dbg.vcxproj x64_dbg_dbg/x64_dbg_dbg.vcxproj.filters
This commit is contained in:
commit
ab3ecaf054
|
@ -1120,6 +1120,26 @@ BRIDGE_IMPEXP void GuiShowCpu()
|
||||||
_gui_sendmessage(GUI_SHOW_CPU, 0, 0);
|
_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)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
hInst = hinstDLL;
|
hInst = hinstDLL;
|
||||||
|
|
|
@ -761,9 +761,16 @@ typedef enum
|
||||||
GUI_LOAD_SOURCE_FILE, // param1=const char* path, param2=line
|
GUI_LOAD_SOURCE_FILE, // param1=const char* path, param2=line
|
||||||
GUI_MENU_SET_ICON, // param1=int hMenu, param2=ICONINFO*
|
GUI_MENU_SET_ICON, // param1=int hMenu, param2=ICONINFO*
|
||||||
GUI_MENU_SET_ENTRY_ICON, // param1=int hEntry, 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;
|
} GUIMSG;
|
||||||
|
|
||||||
|
//GUI Typedefs
|
||||||
|
typedef void (*GUICALLBACK)();
|
||||||
|
|
||||||
//GUI structures
|
//GUI structures
|
||||||
typedef struct
|
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 GuiMenuSetIcon(int hMenu, const ICONDATA* icon);
|
||||||
BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon);
|
BRIDGE_IMPEXP void GuiMenuSetEntryIcon(int hEntry, const ICONDATA* icon);
|
||||||
BRIDGE_IMPEXP void GuiShowCpu();
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
@ -139,7 +139,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>BUILD_BRIDGE;WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -1,51 +1,5 @@
|
||||||
#include "_scriptapi_gui.h"
|
#include "_scriptapi_gui.h"
|
||||||
|
#include "_scriptapi_misc.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
|
SCRIPT_EXPORT bool Script::Gui::Disassembly::SelectionGet(duint* start, duint* end)
|
||||||
{
|
{
|
||||||
|
@ -106,3 +60,93 @@ SCRIPT_EXPORT duint Script::Gui::Stack::SelectionGetEnd()
|
||||||
{
|
{
|
||||||
return Gui::SelectionGetEnd(StackWindow);
|
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<char*> 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);
|
||||||
|
}
|
|
@ -7,18 +7,6 @@ namespace Script
|
||||||
{
|
{
|
||||||
namespace 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);
|
|
||||||
|
|
||||||
namespace Disassembly
|
namespace Disassembly
|
||||||
{
|
{
|
||||||
SCRIPT_EXPORT bool SelectionGet(duint* start, duint* end);
|
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 SelectionGetStart();
|
||||||
SCRIPT_EXPORT duint SelectionGetEnd();
|
SCRIPT_EXPORT duint SelectionGetEnd();
|
||||||
}; //Stack
|
}; //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
|
}; //Gui
|
||||||
}; //Script
|
}; //Script
|
||||||
|
|
||||||
|
|
|
@ -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);
|
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)
|
SCRIPT_EXPORT unsigned char Script::Memory::ReadByte(duint addr)
|
||||||
{
|
{
|
||||||
unsigned char data;
|
unsigned char data;
|
||||||
|
|
|
@ -9,6 +9,9 @@ namespace Memory
|
||||||
{
|
{
|
||||||
SCRIPT_EXPORT bool Read(duint addr, void* data, duint size, duint* sizeRead);
|
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 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 unsigned char ReadByte(duint addr);
|
||||||
SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data);
|
SCRIPT_EXPORT bool WriteByte(duint addr, unsigned char data);
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
|
@ -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
|
|
@ -9,6 +9,7 @@ static const char* regTable[] =
|
||||||
"DR3",
|
"DR3",
|
||||||
"DR6",
|
"DR6",
|
||||||
"DR7",
|
"DR7",
|
||||||
|
|
||||||
"EAX",
|
"EAX",
|
||||||
"AX",
|
"AX",
|
||||||
"AH",
|
"AH",
|
||||||
|
@ -34,7 +35,7 @@ static const char* regTable[] =
|
||||||
"ESP",
|
"ESP",
|
||||||
"SP",
|
"SP",
|
||||||
"EIP",
|
"EIP",
|
||||||
"CIP",
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
"RAX",
|
"RAX",
|
||||||
"RBX",
|
"RBX",
|
||||||
|
@ -80,7 +81,15 @@ static const char* regTable[] =
|
||||||
"R15",
|
"R15",
|
||||||
"R15D",
|
"R15D",
|
||||||
"R15W",
|
"R15W",
|
||||||
"R15"
|
"R15",
|
||||||
|
#endif //_WIN64
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
"RIP",
|
||||||
|
"RSP"
|
||||||
|
#else //x32
|
||||||
|
"EIP",
|
||||||
|
"ESP"
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,6 +105,11 @@ SCRIPT_EXPORT bool Script::Register::Set(Script::Register::RegisterEnum reg, dui
|
||||||
return setregister(regTable[reg], value);
|
return setregister(regTable[reg], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCRIPT_EXPORT int Script::Register::Size()
|
||||||
|
{
|
||||||
|
return (int)sizeof(duint);
|
||||||
|
}
|
||||||
|
|
||||||
SCRIPT_EXPORT duint Script::Register::GetDR0()
|
SCRIPT_EXPORT duint Script::Register::GetDR0()
|
||||||
{
|
{
|
||||||
return Get(DR0);
|
return Get(DR0);
|
||||||
|
@ -406,16 +420,6 @@ SCRIPT_EXPORT bool Script::Register::SetEIP(unsigned int value)
|
||||||
return Set(EIP, 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
|
#ifdef _WIN64
|
||||||
SCRIPT_EXPORT unsigned long long Script::Register::GetRAX()
|
SCRIPT_EXPORT unsigned long long Script::Register::GetRAX()
|
||||||
{
|
{
|
||||||
|
@ -867,3 +871,23 @@ SCRIPT_EXPORT bool Script::Register::SetR15B(unsigned char value)
|
||||||
return Set(R15B, value);
|
return Set(R15B, value);
|
||||||
}
|
}
|
||||||
#endif //_WIN64
|
#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);
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ enum RegisterEnum
|
||||||
DR3,
|
DR3,
|
||||||
DR6,
|
DR6,
|
||||||
DR7,
|
DR7,
|
||||||
|
|
||||||
EAX,
|
EAX,
|
||||||
AX,
|
AX,
|
||||||
AH,
|
AH,
|
||||||
|
@ -40,7 +41,7 @@ enum RegisterEnum
|
||||||
ESP,
|
ESP,
|
||||||
SP,
|
SP,
|
||||||
EIP,
|
EIP,
|
||||||
CIP,
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
RAX,
|
RAX,
|
||||||
RBX,
|
RBX,
|
||||||
|
@ -86,12 +87,16 @@ enum RegisterEnum
|
||||||
R15,
|
R15,
|
||||||
R15D,
|
R15D,
|
||||||
R15W,
|
R15W,
|
||||||
R15B
|
R15B,
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
|
|
||||||
|
CIP,
|
||||||
|
CSP,
|
||||||
}; //RegisterEnum
|
}; //RegisterEnum
|
||||||
|
|
||||||
SCRIPT_EXPORT duint Get(RegisterEnum reg);
|
SCRIPT_EXPORT duint Get(RegisterEnum reg);
|
||||||
SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value);
|
SCRIPT_EXPORT bool Set(RegisterEnum reg, duint value);
|
||||||
|
SCRIPT_EXPORT int Size(); //gets architecture register size in bytes
|
||||||
|
|
||||||
SCRIPT_EXPORT duint GetDR0();
|
SCRIPT_EXPORT duint GetDR0();
|
||||||
SCRIPT_EXPORT bool SetDR0(duint value);
|
SCRIPT_EXPORT bool SetDR0(duint value);
|
||||||
|
@ -105,6 +110,7 @@ SCRIPT_EXPORT duint GetDR6();
|
||||||
SCRIPT_EXPORT bool SetDR6(duint value);
|
SCRIPT_EXPORT bool SetDR6(duint value);
|
||||||
SCRIPT_EXPORT duint GetDR7();
|
SCRIPT_EXPORT duint GetDR7();
|
||||||
SCRIPT_EXPORT bool SetDR7(duint value);
|
SCRIPT_EXPORT bool SetDR7(duint value);
|
||||||
|
|
||||||
SCRIPT_EXPORT unsigned int GetEAX();
|
SCRIPT_EXPORT unsigned int GetEAX();
|
||||||
SCRIPT_EXPORT bool SetEAX(unsigned int value);
|
SCRIPT_EXPORT bool SetEAX(unsigned int value);
|
||||||
SCRIPT_EXPORT unsigned short GetAX();
|
SCRIPT_EXPORT unsigned short GetAX();
|
||||||
|
@ -155,8 +161,7 @@ SCRIPT_EXPORT unsigned short GetSP();
|
||||||
SCRIPT_EXPORT bool SetSP(unsigned short value);
|
SCRIPT_EXPORT bool SetSP(unsigned short value);
|
||||||
SCRIPT_EXPORT unsigned int GetEIP();
|
SCRIPT_EXPORT unsigned int GetEIP();
|
||||||
SCRIPT_EXPORT bool SetEIP(unsigned int value);
|
SCRIPT_EXPORT bool SetEIP(unsigned int value);
|
||||||
SCRIPT_EXPORT duint GetCIP();
|
|
||||||
SCRIPT_EXPORT bool SetCIP(duint value);
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
SCRIPT_EXPORT unsigned long long GetRAX();
|
SCRIPT_EXPORT unsigned long long GetRAX();
|
||||||
SCRIPT_EXPORT bool SetRAX(unsigned long long value);
|
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 unsigned char GetR15B();
|
||||||
SCRIPT_EXPORT bool SetR15B(unsigned char value);
|
SCRIPT_EXPORT bool SetR15B(unsigned char value);
|
||||||
#endif //_WIN64
|
#endif //_WIN64
|
||||||
|
|
||||||
|
SCRIPT_EXPORT duint GetCIP();
|
||||||
|
SCRIPT_EXPORT bool SetCIP(duint value);
|
||||||
|
SCRIPT_EXPORT duint GetCSP();
|
||||||
|
SCRIPT_EXPORT bool SetCSP(duint value);
|
||||||
}; //Register
|
}; //Register
|
||||||
}; //Script
|
}; //Script
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -86,7 +86,7 @@ String Capstone::OperandText(int opindex)
|
||||||
|
|
||||||
case X86_OP_IMM:
|
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);
|
sprintf_s(temp, "%"fext"X", op.imm + mInstr->size);
|
||||||
else
|
else
|
||||||
sprintf_s(temp, "%"fext"X", op.imm);
|
sprintf_s(temp, "%"fext"X", op.imm);
|
||||||
|
@ -163,8 +163,27 @@ const cs_x86 & Capstone::x86()
|
||||||
|
|
||||||
bool Capstone::IsFilling()
|
bool Capstone::IsFilling()
|
||||||
{
|
{
|
||||||
uint8_t opcode = x86().opcode[0];
|
switch(GetId())
|
||||||
return opcode == 0x90 || opcode == 0xCC;
|
{
|
||||||
|
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()
|
x86_insn Capstone::GetId()
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
const uint Address();
|
const uint Address();
|
||||||
const cs_x86 & x86();
|
const cs_x86 & x86();
|
||||||
bool IsFilling();
|
bool IsFilling();
|
||||||
|
bool IsLoop();
|
||||||
x86_insn GetId();
|
x86_insn GetId();
|
||||||
String InstructionText();
|
String InstructionText();
|
||||||
|
|
||||||
|
|
|
@ -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<uint, int> 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;
|
||||||
|
}
|
|
@ -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<uint> _blockStarts;
|
||||||
|
std::vector<BasicBlock> _blocks;
|
||||||
|
|
||||||
|
void BasicBlockStarts();
|
||||||
|
void BasicBlocks();
|
||||||
|
uint GetBranchOperand();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_CONTROLFLOWANALYSIS_H
|
|
@ -776,14 +776,16 @@ static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread)
|
||||||
static void cbSystemBreakpoint(void* ExceptionData)
|
static void cbSystemBreakpoint(void* ExceptionData)
|
||||||
{
|
{
|
||||||
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
hActiveThread = ThreadGetHandle(((DEBUG_EVENT*)GetDebugData())->dwThreadId);
|
||||||
|
|
||||||
|
uint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
||||||
|
GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere
|
||||||
|
|
||||||
//log message
|
//log message
|
||||||
if(bIsAttached)
|
if(bIsAttached)
|
||||||
dputs("Attach breakpoint reached!");
|
dputs("Attach breakpoint reached!");
|
||||||
else
|
else
|
||||||
dputs("System breakpoint reached!");
|
dputs("System breakpoint reached!");
|
||||||
bSkipExceptions = false; //we are not skipping first-chance exceptions
|
bSkipExceptions = false; //we are not skipping first-chance exceptions
|
||||||
uint cip = GetContextDataEx(hActiveThread, UE_CIP);
|
|
||||||
GuiDumpAt(MemFindBaseAddr(cip, 0, true)); //dump somewhere
|
|
||||||
|
|
||||||
//plugin callbacks
|
//plugin callbacks
|
||||||
PLUG_CB_SYSTEMBREAKPOINT callbackInfo;
|
PLUG_CB_SYSTEMBREAKPOINT callbackInfo;
|
||||||
|
|
|
@ -38,7 +38,7 @@ void fillbasicinfo(Capstone* cp, BASIC_INSTRUCTION_INFO* basicinfo)
|
||||||
basicinfo->branch = true;
|
basicinfo->branch = true;
|
||||||
basicinfo->call = true;
|
basicinfo->call = true;
|
||||||
}
|
}
|
||||||
else if(cp->InGroup(CS_GRP_JUMP))
|
else if(cp->InGroup(CS_GRP_JUMP) || cp->IsLoop())
|
||||||
{
|
{
|
||||||
basicinfo->branch = true;
|
basicinfo->branch = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
sprintf_s(instr->instruction, "%s %s", cp.GetInstr()->mnemonic, cp.GetInstr()->op_str);
|
||||||
const cs_x86 & x86 = cp.GetInstr()->detail->x86;
|
const cs_x86 & x86 = cp.GetInstr()->detail->x86;
|
||||||
instr->instr_size = cp.GetInstr()->size;
|
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;
|
instr->type = instr_branch;
|
||||||
else if(strstr(cp.GetInstr()->op_str, "sp") || strstr(cp.GetInstr()->op_str, "bp"))
|
else if(strstr(cp.GetInstr()->op_str, "sp") || strstr(cp.GetInstr()->op_str, "bp"))
|
||||||
instr->type = instr_stack;
|
instr->type = instr_stack;
|
||||||
|
|
|
@ -3,31 +3,20 @@
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
|
|
||||||
#include "module.h"
|
FunctionAnalysis::FunctionAnalysis(uint base, uint size) : Analysis(base, size)
|
||||||
#include "LinearPass.h"
|
|
||||||
|
|
||||||
FunctionAnalysis::FunctionAnalysis(uint base, uint 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()
|
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()
|
void FunctionAnalysis::SetMarkers()
|
||||||
|
@ -109,7 +98,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const cs_x86_op & operand = _cp.x86().operands[0];
|
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;
|
uint dest = (uint)operand.imm;
|
||||||
|
|
||||||
|
@ -121,7 +110,7 @@ uint FunctionAnalysis::FindFunctionEnd(uint start, uint maxaddr)
|
||||||
{
|
{
|
||||||
fardest = dest;
|
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;
|
jumpback = addr;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +135,7 @@ uint FunctionAnalysis::GetReferenceOperand()
|
||||||
for(int i = 0; i < _cp.x86().op_count; i++)
|
for(int i = 0; i < _cp.x86().op_count; i++)
|
||||||
{
|
{
|
||||||
const cs_x86_op & operand = _cp.x86().operands[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;
|
continue;
|
||||||
if(operand.type == X86_OP_IMM) //we are looking for immediate references
|
if(operand.type == X86_OP_IMM) //we are looking for immediate references
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
|
|
||||||
#include "_global.h"
|
#include "_global.h"
|
||||||
#include "capstone_wrapper.h"
|
#include "capstone_wrapper.h"
|
||||||
|
#include "analysis.h"
|
||||||
|
|
||||||
class FunctionAnalysis
|
class FunctionAnalysis : public Analysis
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FunctionAnalysis(uint base, uint size);
|
explicit FunctionAnalysis(uint base, uint size);
|
||||||
FunctionAnalysis(const FunctionAnalysis & that) = delete;
|
|
||||||
~FunctionAnalysis();
|
|
||||||
const unsigned char* TranslateAddress(uint addr);
|
|
||||||
void Analyse();
|
void Analyse();
|
||||||
void SetMarkers();
|
void SetMarkers();
|
||||||
|
|
||||||
|
private:
|
||||||
struct FunctionInfo
|
struct FunctionInfo
|
||||||
{
|
{
|
||||||
uint start;
|
uint start;
|
||||||
|
@ -30,12 +29,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
uint _base;
|
|
||||||
uint _size;
|
|
||||||
unsigned char* _data;
|
|
||||||
std::vector<FunctionInfo> _functions;
|
std::vector<FunctionInfo> _functions;
|
||||||
Capstone _cp;
|
|
||||||
|
|
||||||
void SortCleanup();
|
void SortCleanup();
|
||||||
void PopulateReferences();
|
void PopulateReferences();
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
#include "stringformat.h"
|
#include "stringformat.h"
|
||||||
#include "filereader.h"
|
#include "filereader.h"
|
||||||
|
#include "functionanalysis.h"
|
||||||
|
#include "controlflowanalysis.h"
|
||||||
|
|
||||||
static bool bRefinit = false;
|
static bool bRefinit = false;
|
||||||
|
|
||||||
|
@ -1877,8 +1879,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[])
|
||||||
return STATUS_CONTINUE;
|
return STATUS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "functionanalysis.h"
|
|
||||||
|
|
||||||
CMDRESULT cbInstrAnalyse(int argc, char* argv[])
|
CMDRESULT cbInstrAnalyse(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
SELECTIONDATA sel;
|
SELECTIONDATA sel;
|
||||||
|
@ -1892,6 +1892,19 @@ CMDRESULT cbInstrAnalyse(int argc, char* argv[])
|
||||||
return STATUS_CONTINUE;
|
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[])
|
CMDRESULT cbInstrVisualize(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if(argc < 3)
|
if(argc < 3)
|
||||||
|
@ -1950,7 +1963,7 @@ CMDRESULT cbInstrVisualize(int argc, char* argv[])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const cs_x86_op & operand = _cp.x86().operands[0];
|
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;
|
uint dest = (uint)operand.imm;
|
||||||
|
|
||||||
|
|
|
@ -70,5 +70,6 @@ CMDRESULT cbInstrCapstone(int argc, char* argv[]);
|
||||||
CMDRESULT cbInstrAnalyse(int argc, char* argv[]);
|
CMDRESULT cbInstrAnalyse(int argc, char* argv[]);
|
||||||
CMDRESULT cbInstrVisualize(int argc, char* argv[]);
|
CMDRESULT cbInstrVisualize(int argc, char* argv[]);
|
||||||
CMDRESULT cbInstrMeminfo(int argc, char* argv[]);
|
CMDRESULT cbInstrMeminfo(int argc, char* argv[]);
|
||||||
|
CMDRESULT cbInstrCfanalyse(int argc, char* argv[]);
|
||||||
|
|
||||||
#endif // _INSTRUCTIONS_H
|
#endif // _INSTRUCTIONS_H
|
||||||
|
|
|
@ -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);
|
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);
|
||||||
}
|
}
|
|
@ -14,4 +14,4 @@ bool MemPatch(void* BaseAddress, void* Buffer, SIZE_T Size, SIZE_T* NumberOfByte
|
||||||
bool MemIsValidReadPtr(uint Address);
|
bool MemIsValidReadPtr(uint Address);
|
||||||
bool MemIsCanonicalAddress(uint Address);
|
bool MemIsCanonicalAddress(uint Address);
|
||||||
void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect);
|
void* MemAllocRemote(uint Address, SIZE_T Size, DWORD Protect);
|
||||||
void MemFreeRemote(uint Address);
|
bool MemFreeRemote(uint Address);
|
|
@ -203,6 +203,7 @@ static void registercommands()
|
||||||
dbgcmdnew("capstone", cbInstrCapstone, true); //disassemble using capstone
|
dbgcmdnew("capstone", cbInstrCapstone, true); //disassemble using capstone
|
||||||
dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis
|
dbgcmdnew("visualize", cbInstrVisualize, true); //visualize analysis
|
||||||
dbgcmdnew("meminfo", cbInstrMeminfo, true); //command to debug memory map bugs
|
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)
|
static bool cbCommandProvider(char* cmd, int maxlen)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<ClCompile Include="commandparser.cpp" />
|
<ClCompile Include="commandparser.cpp" />
|
||||||
<ClCompile Include="comment.cpp" />
|
<ClCompile Include="comment.cpp" />
|
||||||
<ClCompile Include="console.cpp" />
|
<ClCompile Include="console.cpp" />
|
||||||
|
<ClCompile Include="controlflowanalysis.cpp" />
|
||||||
<ClCompile Include="dbghelp_safe.cpp" />
|
<ClCompile Include="dbghelp_safe.cpp" />
|
||||||
<ClCompile Include="debugger.cpp" />
|
<ClCompile Include="debugger.cpp" />
|
||||||
<ClCompile Include="debugger_commands.cpp" />
|
<ClCompile Include="debugger_commands.cpp" />
|
||||||
|
@ -72,12 +73,15 @@
|
||||||
<ClCompile Include="_dbgfunctions.cpp" />
|
<ClCompile Include="_dbgfunctions.cpp" />
|
||||||
<ClCompile Include="_global.cpp" />
|
<ClCompile Include="_global.cpp" />
|
||||||
<ClCompile Include="_plugins.cpp" />
|
<ClCompile Include="_plugins.cpp" />
|
||||||
|
<ClCompile Include="_scriptapi_assembler.cpp" />
|
||||||
<ClCompile Include="_scriptapi_debug.cpp" />
|
<ClCompile Include="_scriptapi_debug.cpp" />
|
||||||
<ClCompile Include="_scriptapi_gui.cpp" />
|
<ClCompile Include="_scriptapi_gui.cpp" />
|
||||||
|
<ClCompile Include="_scriptapi_misc.cpp" />
|
||||||
<ClCompile Include="_scriptapi_pattern.cpp" />
|
<ClCompile Include="_scriptapi_pattern.cpp" />
|
||||||
<ClCompile Include="_scriptapi_memory.cpp" />
|
<ClCompile Include="_scriptapi_memory.cpp" />
|
||||||
<ClCompile Include="_scriptapi_module.cpp" />
|
<ClCompile Include="_scriptapi_module.cpp" />
|
||||||
<ClCompile Include="_scriptapi_register.cpp" />
|
<ClCompile Include="_scriptapi_register.cpp" />
|
||||||
|
<ClCompile Include="_scriptapi_stack.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="addrinfo.h" />
|
<ClInclude Include="addrinfo.h" />
|
||||||
|
@ -103,6 +107,7 @@
|
||||||
<ClInclude Include="commandparser.h" />
|
<ClInclude Include="commandparser.h" />
|
||||||
<ClInclude Include="comment.h" />
|
<ClInclude Include="comment.h" />
|
||||||
<ClInclude Include="console.h" />
|
<ClInclude Include="console.h" />
|
||||||
|
<ClInclude Include="controlflowanalysis.h" />
|
||||||
<ClInclude Include="dbghelp\dbghelp.h" />
|
<ClInclude Include="dbghelp\dbghelp.h" />
|
||||||
<ClInclude Include="dbghelp_safe.h" />
|
<ClInclude Include="dbghelp_safe.h" />
|
||||||
<ClInclude Include="debugger.h" />
|
<ClInclude Include="debugger.h" />
|
||||||
|
@ -187,12 +192,15 @@
|
||||||
<ClInclude Include="_global.h" />
|
<ClInclude Include="_global.h" />
|
||||||
<ClInclude Include="_plugins.h" />
|
<ClInclude Include="_plugins.h" />
|
||||||
<ClInclude Include="_plugin_types.h" />
|
<ClInclude Include="_plugin_types.h" />
|
||||||
|
<ClInclude Include="_scriptapi_assembler.h" />
|
||||||
<ClInclude Include="_scriptapi_debug.h" />
|
<ClInclude Include="_scriptapi_debug.h" />
|
||||||
<ClInclude Include="_scriptapi_gui.h" />
|
<ClInclude Include="_scriptapi_gui.h" />
|
||||||
|
<ClInclude Include="_scriptapi_misc.h" />
|
||||||
<ClInclude Include="_scriptapi_pattern.h" />
|
<ClInclude Include="_scriptapi_pattern.h" />
|
||||||
<ClInclude Include="_scriptapi_memory.h" />
|
<ClInclude Include="_scriptapi_memory.h" />
|
||||||
<ClInclude Include="_scriptapi_module.h" />
|
<ClInclude Include="_scriptapi_module.h" />
|
||||||
<ClInclude Include="_scriptapi_register.h" />
|
<ClInclude Include="_scriptapi_register.h" />
|
||||||
|
<ClInclude Include="_scriptapi_stack.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{E6548308-401E-3A8A-5819-905DB90522A6}</ProjectGuid>
|
<ProjectGuid>{E6548308-401E-3A8A-5819-905DB90522A6}</ProjectGuid>
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -160,7 +160,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -410,6 +410,27 @@ void Bridge::emitShowCpu()
|
||||||
emit showCpu();
|
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
|
Static Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
@ -824,6 +845,30 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <agents.h>
|
#include <agents.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include "Imports.h"
|
#include "Imports.h"
|
||||||
#include "NewTypes.h"
|
#include "NewTypes.h"
|
||||||
|
@ -87,6 +88,10 @@ public:
|
||||||
void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon);
|
void emitSetMenuEntryIcon(int hEntry, const ICONDATA* icon);
|
||||||
void emitSetMenuIcon(int hMenu, const ICONDATA* icon);
|
void emitSetMenuIcon(int hMenu, const ICONDATA* icon);
|
||||||
void emitShowCpu();
|
void emitShowCpu();
|
||||||
|
void emitAddQWidgetTab(QWidget* qWidget);
|
||||||
|
void emitShowQWidgetTab(QWidget* qWidget);
|
||||||
|
void emitCloseQWidgetTab(QWidget* qWidget);
|
||||||
|
void emitExecuteOnGuiThread(void* cbGuiThread);
|
||||||
|
|
||||||
//Public variables
|
//Public variables
|
||||||
void* winId;
|
void* winId;
|
||||||
|
@ -156,6 +161,10 @@ signals:
|
||||||
void setIconMenuEntry(int hEntry, QIcon icon);
|
void setIconMenuEntry(int hEntry, QIcon icon);
|
||||||
void setIconMenu(int hMenu, QIcon icon);
|
void setIconMenu(int hMenu, QIcon icon);
|
||||||
void showCpu();
|
void showCpu();
|
||||||
|
void addQWidgetTab(QWidget* qWidget);
|
||||||
|
void showQWidgetTab(QWidget* qWidget);
|
||||||
|
void closeQWidgetTab(QWidget* qWidget);
|
||||||
|
void executeOnGuiThread(void* cbGuiThread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex* mBridgeMutex;
|
QMutex* mBridgeMutex;
|
||||||
|
|
|
@ -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(setIconMenu(int, QIcon)), this, SLOT(setIconMenu(int, QIcon)));
|
||||||
connect(Bridge::getBridge(), SIGNAL(setIconMenuEntry(int, QIcon)), this, SLOT(setIconMenuEntry(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(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
|
//setup menu api
|
||||||
initMenuApi();
|
initMenuApi();
|
||||||
|
@ -130,17 +134,17 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||||
mTabWidget = new MHTabWidget(NULL);
|
mTabWidget = new MHTabWidget(NULL);
|
||||||
|
|
||||||
//Setup tabs
|
//Setup tabs
|
||||||
mTabWidget->addTab(mCpuWidget, mCpuWidget->windowIcon(), mCpuWidget->windowTitle());
|
addQWidgetTab(mCpuWidget);
|
||||||
mTabWidget->addTab(mLogView, mLogView->windowIcon(), mLogView->windowTitle());
|
addQWidgetTab(mLogView);
|
||||||
mTabWidget->addTab(mBreakpointsView, mBreakpointsView->windowIcon(), mBreakpointsView->windowTitle());
|
addQWidgetTab(mBreakpointsView);
|
||||||
mTabWidget->addTab(mMemMapView, mMemMapView->windowIcon(), mMemMapView->windowTitle());
|
addQWidgetTab(mMemMapView);
|
||||||
mTabWidget->addTab(mCallStackView, mCallStackView->windowIcon(), mCallStackView->windowTitle());
|
addQWidgetTab(mCallStackView);
|
||||||
mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle());
|
addQWidgetTab(mScriptView);
|
||||||
mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle());
|
addQWidgetTab(mSymbolView);
|
||||||
mTabWidget->addTab(mSourceViewManager, mSourceViewManager->windowIcon(), mSourceViewManager->windowTitle());
|
addQWidgetTab(mSourceViewManager);
|
||||||
mTabWidget->addTab(mReferenceManager, mReferenceManager->windowIcon(), mReferenceManager->windowTitle());
|
addQWidgetTab(mReferenceManager);
|
||||||
mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle());
|
addQWidgetTab(mThreadView);
|
||||||
mTabWidget->addTab(mSnowmanView, mSnowmanView->windowIcon(), mSnowmanView->windowTitle());
|
addQWidgetTab(mSnowmanView);
|
||||||
|
|
||||||
setCentralWidget(mTabWidget);
|
setCentralWidget(mTabWidget);
|
||||||
|
|
||||||
|
@ -237,6 +241,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
|
||||||
mCloseDialog = new CloseDialog(this);
|
mCloseDialog = new CloseDialog(this);
|
||||||
|
|
||||||
mCpuWidget->mDisas->setFocus();
|
mCpuWidget->mDisas->setFocus();
|
||||||
|
|
||||||
|
GuiAddLogMessage(QString().sprintf("thread id (GUI thread) %X\n", GetCurrentThreadId()).toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent* event)
|
void MainWindow::closeEvent(QCloseEvent* event)
|
||||||
|
@ -343,7 +349,7 @@ void MainWindow::loadMRUList(int maxItems)
|
||||||
mMaxMRU = maxItems;
|
mMaxMRU = maxItems;
|
||||||
for(int i = 0; i < mMaxMRU; i++)
|
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))
|
if(!BridgeSettingGet("Recent Files", QString().sprintf("%.2d", i + 1).toUtf8().constData(), currentFile))
|
||||||
break;
|
break;
|
||||||
if(QString(currentFile).size() && QFile(currentFile).exists())
|
if(QString(currentFile).size() && QFile(currentFile).exists())
|
||||||
|
@ -488,23 +494,17 @@ void MainWindow::execRtr()
|
||||||
|
|
||||||
void MainWindow::displayMemMapWidget()
|
void MainWindow::displayMemMapWidget()
|
||||||
{
|
{
|
||||||
mMemMapView->show();
|
showQWidgetTab(mMemMapView);
|
||||||
mMemMapView->setFocus();
|
|
||||||
setTab(mMemMapView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displayLogWidget()
|
void MainWindow::displayLogWidget()
|
||||||
{
|
{
|
||||||
mLogView->show();
|
showQWidgetTab(mLogView);
|
||||||
mLogView->setFocus();
|
|
||||||
setTab(mLogView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displayScriptWidget()
|
void MainWindow::displayScriptWidget()
|
||||||
{
|
{
|
||||||
mScriptView->show();
|
showQWidgetTab(mScriptView);
|
||||||
mScriptView->setFocus();
|
|
||||||
setTab(mScriptView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displayAboutWidget()
|
void MainWindow::displayAboutWidget()
|
||||||
|
@ -607,9 +607,7 @@ void MainWindow::restartDebugging()
|
||||||
|
|
||||||
void MainWindow::displayBreakpointWidget()
|
void MainWindow::displayBreakpointWidget()
|
||||||
{
|
{
|
||||||
mBreakpointsView->show();
|
showQWidgetTab(mBreakpointsView);
|
||||||
mBreakpointsView->setFocus();
|
|
||||||
setTab(mBreakpointsView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent)
|
void MainWindow::dragEnterEvent(QDragEnterEvent* pEvent)
|
||||||
|
@ -667,44 +665,32 @@ void MainWindow::execSkip()
|
||||||
|
|
||||||
void MainWindow::displayCpuWidget()
|
void MainWindow::displayCpuWidget()
|
||||||
{
|
{
|
||||||
mCpuWidget->show();
|
showQWidgetTab(mCpuWidget);
|
||||||
mCpuWidget->setFocus();
|
|
||||||
setTab(mCpuWidget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displaySymbolWidget()
|
void MainWindow::displaySymbolWidget()
|
||||||
{
|
{
|
||||||
mSymbolView->show();
|
showQWidgetTab(mSymbolView);
|
||||||
mSymbolView->setFocus();
|
|
||||||
setTab(mSymbolView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displaySourceViewWidget()
|
void MainWindow::displaySourceViewWidget()
|
||||||
{
|
{
|
||||||
mSourceViewManager->show();
|
showQWidgetTab(mSourceViewManager);
|
||||||
mSourceViewManager->setFocus();
|
|
||||||
setTab(mSourceViewManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displayReferencesWidget()
|
void MainWindow::displayReferencesWidget()
|
||||||
{
|
{
|
||||||
mReferenceManager->show();
|
showQWidgetTab(mReferenceManager);
|
||||||
mReferenceManager->setFocus();
|
|
||||||
setTab(mReferenceManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displayThreadsWidget()
|
void MainWindow::displayThreadsWidget()
|
||||||
{
|
{
|
||||||
mThreadView->show();
|
showQWidgetTab(mThreadView);
|
||||||
mThreadView->setFocus();
|
|
||||||
setTab(mThreadView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::displaySnowmanWidget()
|
void MainWindow::displaySnowmanWidget()
|
||||||
{
|
{
|
||||||
mSnowmanView->show();
|
showQWidgetTab(mSnowmanView);
|
||||||
mSnowmanView->setFocus();
|
|
||||||
setTab(mSnowmanView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::openSettings()
|
void MainWindow::openSettings()
|
||||||
|
@ -1025,9 +1011,7 @@ void MainWindow::checkUpdates()
|
||||||
|
|
||||||
void MainWindow::displayCallstack()
|
void MainWindow::displayCallstack()
|
||||||
{
|
{
|
||||||
mCallStackView->show();
|
showQWidgetTab(mCallStackView);
|
||||||
mCallStackView->setFocus();
|
|
||||||
setTab(mCallStackView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::donate()
|
void MainWindow::donate()
|
||||||
|
@ -1122,3 +1106,30 @@ void MainWindow::canClose()
|
||||||
bCanClose = true;
|
bCanClose = true;
|
||||||
close();
|
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)();
|
||||||
|
}
|
||||||
|
|
|
@ -104,6 +104,10 @@ public slots:
|
||||||
void changeCommandLine();
|
void changeCommandLine();
|
||||||
void decompileAt(int_t start, int_t end);
|
void decompileAt(int_t start, int_t end);
|
||||||
void canClose();
|
void canClose();
|
||||||
|
void addQWidgetTab(QWidget* qWidget);
|
||||||
|
void showQWidgetTab(QWidget* qWidget);
|
||||||
|
void closeQWidgetTab(QWidget* qWidget);
|
||||||
|
void executeOnGuiThread(void* cbGuiThread);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow* ui;
|
Ui::MainWindow* ui;
|
||||||
|
|
|
@ -579,7 +579,7 @@ void ScriptView::cmdExec()
|
||||||
|
|
||||||
void ScriptView::message(QString message)
|
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.setWindowIcon(QIcon(":/icons/images/information.png"));
|
||||||
msg.setParent(this, Qt::Dialog);
|
msg.setParent(this, Qt::Dialog);
|
||||||
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
Loading…
Reference in New Issue