mirror of https://github.com/x64dbg/TitanEngine
Merge owner updates
This commit is contained in:
commit
4bf9318b59
|
|
@ -43,11 +43,8 @@ CRITICAL_SECTION engineStepActiveCr;
|
|||
// Workaround for a bug in the kernel with x64 emulation on ARM
|
||||
DWORD ContextControlFlags = []
|
||||
{
|
||||
// CONTEXT_CONTROL alone reads/writes only the control registers. When the
|
||||
// debugger (x64) cross-debugs a 32-bit target under WoW64, a SetThreadContext
|
||||
// issued with plain CONTEXT_CONTROL clobbers the debug registers the user
|
||||
// armed via hbreak (DR0..DR7) — Windows writes back the whole flagged set.
|
||||
// Include CONTEXT_DEBUG_REGISTERS so breakpoint steps never erase them.
|
||||
// Preserve hardware-breakpoint state whenever a control-context update is
|
||||
// written back. This is especially important across WoW64 mode switches.
|
||||
DWORD flags = CONTEXT_CONTROL | CONTEXT_DEBUG_REGISTERS;
|
||||
typedef BOOL(WINAPI * type_IsWow64Process2)(HANDLE, USHORT*, USHORT*);
|
||||
auto p_IsWow64Process2 = (type_IsWow64Process2)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process2");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
#include "stdafx.h"
|
||||
#include "definitions.h"
|
||||
#include "Global.Engine.Context.h"
|
||||
#include "Global.Debugger.h"
|
||||
#include "Global.Engine.h"
|
||||
#include "Global.Handle.h"
|
||||
|
||||
#ifdef _WIN64
|
||||
//https://stackoverflow.com/a/869597/1806760
|
||||
|
|
@ -134,6 +137,51 @@ PGETXSTATEFEATURESMASK _GetXStateFeaturesMask = NULL;
|
|||
LOCATEXSTATEFEATURE _LocateXStateFeature = NULL;
|
||||
SETXSTATEFEATURESMASK _SetXStateFeaturesMask = NULL;
|
||||
|
||||
EngineContextMode EngineGetThreadContextMode(HANDLE hThread)
|
||||
{
|
||||
#ifndef _WIN64
|
||||
(void)hThread;
|
||||
return EngineContextMode::X86;
|
||||
#else
|
||||
if(hThread != NULL)
|
||||
{
|
||||
CONTEXT context = {};
|
||||
context.ContextFlags = CONTEXT_CONTROL;
|
||||
if(GetThreadContext(hThread, &context))
|
||||
{
|
||||
// Windows uses selector 0x23 for 32-bit compatibility mode and
|
||||
// selector 0x33 for 64-bit user mode. Check every time because a
|
||||
// WoW64 thread can transition between the two modes.
|
||||
if(context.SegCs == 0x23)
|
||||
return EngineContextMode::X86;
|
||||
if(context.SegCs == 0x33)
|
||||
return EngineContextMode::X64;
|
||||
}
|
||||
}
|
||||
return EngineContextMode::X64;
|
||||
#endif
|
||||
}
|
||||
|
||||
EngineContextMode EngineGetCurrentContextMode()
|
||||
{
|
||||
#ifndef _WIN64
|
||||
return EngineContextMode::X86;
|
||||
#else
|
||||
HANDLE hThread = EngineOpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, false, DBGEvent.dwThreadId);
|
||||
if(hThread == NULL)
|
||||
return EngineContextMode::X64;
|
||||
|
||||
auto mode = EngineGetThreadContextMode(hThread);
|
||||
EngineCloseHandle(hThread);
|
||||
return mode;
|
||||
#endif
|
||||
}
|
||||
|
||||
SIZE_T EngineGetContextPointerSize(EngineContextMode mode)
|
||||
{
|
||||
return mode == EngineContextMode::X86 ? sizeof(DWORD) : sizeof(DWORD64);
|
||||
}
|
||||
|
||||
bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool AVX_PRIORITY)
|
||||
{
|
||||
CONTEXT DBGContext;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,19 @@ extern PGETXSTATEFEATURESMASK _GetXStateFeaturesMask;
|
|||
extern LOCATEXSTATEFEATURE _LocateXStateFeature;
|
||||
extern SETXSTATEFEATURESMASK _SetXStateFeaturesMask;
|
||||
|
||||
enum class EngineContextMode
|
||||
{
|
||||
X86,
|
||||
X64,
|
||||
};
|
||||
|
||||
// Determine the mode in which a thread is currently executing. A WoW64 thread
|
||||
// can switch between 32-bit and 64-bit code, so this deliberately uses CS from
|
||||
// the live thread context instead of the process image architecture.
|
||||
EngineContextMode EngineGetThreadContextMode(HANDLE hThread);
|
||||
EngineContextMode EngineGetCurrentContextMode();
|
||||
SIZE_T EngineGetContextPointerSize(EngineContextMode mode);
|
||||
|
||||
bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool AVX_PRIORITY);
|
||||
bool _GetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool avx);
|
||||
bool InitXState(void);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "Global.Threader.h"
|
||||
#include "Global.Librarian.h"
|
||||
#include "Global.Engine.h"
|
||||
#include "Global.Engine.Context.h"
|
||||
|
||||
__declspec(dllexport) void TITCALL ForceClose()
|
||||
{
|
||||
|
|
@ -43,14 +44,15 @@ __declspec(dllexport) void TITCALL StepInto(LPVOID StepCallBack)
|
|||
if(engineStepThreads.find(DBGEvent.dwThreadId) == engineStepThreads.end())
|
||||
{
|
||||
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
|
||||
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = (char*)EngineStaticDisassembleEx(ueCurrentPosition, (LPVOID)instr, is32Bit);
|
||||
if(strstr(DisassembledString, "PUSHF"))
|
||||
StepOver(StepCallBack);
|
||||
else if(strstr(DisassembledString, "POP SS") || strstr(DisassembledString, "MOV SS")) //prevent the 'PUSH SS', 'POP SS' step trick
|
||||
{
|
||||
ueCurrentPosition += StaticLengthDisassemble((void*)instr);
|
||||
ueCurrentPosition += EngineStaticLengthDisassemble((void*)instr, is32Bit);
|
||||
SetBPX(ueCurrentPosition, UE_BREAKPOINT_TYPE_INT3 + UE_SINGLESHOOT, StepCallBack);
|
||||
}
|
||||
else
|
||||
|
|
@ -71,12 +73,13 @@ __declspec(dllexport) void TITCALL StepInto(LPVOID StepCallBack)
|
|||
__declspec(dllexport) void TITCALL StepOver(LPVOID StepCallBack)
|
||||
{
|
||||
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
|
||||
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = (char*)EngineStaticDisassembleEx(ueCurrentPosition, (LPVOID)instr, is32Bit);
|
||||
if(strstr(DisassembledString, "CALL") || strstr(DisassembledString, "REP") || strstr(DisassembledString, "PUSHF"))
|
||||
{
|
||||
ueCurrentPosition += StaticLengthDisassemble((void*)instr);
|
||||
ueCurrentPosition += EngineStaticLengthDisassemble((void*)instr, is32Bit);
|
||||
SetBPX(ueCurrentPosition, UE_BREAKPOINT_TYPE_INT3 + UE_SINGLESHOOT, StepCallBack);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "Global.Threader.h"
|
||||
#include "Global.Librarian.h"
|
||||
#include "Global.TLS.h"
|
||||
#include "Global.Engine.Context.h"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
|
|
@ -14,6 +15,25 @@
|
|||
#define UE_MODULEx86 0x2000;
|
||||
#define UE_MODULEx64 0x2000;
|
||||
|
||||
static char* DisassembleCurrentInstruction(ULONG_PTR address, void* data)
|
||||
{
|
||||
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
|
||||
return (char*)EngineStaticDisassembleEx(address, data, is32Bit);
|
||||
}
|
||||
|
||||
static void ClearTrapFlagFromStack()
|
||||
{
|
||||
auto mode = EngineGetCurrentContextMode();
|
||||
SIZE_T pointerSize = EngineGetContextPointerSize(mode);
|
||||
void* csp = (void*)GetContextData(UE_CSP);
|
||||
DWORD64 data = 0;
|
||||
if(ReadProcessMemory(dbgProcessInformation.hProcess, csp, &data, pointerSize, nullptr))
|
||||
{
|
||||
data &= ~DWORD64(UE_TRAP_FLAG);
|
||||
WriteProcessMemory(dbgProcessInformation.hProcess, csp, &data, pointerSize, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void engineStep()
|
||||
{
|
||||
EnterCriticalSection(&engineStepActiveCr);
|
||||
|
|
@ -645,7 +665,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
|||
ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress;
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = DisassembleCurrentInstruction(ueCurrentPosition, (LPVOID)instr);
|
||||
if(strstr(DisassembledString, "PUSHF"))
|
||||
PushfBPX = true;
|
||||
}
|
||||
|
|
@ -755,11 +775,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
|||
if(PushfBPX) //remove trap flag from stack
|
||||
{
|
||||
PushfBPX = false;
|
||||
void* csp = (void*)GetContextData(UE_CSP);
|
||||
ULONG_PTR data = 0;
|
||||
ReadProcessMemory(dbgProcessInformation.hProcess, csp, &data, sizeof(ULONG_PTR), 0);
|
||||
data &= ~UE_TRAP_FLAG;
|
||||
WriteProcessMemory(dbgProcessInformation.hProcess, csp, &data, sizeof(ULONG_PTR), 0);
|
||||
ClearTrapFlagFromStack();
|
||||
}
|
||||
if(ResetBPX) //restore 'normal' breakpoint
|
||||
{
|
||||
|
|
@ -947,7 +963,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
|||
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = DisassembleCurrentInstruction(ueCurrentPosition, (LPVOID)instr);
|
||||
if(strstr(DisassembledString, "PUSHF"))
|
||||
PushfBPX = true;
|
||||
}
|
||||
|
|
@ -1186,7 +1202,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
|||
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), nullptr);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = DisassembleCurrentInstruction(ueCurrentPosition, (LPVOID)instr);
|
||||
if(strstr(DisassembledString, "PUSHF"))
|
||||
PushfBPX = true;
|
||||
}
|
||||
|
|
@ -1269,7 +1285,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
|
|||
ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress;
|
||||
unsigned char instr[16];
|
||||
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0);
|
||||
char* DisassembledString = (char*)StaticDisassembleEx(ueCurrentPosition, (LPVOID)instr);
|
||||
char* DisassembledString = DisassembleCurrentInstruction(ueCurrentPosition, (LPVOID)instr);
|
||||
if(strstr(DisassembledString, "PUSHF"))
|
||||
PushfBPX = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "definitions.h"
|
||||
#include "Global.Debugger.h"
|
||||
#include "Global.Engine.Context.h"
|
||||
|
||||
static char szParameterString[512];
|
||||
|
||||
|
|
@ -51,6 +52,8 @@ __declspec(dllexport) ULONG_PTR TITCALL GetFunctionParameter(HANDLE hProcess, DW
|
|||
DWORD StackReadSize = 512;
|
||||
DWORD StringReadSize = 512;
|
||||
bool ValueIsPointer = false;
|
||||
auto mode = EngineGetCurrentContextMode();
|
||||
SIZE_T pointerSize = EngineGetContextPointerSize(mode);
|
||||
|
||||
if(ParameterType == UE_PARAMETER_BYTE)
|
||||
{
|
||||
|
|
@ -94,81 +97,55 @@ __declspec(dllexport) ULONG_PTR TITCALL GetFunctionParameter(HANDLE hProcess, DW
|
|||
{
|
||||
StackSecondReadSize = 0;
|
||||
}
|
||||
StackReadSize = sizeof(ULONG_PTR);
|
||||
StackReadSize = (DWORD)pointerSize;
|
||||
}
|
||||
if(FunctionType >= UE_FUNCTION_STDCALL && FunctionType <= UE_FUNCTION_CCALL_CALL && FunctionType != UE_FUNCTION_FASTCALL_RET)
|
||||
if(FunctionType >= UE_FUNCTION_STDCALL && FunctionType <= UE_FUNCTION_FASTCALL_CALL && FunctionType != UE_FUNCTION_FASTCALL_RET)
|
||||
{
|
||||
StackReadAddress = (ULONG_PTR)GetContextData(UE_CSP);
|
||||
if(FunctionType != UE_FUNCTION_FASTCALL_CALL)
|
||||
{
|
||||
StackReadAddress = StackReadAddress + (ParameterNumber * sizeof(ULONG_PTR));
|
||||
StackReadAddress = StackReadAddress + (ParameterNumber * pointerSize);
|
||||
if(FunctionType >= UE_FUNCTION_STDCALL_CALL)
|
||||
{
|
||||
StackReadAddress = StackReadAddress - sizeof(ULONG_PTR);
|
||||
StackReadAddress = StackReadAddress - pointerSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ParameterNumber <= 4)
|
||||
DWORD registerCount = mode == EngineContextMode::X86 ? 2 : 4;
|
||||
if(ParameterNumber <= registerCount)
|
||||
{
|
||||
static const DWORD x86Registers[] = { UE_ECX, UE_EDX };
|
||||
static const DWORD x64Registers[] = { UE_RCX, UE_RDX, UE_R8, UE_R9 };
|
||||
DWORD registerIndex = mode == EngineContextMode::X86
|
||||
? x86Registers[ParameterNumber - 1]
|
||||
: x64Registers[ParameterNumber - 1];
|
||||
ULONG_PTR registerValue = (ULONG_PTR)GetContextData(registerIndex);
|
||||
if(!ValueIsPointer)
|
||||
{
|
||||
if(ParameterNumber == 1)
|
||||
{
|
||||
return((ULONG_PTR)GetContextData(UE_RCX));
|
||||
}
|
||||
else if(ParameterNumber == 2)
|
||||
{
|
||||
return((ULONG_PTR)GetContextData(UE_RDX));
|
||||
}
|
||||
else if(ParameterNumber == 3)
|
||||
{
|
||||
return((ULONG_PTR)GetContextData(UE_R8));
|
||||
}
|
||||
else if(ParameterNumber == 4)
|
||||
{
|
||||
return((ULONG_PTR)GetContextData(UE_R9));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ParameterNumber == 1)
|
||||
{
|
||||
StackReadAddress = (ULONG_PTR)GetContextData(UE_RCX);
|
||||
}
|
||||
else if(ParameterNumber == 2)
|
||||
{
|
||||
StackReadAddress = (ULONG_PTR)GetContextData(UE_RDX);
|
||||
}
|
||||
else if(ParameterNumber == 3)
|
||||
{
|
||||
StackReadAddress = (ULONG_PTR)GetContextData(UE_R8);
|
||||
}
|
||||
else if(ParameterNumber == 4)
|
||||
{
|
||||
StackReadAddress = (ULONG_PTR)GetContextData(UE_R9);
|
||||
}
|
||||
}
|
||||
return registerValue;
|
||||
StackReadAddress = registerValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
StackReadAddress = StackReadAddress + 0x20 + ((ParameterNumber - 4) * sizeof(ULONG_PTR)) - sizeof(ULONG_PTR);
|
||||
SIZE_T shadowSpace = mode == EngineContextMode::X86 ? 0 : 0x20;
|
||||
StackReadAddress += shadowSpace + ((ParameterNumber - registerCount) * pointerSize) - pointerSize;
|
||||
}
|
||||
}
|
||||
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, sizeof(ULONG_PTR), &ueNumberOfBytesRW))
|
||||
SIZE_T initialReadSize = ValueIsPointer ? pointerSize : (StackReadSize < sizeof(StackReadBuffer) ? StackReadSize : sizeof(StackReadBuffer));
|
||||
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, initialReadSize, &ueNumberOfBytesRW))
|
||||
{
|
||||
if(!ValueIsPointer)
|
||||
{
|
||||
RtlMoveMemory((LPVOID)((ULONG_PTR)&StackFinalBuffer + sizeof(ULONG_PTR) - StackReadSize), (LPVOID)((ULONG_PTR)&StackReadBuffer + sizeof(ULONG_PTR) - StackReadSize), StackReadSize);
|
||||
RtlMoveMemory(&StackFinalBuffer, &StackReadBuffer, StackReadSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
StackReadAddress = StackReadBuffer;
|
||||
if(StackSecondReadSize > NULL)
|
||||
{
|
||||
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, sizeof(ULONG_PTR), &ueNumberOfBytesRW))
|
||||
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, StackSecondReadSize, &ueNumberOfBytesRW))
|
||||
{
|
||||
RtlMoveMemory((LPVOID)((ULONG_PTR)&StackFinalBuffer + sizeof(ULONG_PTR) - StackSecondReadSize), (LPVOID)((ULONG_PTR)&StackReadBuffer + sizeof(ULONG_PTR) - StackSecondReadSize), StackSecondReadSize);
|
||||
RtlMoveMemory(&StackFinalBuffer, &StackReadBuffer, StackSecondReadSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -218,6 +195,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
DWORD CurrentInstructionSize;
|
||||
int ReadMemData = NULL;
|
||||
BYTE ReadByteData = NULL;
|
||||
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
|
||||
|
||||
if(hProcess != NULL)
|
||||
{
|
||||
|
|
@ -227,7 +205,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
if(ReadProcessMemory(hProcess, (LPVOID)InstructionAddress, ReadMemory, MAXIMUM_INSTRUCTION_SIZE, &ueNumberOfBytesRead))
|
||||
{
|
||||
CompareMemory = (PMEMORY_CMP_HANDLER)ReadMemory;
|
||||
CurrentInstructionSize = StaticLengthDisassemble(ReadMemory);
|
||||
CurrentInstructionSize = EngineStaticLengthDisassemble(ReadMemory, is32Bit);
|
||||
if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5)
|
||||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 1), 4);
|
||||
|
|
@ -305,7 +283,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 2), 4);
|
||||
TargetedAddress = ReadMemData;
|
||||
if(sizeof(HANDLE) == 8)
|
||||
if(!is32Bit)
|
||||
{
|
||||
TargetedAddress = TargetedAddress + InstructionAddress;
|
||||
}
|
||||
|
|
@ -314,7 +292,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 2), 4);
|
||||
TargetedAddress = ReadMemData;
|
||||
if(sizeof(HANDLE) == 8)
|
||||
if(!is32Bit)
|
||||
{
|
||||
TargetedAddress = TargetedAddress + InstructionAddress;
|
||||
}
|
||||
|
|
@ -362,7 +340,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
else
|
||||
{
|
||||
CompareMemory = (PMEMORY_CMP_HANDLER)InstructionAddress;
|
||||
CurrentInstructionSize = StaticLengthDisassemble((LPVOID)InstructionAddress);
|
||||
CurrentInstructionSize = EngineStaticLengthDisassemble((LPVOID)InstructionAddress, is32Bit);
|
||||
if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5)
|
||||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 1), 4);
|
||||
|
|
@ -440,7 +418,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 2), 4);
|
||||
TargetedAddress = ReadMemData;
|
||||
if(sizeof(HANDLE) == 8)
|
||||
if(!is32Bit)
|
||||
{
|
||||
TargetedAddress = TargetedAddress + InstructionAddress;
|
||||
}
|
||||
|
|
@ -449,7 +427,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
|
|||
{
|
||||
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 2), 4);
|
||||
TargetedAddress = ReadMemData;
|
||||
if(sizeof(HANDLE) == 8)
|
||||
if(!is32Bit)
|
||||
{
|
||||
TargetedAddress = TargetedAddress + InstructionAddress;
|
||||
}
|
||||
|
|
@ -530,7 +508,8 @@ __declspec(dllexport) bool TITCALL IsJumpGoingToExecuteEx(HANDLE hProcess, HANDL
|
|||
{
|
||||
ThreadEflags = (DWORD)RegFlags;
|
||||
}
|
||||
DisassembledString = (char*)DisassembleEx(hProcess, (LPVOID)ThreadCIP, true);
|
||||
auto mode = hThread != NULL ? EngineGetThreadContextMode(hThread) : EngineGetCurrentContextMode();
|
||||
DisassembledString = (char*)EngineDisassembleEx(hProcess, (LPVOID)ThreadCIP, true, mode == EngineContextMode::X86);
|
||||
if(DisassembledString != NULL)
|
||||
{
|
||||
if(ThreadEflags & (1 << 0))
|
||||
|
|
|
|||
|
|
@ -43,15 +43,12 @@ __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandL
|
|||
}
|
||||
}
|
||||
|
||||
static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
||||
template<typename NtHeaders>
|
||||
static bool ProcessRelocationsForArchitecture(char* imageCopy, NtHeaders* pnth, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
||||
{
|
||||
auto pnth = RtlImageNtHeader(imageCopy);
|
||||
if(pnth == nullptr)
|
||||
return false;
|
||||
|
||||
// Put the new base in the header
|
||||
oldImageBase = pnth->OptionalHeader.ImageBase;
|
||||
pnth->OptionalHeader.ImageBase = newImageBase;
|
||||
// Put the new base in the header using the image's pointer width.
|
||||
oldImageBase = ULONG_PTR(pnth->OptionalHeader.ImageBase);
|
||||
pnth->OptionalHeader.ImageBase = decltype(pnth->OptionalHeader.ImageBase)(newImageBase);
|
||||
|
||||
// Nothing to do if relocations are stripped
|
||||
if(pnth->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
|
||||
|
|
@ -63,7 +60,7 @@ static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR n
|
|||
return true;
|
||||
|
||||
// Process the relocations
|
||||
auto delta = newImageBase - oldImageBase;
|
||||
auto delta = LONG_PTR(newImageBase) - LONG_PTR(oldImageBase);
|
||||
auto relocationItr = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)imageCopy + relocDir.VirtualAddress);
|
||||
auto relocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)relocationItr + relocDir.Size);
|
||||
|
||||
|
|
@ -80,6 +77,20 @@ static bool ProcessRelocations(char* imageCopy, ULONG_PTR imageSize, ULONG_PTR n
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool ProcessRelocations(char* imageCopy, ULONG_PTR newImageBase, ULONG_PTR & oldImageBase)
|
||||
{
|
||||
auto pnth = RtlImageNtHeader(imageCopy);
|
||||
if(pnth == nullptr)
|
||||
return false;
|
||||
|
||||
auto magic = ((PIMAGE_NT_HEADERS32)pnth)->OptionalHeader.Magic;
|
||||
if(magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
return ProcessRelocationsForArchitecture(imageCopy, (PIMAGE_NT_HEADERS32)pnth, newImageBase, oldImageBase);
|
||||
if(magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
|
||||
return ProcessRelocationsForArchitecture(imageCopy, (PIMAGE_NT_HEADERS64)pnth, newImageBase, oldImageBase);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
|
||||
{
|
||||
constexpr auto pageSize = 0x1000;
|
||||
|
|
@ -100,7 +111,7 @@ static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
|
|||
|
||||
// perform the actual relocations
|
||||
ULONG_PTR oldImageBase = 0;
|
||||
auto success = ProcessRelocations(imageCopy, imageSize, (ULONG_PTR)imageBase, oldImageBase);
|
||||
auto success = ProcessRelocations(imageCopy, (ULONG_PTR)imageBase, oldImageBase);
|
||||
|
||||
// write back the pages
|
||||
auto memWrite = [hProcess](PVOID ptr, LPCVOID data, SIZE_T size)
|
||||
|
|
@ -165,28 +176,45 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
|
|||
auto hMapping = CreateFileMappingW(hFile, nullptr, SEC_IMAGE | PAGE_READONLY, 0, 0, nullptr);
|
||||
if(hMapping)
|
||||
{
|
||||
CONTEXT ctx;
|
||||
CONTEXT ctx = {};
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
if(GetThreadContext(pi.hThread, &ctx))
|
||||
{
|
||||
PVOID imageBase;
|
||||
// TODO: support wow64 processes
|
||||
bool isWow64 = false;
|
||||
ULONG_PTR pebAddress = 0;
|
||||
SIZE_T imageBaseOffset = 0;
|
||||
SIZE_T imageBaseSize = 0;
|
||||
#ifdef _WIN64
|
||||
auto & pebRegister = ctx.Rdx;
|
||||
auto & entryPointRegister = ctx.Rcx;
|
||||
#else
|
||||
auto & pebRegister = ctx.Ebx;
|
||||
auto & entryPointRegister = ctx.Eax;
|
||||
#endif // _WIN64
|
||||
if(ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr))
|
||||
ULONG returnLength = 0;
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessWow64Information, &pebAddress, sizeof(pebAddress), &returnLength)) && pebAddress != 0)
|
||||
{
|
||||
if(ULONG_PTR(imageBase) == DebugModuleImageBase)
|
||||
isWow64 = true;
|
||||
imageBaseOffset = offsetof(PEB32, ImageBaseAddress);
|
||||
imageBaseSize = sizeof(DWORD);
|
||||
}
|
||||
else
|
||||
{
|
||||
pebAddress = ctx.Rdx;
|
||||
imageBaseOffset = offsetof(PEB64, ImageBaseAddress);
|
||||
imageBaseSize = sizeof(DWORD64);
|
||||
}
|
||||
#else
|
||||
pebAddress = ctx.Ebx;
|
||||
imageBaseOffset = offsetof(PEB32, ImageBaseAddress);
|
||||
imageBaseSize = sizeof(DWORD);
|
||||
#endif // _WIN64
|
||||
|
||||
ULONG_PTR imageBaseValue = 0;
|
||||
if(ReadProcessMemory(pi.hProcess, (char*)pebAddress + imageBaseOffset, &imageBaseValue, imageBaseSize, nullptr))
|
||||
{
|
||||
if(imageBaseValue == DebugModuleImageBase)
|
||||
{
|
||||
// Already at the right base
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto imageBase = PVOID(imageBaseValue);
|
||||
auto status = NtUnmapViewOfSection(pi.hProcess, imageBase);
|
||||
if(status == STATUS_SUCCESS)
|
||||
{
|
||||
|
|
@ -201,22 +229,59 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
|
|||
}
|
||||
if(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE)
|
||||
{
|
||||
auto pebOk = WriteProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr);
|
||||
imageBaseValue = ULONG_PTR(imageBase);
|
||||
auto pebOk = WriteProcessMemory(pi.hProcess, (char*)pebAddress + imageBaseOffset, &imageBaseValue, imageBaseSize, nullptr);
|
||||
#ifdef _WIN64
|
||||
if(pebOk && isWow64)
|
||||
{
|
||||
PROCESS_BASIC_INFORMATION processInfo = {};
|
||||
if(NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessBasicInformation, &processInfo, sizeof(processInfo), &returnLength)))
|
||||
{
|
||||
DWORD64 imageBase64 = imageBaseValue;
|
||||
pebOk = WriteProcessMemory(pi.hProcess, (char*)processInfo.PebBaseAddress + offsetof(PEB64, ImageBaseAddress), &imageBase64, sizeof(imageBase64), nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
pebOk = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(pebOk && IsThisProcessWow64())
|
||||
{
|
||||
auto peb64 = GetPEBLocation64(pi.hProcess);
|
||||
DWORD64 imageBase64 = imageBaseValue;
|
||||
pebOk = peb64 != nullptr && WriteProcessMemory(pi.hProcess, (char*)peb64 + offsetof(PEB64, ImageBaseAddress), &imageBase64, sizeof(imageBase64), nullptr);
|
||||
}
|
||||
#endif // _WIN64
|
||||
auto relocatedOk = RelocateImage(pi.hProcess, imageBase, viewSize);
|
||||
if(pebOk && relocatedOk)
|
||||
{
|
||||
auto expectedBase = DebugModuleImageBase == ULONG_PTR(imageBase);
|
||||
DebugModuleImageBase = ULONG_PTR(imageBase);
|
||||
entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint;
|
||||
if(SetThreadContext(pi.hThread, &ctx))
|
||||
auto expectedBase = DebugModuleImageBase == imageBaseValue;
|
||||
DebugModuleImageBase = imageBaseValue;
|
||||
auto entryPoint = DebugModuleImageBase + DebugModuleEntryPoint;
|
||||
bool contextOk = false;
|
||||
#ifdef _WIN64
|
||||
if(isWow64)
|
||||
{
|
||||
success = expectedBase;
|
||||
#ifndef _WIN64
|
||||
// For Wow64 processes, also adjust the 64-bit PEB
|
||||
if(IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr))
|
||||
success = false;
|
||||
#endif // _WIN64
|
||||
WOW64_CONTEXT ctx32 = {};
|
||||
ctx32.ContextFlags = WOW64_CONTEXT_INTEGER;
|
||||
if(Wow64GetThreadContext(pi.hThread, &ctx32))
|
||||
{
|
||||
ctx32.Eax = DWORD(entryPoint);
|
||||
contextOk = Wow64SetThreadContext(pi.hThread, &ctx32) != FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.Rcx = entryPoint;
|
||||
contextOk = SetThreadContext(pi.hThread, &ctx) != FALSE;
|
||||
}
|
||||
#else
|
||||
ctx.Eax = DWORD(entryPoint);
|
||||
contextOk = SetThreadContext(pi.hThread, &ctx) != FALSE;
|
||||
#endif // _WIN64
|
||||
if(contextOk)
|
||||
success = expectedBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,31 @@
|
|||
#include "stdafx.h"
|
||||
#include "definitions.h"
|
||||
#include "Global.Debugger.h"
|
||||
#include "Global.Engine.Context.h"
|
||||
#include "distorm.h"
|
||||
|
||||
static char engineDisassembledInstruction[128];
|
||||
|
||||
#if !defined(_WIN64)
|
||||
_DecodeType DecodingType = Decode32Bits;
|
||||
static bool DefaultIs32Bit()
|
||||
{
|
||||
#ifndef _WIN64
|
||||
return true;
|
||||
#else
|
||||
_DecodeType DecodingType = Decode64Bits;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static _DecodeType GetDecodingType(bool Is32Bit)
|
||||
{
|
||||
return Is32Bit ? Decode32Bits : Decode64Bits;
|
||||
}
|
||||
|
||||
static bool GetProcessMode(HANDLE hProcess)
|
||||
{
|
||||
if(hProcess != NULL && hProcess == dbgProcessInformation.hProcess && DBGEvent.dwThreadId != 0)
|
||||
return EngineGetCurrentContextMode() == EngineContextMode::X86;
|
||||
return DefaultIs32Bit();
|
||||
}
|
||||
|
||||
|
||||
SIZE_T IsBadReadPtrRemote(HANDLE hProcess, const VOID* lp, SIZE_T length)
|
||||
|
|
@ -62,7 +78,7 @@ SIZE_T IsBadReadPtrRemote(HANDLE hProcess, const VOID* lp, SIZE_T length)
|
|||
return 0;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress)
|
||||
void* EngineStaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress, bool Is32Bit)
|
||||
{
|
||||
_DecodedInst engineDecodedInstructions[1];
|
||||
unsigned int DecodedInstructionsCount = 0;
|
||||
|
|
@ -70,7 +86,7 @@ __declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart,
|
|||
int MaxDisassmSize = MAXIMUM_INSTRUCTION_SIZE; // (int)IsBadReadPtrRemote(GetCurrentProcess(), DisassmAddress, MAXIMUM_INSTRUCTION_SIZE);
|
||||
if(MaxDisassmSize)
|
||||
{
|
||||
if(distorm_decode((ULONG_PTR)DisassmStart, (const unsigned char*)DisassmAddress, MaxDisassmSize, DecodingType, engineDecodedInstructions, _countof(engineDecodedInstructions), &DecodedInstructionsCount) != DECRES_INPUTERR)
|
||||
if(distorm_decode((ULONG_PTR)DisassmStart, (const unsigned char*)DisassmAddress, MaxDisassmSize, GetDecodingType(Is32Bit), engineDecodedInstructions, _countof(engineDecodedInstructions), &DecodedInstructionsCount) != DECRES_INPUTERR)
|
||||
{
|
||||
RtlZeroMemory(engineDisassembledInstruction, sizeof(engineDisassembledInstruction));
|
||||
|
||||
|
|
@ -87,12 +103,17 @@ __declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart,
|
|||
return 0;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress)
|
||||
{
|
||||
return EngineStaticDisassembleEx(DisassmStart, DisassmAddress, DefaultIs32Bit());
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL StaticDisassemble(LPVOID DisassmAddress)
|
||||
{
|
||||
return StaticDisassembleEx((ULONG_PTR)DisassmAddress, DisassmAddress);
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool ReturnInstructionType)
|
||||
void* EngineDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool ReturnInstructionType, bool Is32Bit)
|
||||
{
|
||||
_DecodedInst engineDecodedInstructions[1];
|
||||
unsigned int DecodedInstructionsCount = 0;
|
||||
|
|
@ -107,7 +128,7 @@ __declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID Disass
|
|||
BOOL rpm = MemoryReadSafe(hProcess, DisassmAddress, readBuffer, MaxDisassmSize, 0);
|
||||
if(rpm)
|
||||
{
|
||||
if(distorm_decode((ULONG_PTR)DisassmAddress, readBuffer, MaxDisassmSize, DecodingType, engineDecodedInstructions, _countof(engineDecodedInstructions), &DecodedInstructionsCount) != DECRES_INPUTERR)
|
||||
if(distorm_decode((ULONG_PTR)DisassmAddress, readBuffer, MaxDisassmSize, GetDecodingType(Is32Bit), engineDecodedInstructions, _countof(engineDecodedInstructions), &DecodedInstructionsCount) != DECRES_INPUTERR)
|
||||
{
|
||||
RtlZeroMemory(engineDisassembledInstruction, sizeof(engineDisassembledInstruction));
|
||||
|
||||
|
|
@ -130,17 +151,27 @@ __declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID Disass
|
|||
return 0;
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool ReturnInstructionType)
|
||||
{
|
||||
return EngineDisassembleEx(hProcess, DisassmAddress, ReturnInstructionType, GetProcessMode(hProcess));
|
||||
}
|
||||
|
||||
__declspec(dllexport) void* TITCALL Disassemble(LPVOID DisassmAddress)
|
||||
{
|
||||
return(DisassembleEx(dbgProcessInformation.hProcess, DisassmAddress, false));
|
||||
return DisassembleEx(dbgProcessInformation.hProcess, DisassmAddress, false);
|
||||
}
|
||||
|
||||
long EngineStaticLengthDisassemble(LPVOID DisassmAddress, bool Is32Bit)
|
||||
{
|
||||
return EngineLengthDisassembleEx(GetCurrentProcess(), DisassmAddress, Is32Bit);
|
||||
}
|
||||
|
||||
__declspec(dllexport) long TITCALL StaticLengthDisassemble(LPVOID DisassmAddress)
|
||||
{
|
||||
return LengthDisassembleEx(GetCurrentProcess(), DisassmAddress);
|
||||
return EngineStaticLengthDisassemble(DisassmAddress, DefaultIs32Bit());
|
||||
}
|
||||
|
||||
__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress)
|
||||
long EngineLengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool Is32Bit)
|
||||
{
|
||||
unsigned int DecodedInstructionsCount = 0;
|
||||
_CodeInfo decomposerCi = {0};
|
||||
|
|
@ -155,7 +186,7 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D
|
|||
{
|
||||
decomposerCi.code = readBuffer;
|
||||
decomposerCi.codeLen = MaxDisassmSize;
|
||||
decomposerCi.dt = DecodingType;
|
||||
decomposerCi.dt = GetDecodingType(Is32Bit);
|
||||
decomposerCi.codeOffset = (LONG_PTR)DisassmAddress;
|
||||
|
||||
if(distorm_decompose(&decomposerCi, decomposerResult, _countof(decomposerResult), &DecodedInstructionsCount) != DECRES_INPUTERR)
|
||||
|
|
@ -171,6 +202,11 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D
|
|||
return -1;
|
||||
}
|
||||
|
||||
__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress)
|
||||
{
|
||||
return EngineLengthDisassembleEx(hProcess, DisassmAddress, GetProcessMode(hProcess));
|
||||
}
|
||||
|
||||
__declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress)
|
||||
{
|
||||
return LengthDisassembleEx(dbgProcessInformation.hProcess, DisassmAddress);
|
||||
|
|
|
|||
|
|
@ -158,6 +158,14 @@ __declspec(dllexport) void* TITCALL Disassemble(LPVOID DisassmAddress);
|
|||
__declspec(dllexport) long TITCALL StaticLengthDisassemble(LPVOID DisassmAddress);
|
||||
__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress);
|
||||
__declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress);
|
||||
|
||||
// Internal variants used when the current thread mode is known. The exported
|
||||
// static APIs keep their historical build-architecture behavior.
|
||||
void* EngineStaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress, bool Is32Bit);
|
||||
void* EngineDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool ReturnInstructionType, bool Is32Bit);
|
||||
long EngineStaticLengthDisassemble(LPVOID DisassmAddress, bool Is32Bit);
|
||||
long EngineLengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress, bool Is32Bit);
|
||||
|
||||
__declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder);
|
||||
__declspec(dllexport) void* TITCALL InitDebugW(wchar_t* szFileName, wchar_t* szCommandLine, wchar_t* szCurrentFolder);
|
||||
__declspec(dllexport) void* TITCALL InitNativeDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder);
|
||||
|
|
|
|||
Loading…
Reference in New Issue