This commit is contained in:
Yemdust 2026-08-05 00:06:02 +02:00 committed by GitHub
commit dbb674d34f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 283 additions and 111 deletions

View File

@ -43,7 +43,9 @@ CRITICAL_SECTION engineStepActiveCr;
// Workaround for a bug in the kernel with x64 emulation on ARM // Workaround for a bug in the kernel with x64 emulation on ARM
DWORD ContextControlFlags = [] DWORD ContextControlFlags = []
{ {
DWORD flags = CONTEXT_CONTROL; // 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*); typedef BOOL(WINAPI * type_IsWow64Process2)(HANDLE, USHORT*, USHORT*);
auto p_IsWow64Process2 = (type_IsWow64Process2)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process2"); auto p_IsWow64Process2 = (type_IsWow64Process2)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "IsWow64Process2");
if(p_IsWow64Process2) if(p_IsWow64Process2)

View File

@ -1,6 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#include "definitions.h" #include "definitions.h"
#include "Global.Engine.Context.h" #include "Global.Engine.Context.h"
#include "Global.Debugger.h"
#include "Global.Engine.h"
#include "Global.Handle.h"
#ifdef _WIN64 #ifdef _WIN64
//https://stackoverflow.com/a/869597/1806760 //https://stackoverflow.com/a/869597/1806760
@ -134,6 +137,51 @@ PGETXSTATEFEATURESMASK _GetXStateFeaturesMask = NULL;
LOCATEXSTATEFEATURE _LocateXStateFeature = NULL; LOCATEXSTATEFEATURE _LocateXStateFeature = NULL;
SETXSTATEFEATURESMASK _SetXStateFeaturesMask = 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) bool _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool AVX_PRIORITY)
{ {
CONTEXT DBGContext; CONTEXT DBGContext;

View File

@ -24,6 +24,19 @@ extern PGETXSTATEFEATURESMASK _GetXStateFeaturesMask;
extern LOCATEXSTATEFEATURE _LocateXStateFeature; extern LOCATEXSTATEFEATURE _LocateXStateFeature;
extern SETXSTATEFEATURESMASK _SetXStateFeaturesMask; 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 _SetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool AVX_PRIORITY);
bool _GetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool avx); bool _GetFullContextDataEx(HANDLE hActiveThread, TITAN_ENGINE_CONTEXT_t* titcontext, bool avx);
bool InitXState(void); bool InitXState(void);

View File

@ -5,6 +5,7 @@
#include "Global.Threader.h" #include "Global.Threader.h"
#include "Global.Librarian.h" #include "Global.Librarian.h"
#include "Global.Engine.h" #include "Global.Engine.h"
#include "Global.Engine.Context.h"
__declspec(dllexport) void TITCALL ForceClose() __declspec(dllexport) void TITCALL ForceClose()
{ {
@ -43,14 +44,15 @@ __declspec(dllexport) void TITCALL StepInto(LPVOID StepCallBack)
if(engineStepThreads.find(DBGEvent.dwThreadId) == engineStepThreads.end()) if(engineStepThreads.find(DBGEvent.dwThreadId) == engineStepThreads.end())
{ {
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP); ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0); 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")) if(strstr(DisassembledString, "PUSHF"))
StepOver(StepCallBack); StepOver(StepCallBack);
else if(strstr(DisassembledString, "POP SS") || strstr(DisassembledString, "MOV SS")) //prevent the 'PUSH SS', 'POP SS' step trick 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); SetBPX(ueCurrentPosition, UE_BREAKPOINT_TYPE_INT3 + UE_SINGLESHOOT, StepCallBack);
} }
else else
@ -71,12 +73,13 @@ __declspec(dllexport) void TITCALL StepInto(LPVOID StepCallBack)
__declspec(dllexport) void TITCALL StepOver(LPVOID StepCallBack) __declspec(dllexport) void TITCALL StepOver(LPVOID StepCallBack)
{ {
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP); ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0); 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")) 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); SetBPX(ueCurrentPosition, UE_BREAKPOINT_TYPE_INT3 + UE_SINGLESHOOT, StepCallBack);
} }
else else

View File

