Add safe attach option

This commit is contained in:
Duncan Ogilvie 2018-07-19 16:27:43 +02:00
parent ab037ef1c5
commit bfec722a12
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
14 changed files with 156 additions and 3 deletions

View File

@ -56,6 +56,7 @@
#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

View File

@ -52,6 +52,7 @@ const BYTE UE_ENGINE_CALL_PLUGIN_CALLBACK = 6;
const BYTE UE_ENGINE_RESET_CUSTOM_HANDLER = 7; const BYTE UE_ENGINE_RESET_CUSTOM_HANDLER = 7;
const BYTE UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8; const BYTE UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8;
const BYTE UE_ENGINE_SET_DEBUG_PRIVILEGE = 9; const BYTE UE_ENGINE_SET_DEBUG_PRIVILEGE = 9;
const BYTE UE_ENGINE_SAFE_ATTACH = 10;
const BYTE UE_OPTION_REMOVEALL = 1; const BYTE UE_OPTION_REMOVEALL = 1;
const BYTE UE_OPTION_DISABLEALL = 2; const BYTE UE_OPTION_DISABLEALL = 2;

View File

@ -71,7 +71,8 @@ enum eEngineVariable : DWORD
UE_ENGINE_CALL_PLUGIN_CALLBACK = UE::UE_ENGINE_CALL_PLUGIN_CALLBACK, UE_ENGINE_CALL_PLUGIN_CALLBACK = UE::UE_ENGINE_CALL_PLUGIN_CALLBACK,
UE_ENGINE_RESET_CUSTOM_HANDLER = UE::UE_ENGINE_RESET_CUSTOM_HANDLER, UE_ENGINE_RESET_CUSTOM_HANDLER = UE::UE_ENGINE_RESET_CUSTOM_HANDLER,
UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = UE::UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK, UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = UE::UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK,
UE_ENGINE_SET_DEBUG_PRIVILEGE = UE::UE_ENGINE_SET_DEBUG_PRIVILEGE UE_ENGINE_SET_DEBUG_PRIVILEGE = UE::UE_ENGINE_SET_DEBUG_PRIVILEGE,
UE_ENGINE_SAFE_ATTACH = UE::UE_ENGINE_SAFE_ATTACH,
}; };
enum eBPRemoveOption : DWORD enum eBPRemoveOption : DWORD

View File

@ -337,6 +337,7 @@ const
UE_ENGINE_RESET_CUSTOM_HANDLER = 7; UE_ENGINE_RESET_CUSTOM_HANDLER = 7;
UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8; UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8;
UE_ENGINE_SET_DEBUG_PRIVILEGE = 9; UE_ENGINE_SET_DEBUG_PRIVILEGE = 9;
UE_ENGINE_SAFE_ATTACH = 10;
UE_OPTION_REMOVEALL = 1; UE_OPTION_REMOVEALL = 1;
UE_OPTION_DISABLEALL = 2; UE_OPTION_DISABLEALL = 2;

View File

@ -37,6 +37,7 @@ UE_ENGINE_CALL_PLUGIN_CALLBACK = 6
UE_ENGINE_RESET_CUSTOM_HANDLER = 7 UE_ENGINE_RESET_CUSTOM_HANDLER = 7
UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8 UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8
UE_ENGINE_SET_DEBUG_PRIVILEGE = 9 UE_ENGINE_SET_DEBUG_PRIVILEGE = 9
UE_ENGINE_SAFE_ATTACH = 10
UE_OPTION_REMOVEALL = 1 UE_OPTION_REMOVEALL = 1
UE_OPTION_DISABLEALL = 2 UE_OPTION_DISABLEALL = 2

View File

@ -23,6 +23,7 @@ UE_ENGINE_BACKUP_FOR_CRITICAL_FUNCTIONS EQU 5
UE_ENGINE_CALL_PLUGIN_CALLBACK EQU 6 UE_ENGINE_CALL_PLUGIN_CALLBACK EQU 6
UE_ENGINE_RESET_CUSTOM_HANDLER EQU 7 UE_ENGINE_RESET_CUSTOM_HANDLER EQU 7
UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK EQU 8 UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK EQU 8
UE_ENGINE_SAFE_ATTACH EQU 10
UE_ENGINE_SET_DEBUG_PRIVILEGE EQU 9 UE_ENGINE_SET_DEBUG_PRIVILEGE EQU 9
UE_OPTION_REMOVEALL EQU 1 UE_OPTION_REMOVEALL EQU 1
UE_OPTION_DISABLEALL EQU 2 UE_OPTION_DISABLEALL EQU 2

View File

@ -28,6 +28,7 @@ UE_ENGINE_CALL_PLUGIN_CALLBACK = 6
UE_ENGINE_RESET_CUSTOM_HANDLER = 7 UE_ENGINE_RESET_CUSTOM_HANDLER = 7
UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8 UE_ENGINE_CALL_PLUGIN_DEBUG_CALLBACK = 8
UE_ENGINE_SET_DEBUG_PRIVILEGE = 9 UE_ENGINE_SET_DEBUG_PRIVILEGE = 9
UE_ENGINE_SAFE_ATTACH = 10
UE_OPTION_REMOVEALL = 1 UE_OPTION_REMOVEALL = 1
UE_OPTION_DISABLEALL = 2 UE_OPTION_DISABLEALL = 2

