support SafeAttach

This commit is contained in:
Duncan Ogilvie 2020-09-08 22:14:04 +02:00
parent 9fd62daff1
commit 44bc9c8c15
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
11 changed files with 9319 additions and 325 deletions

View File

@ -54,12 +54,12 @@ namespace GleeBug
return result; return result;
} }
bool Debugger::Attach(DWORD processId) bool Debugger::Attach(DWORD processId, decltype(&DebugActiveProcess) debugActiveProcess)
{ {
//don't allow attaching when still debugging //don't allow attaching when still debugging
if(mIsDebugging) if(mIsDebugging)
return false; return false;
if(!DebugActiveProcess(processId)) if(!debugActiveProcess(processId))
return false; return false;
mAttachedToProcess = true; mAttachedToProcess = true;
memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo)); memset(&mMainStartupInfo, 0, sizeof(mMainStartupInfo));

View File

@ -47,7 +47,7 @@ namespace GleeBug
\param processId Process to attach to. \param processId Process to attach to.
\return true if the debuggee was attached to successfully, false otherwise. \return true if the debuggee was attached to successfully, false otherwise.
*/ */
bool Attach(DWORD processId); bool Attach(DWORD processId, decltype(&DebugActiveProcess) = &DebugActiveProcess);
/** /**
\brief Stops the debuggee (terminate the process) \brief Stops the debuggee (terminate the process)

View File

@ -3,9 +3,9 @@
#include <GleeBug/Static.Bufferfile.h> #include <GleeBug/Static.Bufferfile.h>
#include <GleeBug/Debugger.Thread.Registers.h> #include <GleeBug/Debugger.Thread.Registers.h>
#include "TitanEngine.h" #include "TitanEngine.h"
#include "ntdll.h"
#include "FileMap.h" #include "FileMap.h"
#include "PEB.h" #include "PEB.h"
#include "NativeAttach.h"
#include "Global.Engine.Context.h" #include "Global.Engine.Context.h"
#include "Hider.h" #include "Hider.h"
@ -67,7 +67,7 @@ public:
bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack) bool AttachDebugger(DWORD ProcessId, bool KillOnExit, LPVOID DebugInfo, LPVOID CallBack)
{ {
if(!Attach(ProcessId)) if(!Attach(ProcessId, mSafeAttach ? DebugActiveProcess_ : DebugActiveProcess))
return false; return false;
mCbATTACHBREAKPOINT = STEPCALLBACK(CallBack); mCbATTACHBREAKPOINT = STEPCALLBACK(CallBack);
mAttachProcessInfo = (PROCESS_INFORMATION*)DebugInfo; mAttachProcessInfo = (PROCESS_INFORMATION*)DebugInfo;
@ -182,8 +182,15 @@ public:
void SetEngineVariable(DWORD VariableId, bool VariableSet) void SetEngineVariable(DWORD VariableId, bool VariableSet)
{ {
if (VariableId == UE_ENGINE_SET_DEBUG_PRIVILEGE) switch (VariableId)
{
case UE_ENGINE_SET_DEBUG_PRIVILEGE:
mSetDebugPrivilege = VariableSet; mSetDebugPrivilege = VariableSet;
break;
case UE_ENGINE_SAFE_ATTACH:
mSafeAttach = VariableSet;
break;
}
} }
//Misc //Misc
@ -1145,6 +1152,7 @@ private: //functions
private: //variables private: //variables
bool mSetDebugPrivilege = false; bool mSetDebugPrivilege = false;
bool mSafeAttach = false;
typedef void(*CUSTOMHANDLER)(const void*); typedef void(*CUSTOMHANDLER)(const void*);
typedef void(*STEPCALLBACK)(); typedef void(*STEPCALLBACK)();
typedef STEPCALLBACK BPCALLBACK; typedef STEPCALLBACK BPCALLBACK;

View File

@ -0,0 +1,191 @@
#pragma once
static DWORD BaseSetLastNTError(IN NTSTATUS Status)
{
DWORD dwErrCode;
dwErrCode = RtlNtStatusToDosError(Status);
SetLastError(dwErrCode);
return dwErrCode;
}
static HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
{
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE Handle;
CLIENT_ID ClientId;
/* If we don't have a PID, look it up */
//if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId();
/* Open a handle to the process */
ClientId.UniqueThread = NULL;
ClientId.UniqueProcess = UlongToHandle(dwProcessId);
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
Status = NtOpenProcess(&Handle,
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ |
PROCESS_SUSPEND_RESUME | PROCESS_QUERY_INFORMATION,
&ObjectAttributes,
&ClientId);
if (!NT_SUCCESS(Status))
{
/* Fail */
BaseSetLastNTError(Status);
return 0;
}
/* Return the handle */
return Handle;
}
#define THREAD_CREATE_FLAGS_CREATE_SUSPENDED 0x00000001
#define THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH 0x00000002
#define THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER 0x00000004
#define THREAD_CREATE_FLAGS_HAS_SECURITY_DESCRIPTOR 0x00000010
#define THREAD_CREATE_FLAGS_ACCESS_CHECK_IN_TARGET 0x00000020
#define THREAD_CREATE_FLAGS_INITIAL_THREAD 0x00000080
static NTSTATUS CreateThreadSkipAttach(IN HANDLE ProcessHandle, IN PUSER_THREAD_START_ROUTINE StartRoutine, IN PVOID Argument)
{
NTSTATUS Status;
HANDLE hThread;
typedef NTSTATUS(NTAPI *t_NtCreateThreadEx)(
PHANDLE /* ThreadHandle */,
ACCESS_MASK /* DesiredAccess */,
POBJECT_ATTRIBUTES /* ObjectAttributes */,
HANDLE /* ProcessHandle */,
PUSER_THREAD_START_ROUTINE /* StartRoutine */,
PVOID /* Argument */,
ULONG /* CreateFlags */,
ULONG_PTR /* ZeroBits */,
SIZE_T /* StackSize */,
SIZE_T /* MaximumStackSize */,
PPS_ATTRIBUTE_LIST /* AttributeList */
);
auto p_NtCreateThreadEx = (t_NtCreateThreadEx)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
if (p_NtCreateThreadEx)
{
// Based on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/339263/16/client/crashpad_client_win.cc#697
Status = p_NtCreateThreadEx(&hThread,
STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
nullptr,
ProcessHandle,
StartRoutine,
Argument,
THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
0,
0x4000 /* PAGE_SIZE * 4 */,
0x4000,
nullptr);
}
else
{
CLIENT_ID ClientId;
Status = RtlCreateUserThread(ProcessHandle,
NULL,
FALSE,
0,
0x4000,
0x4000 /* PAGE_SIZE * 4 */,
StartRoutine,
Argument,
&hThread,
&ClientId);
}
if (NT_SUCCESS(Status))
{
NtClose(hThread);
}
return Status;
}
static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
{
PUSER_THREAD_START_ROUTINE RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)DbgUiRemoteBreakin;
LPVOID RemoteMemory = VirtualAllocEx(Process, 0, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READ);
if (RemoteMemory)
{
SIZE_T written = 0;
unsigned char payload[] = { 0xCC, 0xC3 };
if (WriteProcessMemory(Process, RemoteMemory, payload, sizeof(payload), &written))
{
RemoteBreakFunction = (PUSER_THREAD_START_ROUTINE)RemoteMemory;
}
else
{
VirtualFreeEx(Process, RemoteMemory, 0, MEM_RELEASE);
}
}
/* Create the thread that will perform the breakin (on Vista+ it will skip DllMain and TLS callbacks) */
return CreateThreadSkipAttach(Process, RemoteBreakFunction, NULL);
}
static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
{
/* Tell the kernel to start debugging */
NTSTATUS Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]);
if (NT_SUCCESS(Status))
{
/* Now break-in the process */
Status = DbgUiIssueRemoteBreakin_(Process);
if (!NT_SUCCESS(Status))
{
/* We couldn't break-in, cancel debugging */
DbgUiStopDebugging(Process);
}
}
/* Return status */
return Status;
}
static NTSTATUS NTAPI DbgUiConnectToDbg_()
{
if (NtCurrentTeb()->DbgSsReserved[1] != NULL)
return STATUS_SUCCESS;
OBJECT_ATTRIBUTES ObjectAttributes;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
return NtCreateDebugObject(&NtCurrentTeb()->DbgSsReserved[1], DEBUG_ALL_ACCESS, &ObjectAttributes, 0);
}
// Source: https://github.com/mirror/reactos/blob/c6d2b35ffc91e09f50dfb214ea58237509329d6b/reactos/dll/win32/kernel32/client/debugger.c#L480
BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
{
/* Connect to the debugger */
NTSTATUS Status = DbgUiConnectToDbg_();
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
/* Get the process handle */
HANDLE Handle = ProcessIdToHandle(dwProcessId);
if (!Handle)
{
return FALSE;
}
/* Now debug the process */
Status = DbgUiDebugActiveProcess_(Handle);
/* Close the handle since we're done */
NtClose(Handle);
/* Check if debugging worked */
if (!NT_SUCCESS(Status))
{
/* Fail */
BaseSetLastNTError(Status);
return FALSE;
}
/* Success */
}

