diff --git a/StaticEngine/TitanEngine.h b/StaticEngine/TitanEngine.h index c816446..e189d0e 100644 --- a/StaticEngine/TitanEngine.h +++ b/StaticEngine/TitanEngine.h @@ -10,6 +10,8 @@ #include #include +typedef void(TITCALL* TITANCBSTEP)(); + #pragma pack(push, 1) // Global.Constant.Structure.Declaration: @@ -35,6 +37,51 @@ #define UE_ACCESS_WRITE 1 #define UE_ACCESS_ALL 2 +enum TitanSessionKind +{ + UE_SESSION_NONE = 0, + UE_SESSION_LIVE = 1, + UE_SESSION_MINIDUMP = 2, + UE_SESSION_TTD = 3, + UE_SESSION_STATIC = 4, +}; + +enum TitanSessionCapability : uint64_t +{ + UE_SESSION_CAP_MEMORY_READ = 1ull << 0, + UE_SESSION_CAP_MEMORY_QUERY = 1ull << 1, + UE_SESSION_CAP_CONTEXT_READ = 1ull << 2, + UE_SESSION_CAP_FORWARD_EXECUTION = 1ull << 3, + UE_SESSION_CAP_REVERSE_EXECUTION = 1ull << 4, + UE_SESSION_CAP_EXACT_POSITION = 1ull << 5, + UE_SESSION_CAP_LOGICAL_CODE_BREAKPOINT = 1ull << 6, + UE_SESSION_CAP_LOGICAL_DATA_BREAKPOINT = 1ull << 7, + UE_SESSION_CAP_MEMORY_WRITE = 1ull << 8, + UE_SESSION_CAP_CONTEXT_WRITE = 1ull << 9, + UE_SESSION_CAP_PROCESS_CONTROL = 1ull << 10, + UE_SESSION_CAP_THREAD_CONTROL = 1ull << 11, + UE_SESSION_CAP_NATIVE_HANDLES = 1ull << 12, + UE_SESSION_CAP_EXCEPTION_CONTINUE = 1ull << 13, + UE_SESSION_CAP_TIMELINE_STATE = 1ull << 14, +}; + +typedef struct +{ + DWORD structSize; + TitanSessionKind kind; + uint64_t capabilities; + DWORD machineType; + DWORD processId; + DWORD threadId; + DWORD reserved; +} TITAN_SESSION_INFO; + +typedef struct +{ + uint64_t sequence; + uint64_t steps; +} TITAN_REPLAY_POSITION; + #define UE_HIDE_PEBONLY 0 #define UE_HIDE_BASIC 1 @@ -844,6 +891,13 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D __declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress); __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder); __declspec(dllexport) void* TITCALL InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder); +__declspec(dllexport) PROCESS_INFORMATION* TITCALL InitReplayW(const wchar_t* szArtifactPath, TitanSessionKind ExpectedKind); +__declspec(dllexport) bool TITCALL GetSessionInfo(TITAN_SESSION_INFO* SessionInfo); +__declspec(dllexport) bool TITCALL ReplayGetPosition(TITAN_REPLAY_POSITION* Position); +__declspec(dllexport) bool TITCALL ReplayGetExtent(TITAN_REPLAY_POSITION* First, TITAN_REPLAY_POSITION* Last); +__declspec(dllexport) bool TITCALL ReplaySetPosition(const TITAN_REPLAY_POSITION* Position); +__declspec(dllexport) bool TITCALL ReplayRun(bool Reverse); +__declspec(dllexport) bool TITCALL ReplayStep(bool Reverse, bool StepOver, TITANCBSTEP StepCallBack); __declspec(dllexport) void* TITCALL InitDebugEx(const char* szFileName, const char* szCommandLine, const char* szCurrentFolder, LPVOID EntryCallBack); __declspec(dllexport) void* TITCALL InitDebugExW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID EntryCallBack); __declspec(dllexport) void* TITCALL InitDLLDebug(const char* szFileName, bool ReserveModuleBase, const char* szCommandLine, const char* szCurrentFolder, LPVOID EntryCallBack); @@ -1037,6 +1091,8 @@ __declspec(dllexport) long TITCALL GetActiveProcessIdW(const wchar_t* szImageNam __declspec(dllexport) void TITCALL EnumProcessesWithLibrary(const char* szLibraryName, void* EnumFunction); __declspec(dllexport) HANDLE TITCALL TitanOpenProcess(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwProcessId); __declspec(dllexport) HANDLE TITCALL TitanOpenThread(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwThreadId); +__declspec(dllexport) bool TITCALL TitanGetProcessImagePathW(HANDLE hProcess, LPWSTR szPath, SIZE_T cchPath); +__declspec(dllexport) bool TITCALL TitanGetModulePathW(HANDLE hProcess, ULONG_PTR ModuleBase, LPWSTR szPath, SIZE_T cchPath); __declspec(dllexport) bool TITCALL TitanCloseHandle(HANDLE hEngineHandle); __declspec(dllexport) bool TITCALL ProcessIsWow64(HANDLE hProcess, PBOOL isWow64); __declspec(dllexport) bool TITCALL TitanTerminateProcess(HANDLE hProcess, DWORD exitCode); diff --git a/StaticEngine/TitanEngineEmulator.cpp b/StaticEngine/TitanEngineEmulator.cpp index aeae3fd..1cc6435 100644 --- a/StaticEngine/TitanEngineEmulator.cpp +++ b/StaticEngine/TitanEngineEmulator.cpp @@ -1,12 +1,84 @@ #include +#include #include "Emulator.h" +#pragma comment(lib, "psapi.lib") + Emulator emu; +static bool gSessionStarted = false; //Debugger basics __declspec(dllexport) void* TITCALL InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder) { - return emu.InitDebugW(szFileName, szCommandLine, szCurrentFolder); + auto result = emu.InitDebugW(szFileName, szCommandLine, szCurrentFolder); + gSessionStarted = result != nullptr; + return result; +} + +__declspec(dllexport) PROCESS_INFORMATION* TITCALL InitReplayW(const wchar_t* szArtifactPath, TitanSessionKind ExpectedKind) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return nullptr; +} + +__declspec(dllexport) bool TITCALL GetSessionInfo(TITAN_SESSION_INFO* SessionInfo) +{ + if(!SessionInfo) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + *SessionInfo = {}; + SessionInfo->structSize = sizeof(*SessionInfo); + if(!gSessionStarted && !emu.IsFileBeingDebugged()) + return true; + SessionInfo->kind = UE_SESSION_STATIC; + SessionInfo->capabilities = UE_SESSION_CAP_MEMORY_READ | UE_SESSION_CAP_MEMORY_QUERY | + UE_SESSION_CAP_CONTEXT_READ | UE_SESSION_CAP_MEMORY_WRITE | + UE_SESSION_CAP_CONTEXT_WRITE | UE_SESSION_CAP_PROCESS_CONTROL | + UE_SESSION_CAP_THREAD_CONTROL | UE_SESSION_CAP_NATIVE_HANDLES; +#ifdef _WIN64 + SessionInfo->machineType = IMAGE_FILE_MACHINE_AMD64; +#else + SessionInfo->machineType = IMAGE_FILE_MACHINE_I386; +#endif + return true; +} + +__declspec(dllexport) bool TITCALL ReplayGetPosition(TITAN_REPLAY_POSITION* Position) +{ + if(Position) + *Position = {}; + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayGetExtent(TITAN_REPLAY_POSITION* First, TITAN_REPLAY_POSITION* Last) +{ + if(First) + *First = {}; + if(Last) + *Last = {}; + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplaySetPosition(const TITAN_REPLAY_POSITION* Position) +{ + SetLastError(Position ? ERROR_NOT_SUPPORTED : ERROR_INVALID_PARAMETER); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayRun(bool Reverse) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayStep(bool Reverse, bool StepOver, TITANCBSTEP StepCallBack) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return false; } __declspec(dllexport) void* TITCALL InitDLLDebugW(const wchar_t* szFileName, bool ReserveModuleBase, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID EntryCallBack) @@ -16,12 +88,17 @@ __declspec(dllexport) void* TITCALL InitDLLDebugW(const wchar_t* szFileName, boo __declspec(dllexport) bool TITCALL StopDebug() { - return emu.StopDebug(); + auto result = emu.StopDebug(); + gSessionStarted = false; + return result; } __declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) { - return emu.AttachDebugger(ProcessId, KillOnExit, DebugInfo, CallBack); + gSessionStarted = true; + auto result = emu.AttachDebugger(ProcessId, KillOnExit, DebugInfo, CallBack); + gSessionStarted = false; + return result; } __declspec(dllexport) bool TITCALL DetachDebuggerEx(DWORD ProcessId) @@ -132,6 +209,27 @@ __declspec(dllexport) HANDLE TITCALL TitanOpenThread(DWORD dwDesiredAccess, bool return emu.TitanOpenThread(dwDesiredAccess, bInheritHandle, dwThreadId); } +__declspec(dllexport) bool TITCALL TitanGetProcessImagePathW(HANDLE hProcess, LPWSTR szPath, SIZE_T cchPath) +{ + if(!hProcess || !szPath || !cchPath || cchPath > MAXDWORD) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + DWORD length = (DWORD)cchPath; + return !!QueryFullProcessImageNameW(hProcess, 0, szPath, &length); +} + +__declspec(dllexport) bool TITCALL TitanGetModulePathW(HANDLE hProcess, ULONG_PTR ModuleBase, LPWSTR szPath, SIZE_T cchPath) +{ + if(!hProcess || !ModuleBase || !szPath || !cchPath || cchPath > MAXDWORD) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + return GetModuleFileNameExW(hProcess, (HMODULE)ModuleBase, szPath, (DWORD)cchPath) != 0; +} + __declspec(dllexport) bool TITCALL TitanCloseHandle(HANDLE hEngineHandle) { return !!CloseHandle(hEngineHandle); diff --git a/TitanEngineEmulator/TitanEngine.h b/TitanEngineEmulator/TitanEngine.h index 5b23216..f9412b6 100644 --- a/TitanEngineEmulator/TitanEngine.h +++ b/TitanEngineEmulator/TitanEngine.h @@ -10,6 +10,8 @@ #include #include +typedef void(TITCALL* TITANCBSTEP)(); + #pragma pack(push, 1) // Global.Constant.Structure.Declaration: @@ -35,6 +37,51 @@ #define UE_ACCESS_WRITE 1 #define UE_ACCESS_ALL 2 +enum TitanSessionKind +{ + UE_SESSION_NONE = 0, + UE_SESSION_LIVE = 1, + UE_SESSION_MINIDUMP = 2, + UE_SESSION_TTD = 3, + UE_SESSION_STATIC = 4, +}; + +enum TitanSessionCapability : uint64_t +{ + UE_SESSION_CAP_MEMORY_READ = 1ull << 0, + UE_SESSION_CAP_MEMORY_QUERY = 1ull << 1, + UE_SESSION_CAP_CONTEXT_READ = 1ull << 2, + UE_SESSION_CAP_FORWARD_EXECUTION = 1ull << 3, + UE_SESSION_CAP_REVERSE_EXECUTION = 1ull << 4, + UE_SESSION_CAP_EXACT_POSITION = 1ull << 5, + UE_SESSION_CAP_LOGICAL_CODE_BREAKPOINT = 1ull << 6, + UE_SESSION_CAP_LOGICAL_DATA_BREAKPOINT = 1ull << 7, + UE_SESSION_CAP_MEMORY_WRITE = 1ull << 8, + UE_SESSION_CAP_CONTEXT_WRITE = 1ull << 9, + UE_SESSION_CAP_PROCESS_CONTROL = 1ull << 10, + UE_SESSION_CAP_THREAD_CONTROL = 1ull << 11, + UE_SESSION_CAP_NATIVE_HANDLES = 1ull << 12, + UE_SESSION_CAP_EXCEPTION_CONTINUE = 1ull << 13, + UE_SESSION_CAP_TIMELINE_STATE = 1ull << 14, +}; + +typedef struct +{ + DWORD structSize; + TitanSessionKind kind; + uint64_t capabilities; + DWORD machineType; + DWORD processId; + DWORD threadId; + DWORD reserved; +} TITAN_SESSION_INFO; + +typedef struct +{ + uint64_t sequence; + uint64_t steps; +} TITAN_REPLAY_POSITION; + #define UE_HIDE_PEBONLY 0 #define UE_HIDE_BASIC 1 @@ -848,6 +895,13 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D __declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress); __declspec(dllexport) void* TITCALL InitDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder); __declspec(dllexport) void* TITCALL InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder); +__declspec(dllexport) PROCESS_INFORMATION* TITCALL InitReplayW(const wchar_t* szArtifactPath, TitanSessionKind ExpectedKind); +__declspec(dllexport) bool TITCALL GetSessionInfo(TITAN_SESSION_INFO* SessionInfo); +__declspec(dllexport) bool TITCALL ReplayGetPosition(TITAN_REPLAY_POSITION* Position); +__declspec(dllexport) bool TITCALL ReplayGetExtent(TITAN_REPLAY_POSITION* First, TITAN_REPLAY_POSITION* Last); +__declspec(dllexport) bool TITCALL ReplaySetPosition(const TITAN_REPLAY_POSITION* Position); +__declspec(dllexport) bool TITCALL ReplayRun(bool Reverse); +__declspec(dllexport) bool TITCALL ReplayStep(bool Reverse, bool StepOver, TITANCBSTEP StepCallBack); __declspec(dllexport) void* TITCALL InitNativeDebug(char* szFileName, char* szCommandLine, char* szCurrentFolder); __declspec(dllexport) void* TITCALL InitNativeDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder); __declspec(dllexport) void* TITCALL InitDebugEx(const char* szFileName, const char* szCommandLine, const char* szCurrentFolder, LPVOID EntryCallBack); @@ -1043,6 +1097,8 @@ __declspec(dllexport) long TITCALL GetActiveProcessIdW(const wchar_t* szImageNam __declspec(dllexport) void TITCALL EnumProcessesWithLibrary(const char* szLibraryName, void* EnumFunction); __declspec(dllexport) HANDLE TITCALL TitanOpenProcess(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwProcessId); __declspec(dllexport) HANDLE TITCALL TitanOpenThread(DWORD dwDesiredAccess, bool bInheritHandle, DWORD dwThreadId); +__declspec(dllexport) bool TITCALL TitanGetProcessImagePathW(HANDLE hProcess, LPWSTR szPath, SIZE_T cchPath); +__declspec(dllexport) bool TITCALL TitanGetModulePathW(HANDLE hProcess, ULONG_PTR ModuleBase, LPWSTR szPath, SIZE_T cchPath); __declspec(dllexport) bool TITCALL TitanCloseHandle(HANDLE hEngineHandle); __declspec(dllexport) bool TITCALL ProcessIsWow64(HANDLE hProcess, PBOOL isWow64); __declspec(dllexport) bool TITCALL TitanTerminateProcess(HANDLE hProcess, DWORD exitCode); diff --git a/TitanEngineEmulator/TitanEngineEmulator.cpp b/TitanEngineEmulator/TitanEngineEmulator.cpp index 6704a09..03f015b 100644 --- a/TitanEngineEmulator/TitanEngineEmulator.cpp +++ b/TitanEngineEmulator/TitanEngineEmulator.cpp @@ -1,11 +1,84 @@ #include "Emulator.h" +#include + +#pragma comment(lib, "psapi.lib") Emulator emu; +static bool gSessionStarted = false; //Debugger basics __declspec(dllexport) void* TITCALL InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder) { - return emu.InitDebugW(szFileName, szCommandLine, szCurrentFolder); + auto result = emu.InitDebugW(szFileName, szCommandLine, szCurrentFolder); + gSessionStarted = result != nullptr; + return result; +} + +__declspec(dllexport) PROCESS_INFORMATION* TITCALL InitReplayW(const wchar_t* szArtifactPath, TitanSessionKind ExpectedKind) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return nullptr; +} + +__declspec(dllexport) bool TITCALL GetSessionInfo(TITAN_SESSION_INFO* SessionInfo) +{ + if(!SessionInfo) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + *SessionInfo = {}; + SessionInfo->structSize = sizeof(*SessionInfo); + if(!gSessionStarted && !emu.IsFileBeingDebugged()) + return true; + SessionInfo->kind = UE_SESSION_LIVE; + SessionInfo->capabilities = UE_SESSION_CAP_MEMORY_READ | UE_SESSION_CAP_MEMORY_QUERY | + UE_SESSION_CAP_CONTEXT_READ | UE_SESSION_CAP_FORWARD_EXECUTION | + UE_SESSION_CAP_MEMORY_WRITE | UE_SESSION_CAP_CONTEXT_WRITE | + UE_SESSION_CAP_PROCESS_CONTROL | UE_SESSION_CAP_THREAD_CONTROL | + UE_SESSION_CAP_NATIVE_HANDLES | UE_SESSION_CAP_EXCEPTION_CONTINUE; +#ifdef _WIN64 + SessionInfo->machineType = IMAGE_FILE_MACHINE_AMD64; +#else + SessionInfo->machineType = IMAGE_FILE_MACHINE_I386; +#endif + return true; +} + +__declspec(dllexport) bool TITCALL ReplayGetPosition(TITAN_REPLAY_POSITION* Position) +{ + if(Position) + *Position = {}; + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayGetExtent(TITAN_REPLAY_POSITION* First, TITAN_REPLAY_POSITION* Last) +{ + if(First) + *First = {}; + if(Last) + *Last = {}; + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplaySetPosition(const TITAN_REPLAY_POSITION* Position) +{ + SetLastError(Position ? ERROR_NOT_SUPPORTED : ERROR_INVALID_PARAMETER); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayRun(bool Reverse) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return false; +} + +__declspec(dllexport) bool TITCALL ReplayStep(bool Reverse, bool StepOver, TITANCBSTEP StepCallBack) +{ + SetLastError(ERROR_NOT_SUPPORTED); + return false; } __declspec(dllexport) void* TITCALL InitDLLDebugW(const wchar_t* szFileName, bool ReserveModuleBase, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder, LPVOID EntryCallBack) @@ -15,12 +88,17 @@ __declspec(dllexport) void* TITCALL InitDLLDebugW(const wchar_t* szFileName, boo __declspec(dllexport) bool TITCALL StopDebug() { - return emu.StopDebug(); + auto result = emu.StopDebug(); + gSessionStarted = false; + return result; } __declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) { - return emu.AttachDebugger(ProcessId, KillOnExit, DebugInfo, CallBack); + gSessionStarted = true; + auto result = emu.AttachDebugger(ProcessId, KillOnExit, DebugInfo, CallBack); + gSessionStarted = false; + return result; } __declspec(dllexport) bool TITCALL DetachDebuggerEx(DWORD ProcessId) @@ -131,6 +209,27 @@ __declspec(dllexport) HANDLE TITCALL TitanOpenThread(DWORD dwDesiredAccess, bool return emu.TitanOpenThread(dwDesiredAccess, bInheritHandle, dwThreadId); } +__declspec(dllexport) bool TITCALL TitanGetProcessImagePathW(HANDLE hProcess, LPWSTR szPath, SIZE_T cchPath) +{ + if(!hProcess || !szPath || !cchPath || cchPath > MAXDWORD) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + DWORD length = (DWORD)cchPath; + return !!QueryFullProcessImageNameW(hProcess, 0, szPath, &length); +} + +__declspec(dllexport) bool TITCALL TitanGetModulePathW(HANDLE hProcess, ULONG_PTR ModuleBase, LPWSTR szPath, SIZE_T cchPath) +{ + if(!hProcess || !ModuleBase || !szPath || !cchPath || cchPath > MAXDWORD) + { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + return GetModuleFileNameExW(hProcess, (HMODULE)ModuleBase, szPath, (DWORD)cchPath) != 0; +} + __declspec(dllexport) bool TITCALL TitanCloseHandle(HANDLE hEngineHandle) { return !!CloseHandle(hEngineHandle);