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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<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>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
|
@ -139,7 +139,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<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>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <vector>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#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"
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -106,3 +60,93 @@ 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<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
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
"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()
|
||||
{
|
||||
|
@ -867,3 +871,23 @@ SCRIPT_EXPORT bool Script::Register::SetR15B(unsigned char value)
|
|||
return Set(R15B, value);
|
||||
}
|
||||
#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,
|
||||
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
|
||||
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
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()
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
const uint Address();
|
||||
const cs_x86 & x86();
|
||||
bool IsFilling();
|
||||
bool IsLoop();
|
||||
x86_insn GetId();
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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<FunctionInfo> _functions;
|
||||
Capstone _cp;
|
||||
|
||||
void SortCleanup();
|
||||
void PopulateReferences();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
bool MemFreeRemote(uint Address);
|
|
@ -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)
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
<ClCompile Include="commandparser.cpp" />
|
||||
<ClCompile Include="comment.cpp" />
|
||||
<ClCompile Include="console.cpp" />
|
||||
<ClCompile Include="controlflowanalysis.cpp" />
|
||||
<ClCompile Include="dbghelp_safe.cpp" />
|
||||
<ClCompile Include="debugger.cpp" />
|
||||
<ClCompile Include="debugger_commands.cpp" />
|
||||
|
@ -72,12 +73,15 @@
|
|||
<ClCompile Include="_dbgfunctions.cpp" />
|
||||
<ClCompile Include="_global.cpp" />
|
||||
<ClCompile Include="_plugins.cpp" />
|
||||
<ClCompile Include="_scriptapi_assembler.cpp" />
|
||||
<ClCompile Include="_scriptapi_debug.cpp" />
|
||||
<ClCompile Include="_scriptapi_gui.cpp" />
|
||||
<ClCompile Include="_scriptapi_misc.cpp" />
|
||||
<ClCompile Include="_scriptapi_pattern.cpp" />
|
||||
<ClCompile Include="_scriptapi_memory.cpp" />
|
||||
<ClCompile Include="_scriptapi_module.cpp" />
|
||||
<ClCompile Include="_scriptapi_register.cpp" />
|
||||
<ClCompile Include="_scriptapi_stack.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="addrinfo.h" />
|
||||
|
@ -103,6 +107,7 @@
|
|||
<ClInclude Include="commandparser.h" />
|
||||
<ClInclude Include="comment.h" />
|
||||
<ClInclude Include="console.h" />
|
||||
<ClInclude Include="controlflowanalysis.h" />
|
||||
<ClInclude Include="dbghelp\dbghelp.h" />
|
||||
<ClInclude Include="dbghelp_safe.h" />
|
||||
<ClInclude Include="debugger.h" />
|
||||
|
@ -187,12 +192,15 @@
|
|||
<ClInclude Include="_global.h" />
|
||||
<ClInclude Include="_plugins.h" />
|
||||
<ClInclude Include="_plugin_types.h" />
|
||||
<ClInclude Include="_scriptapi_assembler.h" />
|
||||
<ClInclude Include="_scriptapi_debug.h" />
|
||||
<ClInclude Include="_scriptapi_gui.h" />
|
||||
<ClInclude Include="_scriptapi_misc.h" />
|
||||
<ClInclude Include="_scriptapi_pattern.h" />
|
||||
<ClInclude Include="_scriptapi_memory.h" />
|
||||
<ClInclude Include="_scriptapi_module.h" />
|
||||
<ClInclude Include="_scriptapi_register.h" />
|
||||
<ClInclude Include="_scriptapi_stack.h" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E6548308-401E-3A8A-5819-905DB90522A6}</ProjectGuid>
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
|
@ -160,7 +160,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <agents.h>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QMutex>
|
||||
#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;
|
||||
|
|
|
@ -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)();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;X64_DBG_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
|
|
Loading…
Reference in New Issue