View File

@ -56,31 +56,32 @@
#define UE_ENGINE_RESET_CUSTOM_HANDLER 7 #define UE_ENGINE_RESET_CUSTOM_HANDLER 7
#define UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK 8 #define UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK 8
#define UE_ENGINE_SET_DEBUG_PRIVILEGE 9 #define UE_ENGINE_SET_DEBUG_PRIVILEGE 9
#define UE_ENGINE_SAFE_ATTACH 10
#define UE_OPTION_REMOVEALL 1 #define UE_OPTION_REMOVEALL 1
#define UE_OPTION_DISABLEALL 2 #define UE_OPTION_DISABLEALL 2
#define UE_OPTION_REMOVEALLDISABLED 3 #define UE_OPTION_REMOVEALLDISABLED 3
#define UE_OPTION_REMOVEALLENABLED 4 #define UE_OPTION_REMOVEALLENABLED 4
#define UESTATIC_DECRYPTOR_XOR 1 #define UE_STATIC_DECRYPTOR_XOR 1
#define UESTATIC_DECRYPTOR_SUB 2 #define UE_STATIC_DECRYPTOR_SUB 2
#define UESTATIC_DECRYPTOR_ADD 3 #define UE_STATIC_DECRYPTOR_ADD 3
#define UESTATIC_DECRYPTOR_FOREWARD 1 #define UE_STATIC_DECRYPTOR_FOREWARD 1
#define UESTATIC_DECRYPTOR_BACKWARD 2 #define UE_STATIC_DECRYPTOR_BACKWARD 2
#define UESTATIC_KEY_SIZE_1 1 #define UE_STATIC_KEY_SIZE_1 1
#define UESTATIC_KEY_SIZE_2 2 #define UE_STATIC_KEY_SIZE_2 2
#define UESTATIC_KEY_SIZE_4 4 #define UE_STATIC_KEY_SIZE_4 4
#define UESTATIC_KEY_SIZE_8 8 #define UE_STATIC_KEY_SIZE_8 8
#define UESTATIC_APLIB 1 #define UE_STATIC_APLIB 1
#define UESTATIC_APLIB_DEPACK 2 #define UE_STATIC_APLIB_DEPACK 2
#define UESTATIC_LZMA 3 #define UE_STATIC_LZMA 3
#define UESTATIC_HASH_MD5 1 #define UE_STATIC_HASH_MD5 1
#define UESTATIC_HASH_SHA1 2 #define UE_STATIC_HASH_SHA1 2
#define UESTATIC_HASH_CRC32 3 #define UE_STATIC_HASH_CRC32 3
#define UE_RESOURCE_LANGUAGE_ANY -1 #define UE_RESOURCE_LANGUAGE_ANY -1
@ -505,7 +506,7 @@ typedef struct HOOK_ENTRY
#define UE_FIELD_OK 0 #define UE_FIELD_OK 0
#define UE_FIELD_BROKEN_NON_FIXABLE 1 #define UE_FIELD_BROKEN_NON_FIXABLE 1
#define UE_FIELD_BROKEN_NON_CRITICAL 2 #define UE_FIELD_BROKEN_NON_CRITICAL 2
#define UE_FIELD_BROKEN_FIXABLE_FORSTATIC_USE 3 #define UE_FIELD_BROKEN_FIXABLE_FOR_STATIC_USE 3
#define UE_FIELD_BROKEN_BUT_CAN_BE_EMULATED 4 #define UE_FIELD_BROKEN_BUT_CAN_BE_EMULATED 4
#define UE_FIELD_FIXABLE_NON_CRITICAL 5 #define UE_FIELD_FIXABLE_NON_CRITICAL 5
#define UE_FIELD_FIXABLE_CRITICAL 6 #define UE_FIELD_FIXABLE_CRITICAL 6
@ -782,7 +783,7 @@ __declspec(dllexport) bool TITCALL RelocaterWipeRelocationTableW(const wchar_t*
__declspec(dllexport) ULONG_PTR TITCALL ResourcerLoadFileForResourceUse(const char* szFileName); __declspec(dllexport) ULONG_PTR TITCALL ResourcerLoadFileForResourceUse(const char* szFileName);
__declspec(dllexport) ULONG_PTR TITCALL ResourcerLoadFileForResourceUseW(const wchar_t* szFileName); __declspec(dllexport) ULONG_PTR TITCALL ResourcerLoadFileForResourceUseW(const wchar_t* szFileName);
__declspec(dllexport) bool TITCALL ResourcerFreeLoadedFile(LPVOID LoadedFileBase); __declspec(dllexport) bool TITCALL ResourcerFreeLoadedFile(LPVOID LoadedFileBase);
__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileEx(ULONG_PTR FileMapVA, const char* szResourceType, const char* szResourceName, const char* szExtractedFileName); __declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileEx(HMODULE hFile, const char* szResourceType, const char* szResourceName, const char* szExtractedFileName);
__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFile(const char* szFileName, const char* szResourceType, const char* szResourceName, const char* szExtractedFileName); __declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFile(const char* szFileName, const char* szResourceType, const char* szResourceName, const char* szExtractedFileName);
__declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileW(const wchar_t* szFileName, char* szResourceType, const char* szResourceName, const char* szExtractedFileName); __declspec(dllexport) bool TITCALL ResourcerExtractResourceFromFileW(const wchar_t* szFileName, char* szResourceType, const char* szResourceName, const char* szExtractedFileName);
__declspec(dllexport) bool TITCALL ResourcerFindResource(const char* szFileName, const char* szResourceType, DWORD ResourceType, const char* szResourceName, DWORD ResourceName, DWORD ResourceLanguage, PULONG_PTR pResourceData, LPDWORD pResourceSize); __declspec(dllexport) bool TITCALL ResourcerFindResource(const char* szFileName, const char* szResourceType, DWORD ResourceType, const char* szResourceName, DWORD ResourceName, DWORD ResourceLanguage, PULONG_PTR pResourceData, LPDWORD pResourceSize);
@ -823,6 +824,8 @@ __declspec(dllexport) long TITCALL LengthDisassembleEx(HANDLE hProcess, LPVOID D
__declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress); __declspec(dllexport) long TITCALL LengthDisassemble(LPVOID DisassmAddress);
__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(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder); __declspec(dllexport) void* TITCALL InitDebugW(const wchar_t* szFileName, const wchar_t* szCommandLine, const wchar_t* szCurrentFolder);
__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); __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 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); __declspec(dllexport) void* TITCALL InitDLLDebug(const char* szFileName, bool ReserveModuleBase, const char* szCommandLine, const char* szCurrentFolder, LPVOID EntryCallBack);

View File

@ -1,4 +1,4 @@
#include <windows.h> #include "ntdll.h"
#include "Emulator.h" #include "Emulator.h"
Emulator emu; Emulator emu;

View File

@ -158,6 +158,8 @@
<ClInclude Include="FileMap.h" /> <ClInclude Include="FileMap.h" />
<ClInclude Include="Global.Engine.Context.h" /> <ClInclude Include="Global.Engine.Context.h" />
<ClInclude Include="Hider.h" /> <ClInclude Include="Hider.h" />
<ClInclude Include="NativeAttach.h" />
<ClInclude Include="ntdll.h" />
<ClInclude Include="PEB.h" /> <ClInclude Include="PEB.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="TitanEngine.h" /> <ClInclude Include="TitanEngine.h" />

View File

@ -43,6 +43,12 @@
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="NativeAttach.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ntdll.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="TitanEngine.rc"> <ResourceCompile Include="TitanEngine.rc">

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.