@ -7,6 +7,7 @@
#include "Global.Threader.h" #include "Global.Threader.h"
#include "Global.Librarian.h" #include "Global.Librarian.h"
#include "Global.TLS.h" #include "Global.TLS.h"
#include "Global.Engine.Context.h"
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <functional> #include <functional>
@ -14,6 +15,25 @@
#define UE_MODULEx86 0x2000; #define UE_MODULEx86 0x2000;
#define UE_MODULEx64 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() static void engineStep()
{ {
EnterCriticalSection(&engineStepActiveCr); EnterCriticalSection(&engineStepActiveCr);
@ -591,6 +611,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
switch((LONG)DBGEvent.u.Exception.ExceptionRecord.ExceptionCode) switch((LONG)DBGEvent.u.Exception.ExceptionRecord.ExceptionCode)
{ {
case STATUS_BREAKPOINT: case STATUS_BREAKPOINT:
case STATUS_WX86_BREAKPOINT:
{ {
bool bFoundBreakPoint = false; bool bFoundBreakPoint = false;
BreakPointDetail FoundBreakPoint; BreakPointDetail FoundBreakPoint;
@ -644,7 +665,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress; ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress;
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0); 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")) if(strstr(DisassembledString, "PUSHF"))
PushfBPX = true; PushfBPX = true;
} }
@ -736,6 +757,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
break; break;
case STATUS_SINGLE_STEP: case STATUS_SINGLE_STEP:
case STATUS_WX86_SINGLE_STEP:
{ {
if(IsDbgReplyLaterSupported) if(IsDbgReplyLaterSupported)
{ {
@ -753,11 +775,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
if(PushfBPX) //remove trap flag from stack if(PushfBPX) //remove trap flag from stack
{ {
PushfBPX = false; PushfBPX = false;
void* csp = (void*)GetContextData(UE_CSP); ClearTrapFlagFromStack();
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);
} }
if(ResetBPX) //restore 'normal' breakpoint if(ResetBPX) //restore 'normal' breakpoint
{ {
@ -945,7 +963,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP); ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0); 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")) if(strstr(DisassembledString, "PUSHF"))
PushfBPX = true; PushfBPX = true;
} }
@ -1184,7 +1202,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP); ULONG_PTR ueCurrentPosition = GetContextData(UE_CIP);
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), nullptr); 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")) if(strstr(DisassembledString, "PUSHF"))
PushfBPX = true; PushfBPX = true;
} }
@ -1270,7 +1288,7 @@ __declspec(dllexport) void TITCALL DebugLoop()
ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress; ULONG_PTR ueCurrentPosition = FoundBreakPoint.BreakPointAddress;
unsigned char instr[16]; unsigned char instr[16];
MemoryReadSafe(dbgProcessInformation.hProcess, (void*)ueCurrentPosition, instr, sizeof(instr), 0); 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")) if(strstr(DisassembledString, "PUSHF"))
PushfBPX = true; PushfBPX = true;
} }