View File

@ -93,3 +93,141 @@ void StepOutStepCallBack()
else else
StepOver(StepOutStepCallBack); StepOver(StepOutStepCallBack);
} }
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;
}
static NTSTATUS NTAPI DbgUiIssueRemoteBreakin_(IN HANDLE Process)
{
HANDLE hThread;
CLIENT_ID ClientId;
NTSTATUS Status;
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 do the breakin */
Status = RtlCreateUserThread(Process,
NULL,
FALSE,
0,
0,
0x1000 /* PAGE_SIZE */,
RemoteBreakFunction,
NULL,
&hThread,
&ClientId);
/* Close the handle on success */
if(NT_SUCCESS(Status)) NtClose(hThread);
/* Return status */
return Status;
}
static NTSTATUS NTAPI DbgUiDebugActiveProcess_(IN HANDLE Process)
{
NTSTATUS Status;
/* Tell the kernel to start debugging */
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;
}
// Source: https://github.com/mirror/reactos/blob/c6d2b35ffc91e09f50dfb214ea58237509329d6b/reactos/dll/win32/kernel32/client/debugger.c#L480
BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId)
{
NTSTATUS Status, Status1;
HANDLE Handle;
/* Connect to the debugger */
Status = DbgUiConnectToDbg();
if(!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
/* Get the process handle */
Handle = ProcessIdToHandle(dwProcessId);
if(!Handle) return FALSE;
/* Now debug the process */
Status = DbgUiDebugActiveProcess_(Handle);
/* Close the handle since we're done */
Status1 = NtClose(Handle);
/* Check if debugging worked */
if(!NT_SUCCESS(Status))
{
/* Fail */
BaseSetLastNTError(Status);
return FALSE;
}
/* Success */
return TRUE;
}

View File

@ -46,5 +46,6 @@ void DebuggerReset();
void ClearProcessList(); void ClearProcessList();
void ClearTlsCallBackList(); void ClearTlsCallBackList();
void StepOutStepCallBack(); void StepOutStepCallBack();
BOOL WINAPI DebugActiveProcess_(IN DWORD dwProcessId);
#endif //_GLOBAL_DEBUGGER_H #endif //_GLOBAL_DEBUGGER_H

View File

@ -18,6 +18,7 @@ bool enginePassAllExceptions = true;
bool engineExecutePluginCallBack = true; bool engineExecutePluginCallBack = true;
bool engineAutoHideFromDebugger = false; // hardcoded bool engineAutoHideFromDebugger = false; // hardcoded
bool engineEnableDebugPrivilege = false; bool engineEnableDebugPrivilege = false;
bool engineSafeAttach = false;
char engineFoundDLLName[512] = {0}; char engineFoundDLLName[512] = {0};
char engineFoundAPIName[512] = {0}; char engineFoundAPIName[512] = {0};

View File

@ -21,6 +21,7 @@ extern bool enginePassAllExceptions;
extern bool engineExecutePluginCallBack; extern bool engineExecutePluginCallBack;
extern bool engineAutoHideFromDebugger; extern bool engineAutoHideFromDebugger;
extern bool engineEnableDebugPrivilege; extern bool engineEnableDebugPrivilege;
extern bool engineSafeAttach;
//Global.Engine.Functions //Global.Engine.Functions
void EngineInit(); void EngineInit();

View File

@ -550,7 +550,7 @@ __declspec(dllexport) bool TITCALL AttachDebugger(DWORD ProcessId, bool KillOnEx
EngineSetDebugPrivilege(GetCurrentProcess(), true); EngineSetDebugPrivilege(GetCurrentProcess(), true);
DebugRemoveDebugPrivilege = true; DebugRemoveDebugPrivilege = true;
} }
if(DebugActiveProcess(ProcessId)) if((engineSafeAttach ? DebugActiveProcess_ : DebugActiveProcess)(ProcessId))
{ {
if(engineEnableDebugPrivilege) if(engineEnableDebugPrivilege)
EngineSetDebugPrivilege(GetCurrentProcess(), false); EngineSetDebugPrivilege(GetCurrentProcess(), false);

View File

@ -42,6 +42,10 @@ __declspec(dllexport) void TITCALL SetEngineVariable(DWORD VariableId, bool Vari
{ {
engineEnableDebugPrivilege = VariableSet; engineEnableDebugPrivilege = VariableSet;
} }
else if(VariableId == UE_ENGINE_SAFE_ATTACH)
{
engineSafeAttach = VariableSet;
}
} }
__declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles) __declspec(dllexport) bool TITCALL EngineCreateMissingDependencies(char* szFileName, char* szOutputFolder, bool LogCreatedFiles)

View File

@ -469,6 +469,7 @@ typedef struct HOOK_ENTRY
#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