View File

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "definitions.h" #include "definitions.h"
#include "Global.Debugger.h" #include "Global.Debugger.h"
#include "Global.Engine.Context.h"
static char szParameterString[512]; static char szParameterString[512];
@ -51,6 +52,8 @@ __declspec(dllexport) ULONG_PTR TITCALL GetFunctionParameter(HANDLE hProcess, DW
DWORD StackReadSize = 512; DWORD StackReadSize = 512;
DWORD StringReadSize = 512; DWORD StringReadSize = 512;
bool ValueIsPointer = false; bool ValueIsPointer = false;
auto mode = EngineGetCurrentContextMode();
SIZE_T pointerSize = EngineGetContextPointerSize(mode);
if(ParameterType == UE_PARAMETER_BYTE) if(ParameterType == UE_PARAMETER_BYTE)
{ {
@ -94,81 +97,55 @@ __declspec(dllexport) ULONG_PTR TITCALL GetFunctionParameter(HANDLE hProcess, DW
{ {
StackSecondReadSize = 0; 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); StackReadAddress = (ULONG_PTR)GetContextData(UE_CSP);
if(FunctionType != UE_FUNCTION_FASTCALL_CALL) if(FunctionType != UE_FUNCTION_FASTCALL_CALL)
{ {
StackReadAddress = StackReadAddress + (ParameterNumber * sizeof(ULONG_PTR)); StackReadAddress = StackReadAddress + (ParameterNumber * pointerSize);
if(FunctionType >= UE_FUNCTION_STDCALL_CALL) if(FunctionType >= UE_FUNCTION_STDCALL_CALL)
{ {
StackReadAddress = StackReadAddress - sizeof(ULONG_PTR); StackReadAddress = StackReadAddress - pointerSize;
} }
} }
else 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)
return registerValue;
StackReadAddress = registerValue;
}
else
{
SIZE_T shadowSpace = mode == EngineContextMode::X86 ? 0 : 0x20;
StackReadAddress += shadowSpace + ((ParameterNumber - registerCount) * pointerSize) - pointerSize;
}
}
SIZE_T initialReadSize = ValueIsPointer ? pointerSize : (StackReadSize < sizeof(StackReadBuffer) ? StackReadSize : sizeof(StackReadBuffer));
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, initialReadSize, &ueNumberOfBytesRW))
{ {
if(!ValueIsPointer) if(!ValueIsPointer)
{ {
if(ParameterNumber == 1) RtlMoveMemory(&StackFinalBuffer, &StackReadBuffer, StackReadSize);
{
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);
}
}
}
else
{
StackReadAddress = StackReadAddress + 0x20 + ((ParameterNumber - 4) * sizeof(ULONG_PTR)) - sizeof(ULONG_PTR);
}
}
if(ReadProcessMemory(hProcess, (LPVOID)StackReadAddress, &StackReadBuffer, sizeof(ULONG_PTR), &ueNumberOfBytesRW))
{
if(!ValueIsPointer)
{
RtlMoveMemory((LPVOID)((ULONG_PTR)&StackFinalBuffer + sizeof(ULONG_PTR) - StackReadSize), (LPVOID)((ULONG_PTR)&StackReadBuffer + sizeof(ULONG_PTR) - StackReadSize), StackReadSize);
} }
else else
{ {
StackReadAddress = StackReadBuffer; StackReadAddress = StackReadBuffer;
if(StackSecondReadSize > NULL) 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 else
{ {
@ -218,6 +195,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
DWORD CurrentInstructionSize; DWORD CurrentInstructionSize;
int ReadMemData = NULL; int ReadMemData = NULL;
BYTE ReadByteData = NULL; BYTE ReadByteData = NULL;
bool is32Bit = EngineGetCurrentContextMode() == EngineContextMode::X86;
if(hProcess != NULL) 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)) if(ReadProcessMemory(hProcess, (LPVOID)InstructionAddress, ReadMemory, MAXIMUM_INSTRUCTION_SIZE, &ueNumberOfBytesRead))
{ {
CompareMemory = (PMEMORY_CMP_HANDLER)ReadMemory; CompareMemory = (PMEMORY_CMP_HANDLER)ReadMemory;
CurrentInstructionSize = StaticLengthDisassemble(ReadMemory); CurrentInstructionSize = EngineStaticLengthDisassemble(ReadMemory, is32Bit);
if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5) if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5)
{ {
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 1), 4); 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); RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 2), 4);
TargetedAddress = ReadMemData; TargetedAddress = ReadMemData;
if(sizeof(HANDLE) == 8) if(!is32Bit)
{ {
TargetedAddress = TargetedAddress + InstructionAddress; TargetedAddress = TargetedAddress + InstructionAddress;
} }
@ -314,7 +292,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
{ {
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 2), 4); RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)ReadMemory + 2), 4);
TargetedAddress = ReadMemData; TargetedAddress = ReadMemData;
if(sizeof(HANDLE) == 8) if(!is32Bit)
{ {
TargetedAddress = TargetedAddress + InstructionAddress; TargetedAddress = TargetedAddress + InstructionAddress;
} }
@ -362,7 +340,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
else else
{ {
CompareMemory = (PMEMORY_CMP_HANDLER)InstructionAddress; CompareMemory = (PMEMORY_CMP_HANDLER)InstructionAddress;
CurrentInstructionSize = StaticLengthDisassemble((LPVOID)InstructionAddress); CurrentInstructionSize = EngineStaticLengthDisassemble((LPVOID)InstructionAddress, is32Bit);
if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5) if(CompareMemory->DataByte[0] == 0xE9 && CurrentInstructionSize == 5)
{ {
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 1), 4); 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); RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 2), 4);
TargetedAddress = ReadMemData; TargetedAddress = ReadMemData;
if(sizeof(HANDLE) == 8) if(!is32Bit)
{ {
TargetedAddress = TargetedAddress + InstructionAddress; TargetedAddress = TargetedAddress + InstructionAddress;
} }
@ -449,7 +427,7 @@ __declspec(dllexport) ULONG_PTR TITCALL GetJumpDestinationEx(HANDLE hProcess, UL
{ {
RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 2), 4); RtlMoveMemory(&ReadMemData, (LPVOID)((ULONG_PTR)InstructionAddress + 2), 4);
TargetedAddress = ReadMemData; TargetedAddress = ReadMemData;
if(sizeof(HANDLE) == 8) if(!is32Bit)
{ {
TargetedAddress = TargetedAddress + InstructionAddress; TargetedAddress = TargetedAddress + InstructionAddress;
} }
@ -530,7 +508,8 @@ __declspec(dllexport) bool TITCALL IsJumpGoingToExecuteEx(HANDLE hProcess, HANDL
{ {
ThreadEflags = (DWORD)RegFlags; 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(DisassembledString != NULL)
{ {
if(ThreadEflags & (1 << 0)) if(ThreadEflags & (1 << 0))

View File

@ -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); // Put the new base in the header using the image's pointer width.
if(pnth == nullptr) oldImageBase = ULONG_PTR(pnth->OptionalHeader.ImageBase);
return false; pnth->OptionalHeader.ImageBase = decltype(pnth->OptionalHeader.ImageBase)(newImageBase);
// Put the new base in the header
oldImageBase = pnth->OptionalHeader.ImageBase;
pnth->OptionalHeader.ImageBase = newImageBase;
// Nothing to do if relocations are stripped // Nothing to do if relocations are stripped
if(pnth->FileHeader.Characteristics & IMAGE_FILE_RELOCS_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; return true;
// Process the relocations // 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 relocationItr = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)imageCopy + relocDir.VirtualAddress);
auto relocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)relocationItr + relocDir.Size); 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; 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) static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
{ {
constexpr auto pageSize = 0x1000; constexpr auto pageSize = 0x1000;
@ -100,7 +111,7 @@ static bool RelocateImage(HANDLE hProcess, PVOID imageBase, SIZE_T imageSize)
// perform the actual relocations // perform the actual relocations
ULONG_PTR oldImageBase = 0; 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 // write back the pages
auto memWrite = [hProcess](PVOID ptr, LPCVOID data, SIZE_T size) 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); auto hMapping = CreateFileMappingW(hFile, nullptr, SEC_IMAGE | PAGE_READONLY, 0, 0, nullptr);
if(hMapping) if(hMapping)
{ {
CONTEXT ctx; CONTEXT ctx = {};
ctx.ContextFlags = CONTEXT_ALL; ctx.ContextFlags = CONTEXT_ALL;
if(GetThreadContext(pi.hThread, &ctx)) if(GetThreadContext(pi.hThread, &ctx))
{ {
PVOID imageBase; bool isWow64 = false;
// TODO: support wow64 processes ULONG_PTR pebAddress = 0;
SIZE_T imageBaseOffset = 0;
SIZE_T imageBaseSize = 0;
#ifdef _WIN64 #ifdef _WIN64
auto & pebRegister = ctx.Rdx; ULONG returnLength = 0;
auto & entryPointRegister = ctx.Rcx; if(NT_SUCCESS(NtQueryInformationProcess(pi.hProcess, ProcessWow64Information, &pebAddress, sizeof(pebAddress), &returnLength)) && pebAddress != 0)
#else
auto & pebRegister = ctx.Ebx;
auto & entryPointRegister = ctx.Eax;
#endif // _WIN64
if(ReadProcessMemory(pi.hProcess, (char*)pebRegister + offsetof(PEB, ImageBaseAddress), &imageBase, sizeof(PVOID), nullptr))
{ {
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 // Already at the right base
success = true; success = true;
} }
else else
{ {
auto imageBase = PVOID(imageBaseValue);
auto status = NtUnmapViewOfSection(pi.hProcess, imageBase); auto status = NtUnmapViewOfSection(pi.hProcess, imageBase);
if(status == STATUS_SUCCESS) if(status == STATUS_SUCCESS)
{ {
@ -201,23 +229,60 @@ static bool HollowProcessWithoutASLR(const wchar_t* szFileName, PROCESS_INFORMAT
} }
if(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE) 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); auto relocatedOk = RelocateImage(pi.hProcess, imageBase, viewSize);
if(pebOk && relocatedOk) if(pebOk && relocatedOk)
{ {
auto expectedBase = DebugModuleImageBase == ULONG_PTR(imageBase); auto expectedBase = DebugModuleImageBase == imageBaseValue;
DebugModuleImageBase = ULONG_PTR(imageBase); DebugModuleImageBase = imageBaseValue;
entryPointRegister = DebugModuleImageBase + DebugModuleEntryPoint; auto entryPoint = DebugModuleImageBase + DebugModuleEntryPoint;
if(SetThreadContext(pi.hThread, &ctx)) bool contextOk = false;
#ifdef _WIN64
if(isWow64)
{ {
success = expectedBase; WOW64_CONTEXT ctx32 = {};
#ifndef _WIN64 ctx32.ContextFlags = WOW64_CONTEXT_INTEGER;
// For Wow64 processes, also adjust the 64-bit PEB if(Wow64GetThreadContext(pi.hThread, &ctx32))
if(IsThisProcessWow64() && !WriteProcessMemory(pi.hProcess, (char*)pebRegister - 0x1000 + 0x10, &imageBase, sizeof(PVOID), nullptr)) {
success = false; ctx32.Eax = DWORD(entryPoint);
#endif // _WIN64 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;
}
} }
} }
} }

View File

@ -1,15 +1,31 @@
#include "stdafx.h" #include "stdafx.h"
#include "definitions.h" #include "definitions.h"
#include "Global.Debugger.h" #include "Global.Debugger.h"
#include "Global.Engine.Context.h"
#include "distorm.h" #include "distorm.h"
static char engineDisassembledInstruction[128]; static char engineDisassembledInstruction[128];
#if !defined(_WIN64) static bool DefaultIs32Bit()
_DecodeType DecodingType = Decode32Bits; {
#ifndef _WIN64
return true;
#else #else
_DecodeType DecodingType = Decode64Bits; return false;
#endif #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) 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; return 0;
} }
__declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress) void* EngineStaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress, bool Is32Bit)
{ {
_DecodedInst engineDecodedInstructions[1]; _DecodedInst engineDecodedInstructions[1];
unsigned int DecodedInstructionsCount = 0; 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); int MaxDisassmSize = MAXIMUM_INSTRUCTION_SIZE; // (int)IsBadReadPtrRemote(GetCurrentProcess(), DisassmAddress, MAXIMUM_INSTRUCTION_SIZE);
if(MaxDisassmSize) 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)); RtlZeroMemory(engineDisassembledInstruction, sizeof(engineDisassembledInstruction));
@ -87,12 +103,17 @@ __declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart,
return 0; return 0;
} }
__declspec(dllexport) void* TITCALL StaticDisassembleEx(ULONG_PTR DisassmStart, LPVOID DisassmAddress)
{
return EngineStaticDisassembleEx(DisassmStart, DisassmAddress, DefaultIs32Bit());
}
__declspec(dllexport) void* TITCALL StaticDisassemble(LPVOID DisassmAddress) __declspec(dllexport) void* TITCALL StaticDisassemble(LPVOID DisassmAddress)
{ {
return StaticDisassembleEx((ULONG_PTR)DisassmAddress, 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]; _DecodedInst engineDecodedInstructions[1];
unsigned int DecodedInstructionsCount = 0; 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); BOOL rpm = MemoryReadSafe(hProcess, DisassmAddress, readBuffer, MaxDisassmSize, 0);
if(rpm) 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)); RtlZeroMemory(engineDisassembledInstruction, sizeof(engineDisassembledInstruction));
@ -130,17 +151,27 @@ __declspec(dllexport) void* TITCALL DisassembleEx(HANDLE hProcess, LPVOID Disass
return 0; 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) __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) __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; unsigned int DecodedInstructionsCount = 0;
_CodeInfo decomposerCi = {0}; _CodeInfo decomposerCi = {0};
@ -155,7 +186,7 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D
{ {
decomposerCi.code = readBuffer; decomposerCi.code = readBuffer;
decomposerCi.codeLen = MaxDisassmSize; decomposerCi.codeLen = MaxDisassmSize;
decomposerCi.dt = DecodingType; decomposerCi.dt = GetDecodingType(Is32Bit);
decomposerCi.codeOffset = (LONG_PTR)DisassmAddress; decomposerCi.codeOffset = (LONG_PTR)DisassmAddress;
if(distorm_decompose(&decomposerCi, decomposerResult, _countof(decomposerResult), &DecodedInstructionsCount) != DECRES_INPUTERR) 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; return -1;
} }
__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress)
{
return EngineLengthDisassembleEx(hProcess, DisassmAddress, GetProcessMode(hProcess));
}
__declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress) __declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress)
{ {
return LengthDisassembleEx(dbgProcessInformation.hProcess, DisassmAddress); return LengthDisassembleEx(dbgProcessInformation.hProcess, DisassmAddress);

View File

@ -158,6 +158,14 @@ __declspec(dllexport) void* TITCALL Disassemble(LPVOID DisassmAddress);
__declspec(dllexport) long TITCALL StaticLengthDisassemble(LPVOID DisassmAddress); __declspec(dllexport) long TITCALL StaticLengthDisassemble(LPVOID DisassmAddress);
__declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress); __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID DisassmAddress);
__declspec(dllexport) long TITCALL LengthDisassemble(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 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 InitDebugW(wchar_t* szFileName, wchar_t* szCommandLine, wchar_t* szCurrentFolder);
__declspec(dllexport) void* TITCALL InitNativeDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder); __declspec(dllexport) void* TITCALL InitNativeDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder);