Move the threadstate to a backup before enabling interrupts, and fix showing the xmm state, and implement writing to xmm

This commit is contained in:
Dark Byte 2020-11-18 12:11:11 +01:00
parent dcbc8c3341
commit d8b3574ceb
3 changed files with 139 additions and 16 deletions

View File

@ -600,6 +600,8 @@ void UnloadDriver(PDRIVER_OBJECT DriverObject)
return; // return; //
} }
debugger_shutdown();
ultimap_disable(); ultimap_disable();
DisableUltimap2(); DisableUltimap2();
UnregisterUltimapPMI(); UnregisterUltimapPMI();

View File

@ -61,7 +61,7 @@ volatile struct
char b[1]; char b[1];
volatile BYTE DECLSPEC_ALIGN(16) fxstate[512]; //volatile BYTE DECLSPEC_ALIGN(16) fxstate[512];
BOOL isSteppingTillClear; //when set the user has entered single stepping mode. This is a one thread only thing, so when it's active and another single step happens, discard it BOOL isSteppingTillClear; //when set the user has entered single stepping mode. This is a one thread only thing, so when it's active and another single step happens, discard it
@ -80,6 +80,17 @@ JUMPBACK Int1JumpBackLocation;
typedef struct _SavedStack
{
BOOL inuse;
QWORD stacksnapshot[600];
} SavedStack, *PSavedStack;
criticalSection StacksCS;
int StackCount;
PSavedStack *Stacks;
void debugger_dr7_setGD(int state) void debugger_dr7_setGD(int state)
{ {
@ -191,6 +202,71 @@ void debugger_initialize(void)
//DbgPrint("DebuggerState.fxstate=%p\n",DebuggerState.fxstate); //DbgPrint("DebuggerState.fxstate=%p\n",DebuggerState.fxstate);
StackCount = getCpuCount() * 4;
Stacks = (PSavedStack*)ExAllocatePool(NonPagedPool, StackCount*sizeof(PSavedStack));
int i;
for (i = 0; i < StackCount; i++)
{
Stacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
RtlZeroMemory(Stacks[i], sizeof(SavedStack));
}
}
void debugger_shutdown(void)
{
if (Stacks)
{
int i;
for (i = 0; i < StackCount; i++)
{
if (Stacks[i])
{
ExFreePool(Stacks[i]);
Stacks[i] = NULL;
}
}
ExFreePool(Stacks);
Stacks = NULL;
}
}
void debugger_growstack()
//only call when the critical section has been obtained
{
if (Stacks)
{
int newStackCount = StackCount * 2;
int i;
PSavedStack *newStacks;
newStacks = (PSavedStack*)ExAllocatePool(NonPagedPool, newStackCount * sizeof(PSavedStack));
if (newStacks)
{
for (i = 0; i < StackCount; i++)
newStacks[i] = Stacks[i];
for (i = StackCount; i < newStackCount; i++)
{
newStacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
if (newStacks[i])
RtlZeroMemory(newStacks[i], sizeof(SavedStack));
else
{
ExFreePool(newStacks);
return;
}
}
ExFreePool(Stacks);
Stacks = newStacks;
}
}
} }
void debugger_setInitialFakeState(void) void debugger_setInitialFakeState(void)
@ -469,10 +545,9 @@ NTSTATUS debugger_getDebuggerState(PDebugStackState state)
state->r13=DebuggerState.LastStackPointer[si_r13]; state->r13=DebuggerState.LastStackPointer[si_r13];
state->r14=DebuggerState.LastStackPointer[si_r14]; state->r14=DebuggerState.LastStackPointer[si_r14];
state->r15=DebuggerState.LastStackPointer[si_r15]; state->r15=DebuggerState.LastStackPointer[si_r15];
#endif #endif
memcpy(state->fxstate, (void *)DebuggerState.fxstate,512); memcpy(state->fxstate, (void *)&DebuggerState.LastStackPointer[si_xmm],512);
//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow //generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
@ -481,7 +556,6 @@ NTSTATUS debugger_getDebuggerState(PDebugStackState state)
//priv level change, so the stack info was pushed as well //priv level change, so the stack info was pushed as well
state->rsp=DebuggerState.LastStackPointer[si_esp]; state->rsp=DebuggerState.LastStackPointer[si_esp];
state->ss=DebuggerState.LastStackPointer[si_ss]; state->ss=DebuggerState.LastStackPointer[si_ss];
} }
else else
{ {
@ -586,6 +660,8 @@ NTSTATUS debugger_setDebuggerState(PDebugStackState state)
DebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14; DebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14;
DebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15; DebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15;
#endif #endif
memcpy((void *)&DebuggerState.LastStackPointer[si_xmm], state->fxstate, 512);
if (!DebuggerState.globalDebug) if (!DebuggerState.globalDebug)
{ {
@ -670,14 +746,7 @@ int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs,
DebuggerState.CausedByDBVM = causedbyDBVM; DebuggerState.CausedByDBVM = causedbyDBVM;
#ifdef AMD64
//_fxsave(DebuggerState.fxstate);
#else
__asm
{
// fxsave [DebuggerState.fxstate]
}
#endif
@ -1258,19 +1327,70 @@ int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
//if (1) return 1; //if (1) return 1;
enableInterrupts(); //save the state of the thread to a place that won't get overwritten
//todo: breaks 32-bit
int i;
BOOL NeedsToGrowStackList = FALSE;
UINT_PTR *newStackPointer = NULL;
csEnter(&StacksCS);
for (i = 0; i < StackCount; i++)
{ {
int rs=1; if (Stacks[i]->inuse == FALSE)
{
Stacks[i]->inuse = TRUE;
newStackPointer = (UINT_PTR *)Stacks[i]->stacksnapshot;
RtlCopyMemory(newStackPointer, stackpointer, 600 * 8);
if (i > StackCount / 2)
NeedsToGrowStackList = TRUE;
break;
}
}
enableInterrupts();
//grow stack if needed
if (NeedsToGrowStackList)
debugger_growstack();
csLeave(&StacksCS);
{
int rs=1;
int RestoreStack = newStackPointer != NULL;
//DbgPrint("calling breakpointHandler_kernel\n"); //DbgPrint("calling breakpointHandler_kernel\n");
if (newStackPointer == NULL) //fuck
newStackPointer = stackpointer;
rs = breakpointHandler_kernel(stackpointer, currentdebugregs, LBR_Stack, causedbyDBVM); rs = breakpointHandler_kernel(newStackPointer, currentdebugregs, LBR_Stack, causedbyDBVM);
//DbgPrint("After handler\n"); //DbgPrint("After handler\n");
if (RestoreStack) //restore the stack
{
RtlCopyMemory(stackpointer, newStackPointer, 600 * 8);
csEnter(&StacksCS);
Stacks[i]->inuse = FALSE;
csLeave(&StacksCS);
}
//DbgPrint("rs=%d\n",rs); //DbgPrint("rs=%d\n",rs);
disableInterrupts(); disableInterrupts();
//restore the
//we might be on a different CPU now //we might be on a different CPU now
if (DebuggerState.globalDebug) if (DebuggerState.globalDebug)

View File

@ -51,6 +51,7 @@ typedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnReadsAndWr
typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/, bl_4byte=3} BreakLength; typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/, bl_4byte=3} BreakLength;
void debugger_initialize(void); void debugger_initialize(void);
void debugger_shutdown(void);
int debugger_initHookForCurrentCPU(void); int debugger_initHookForCurrentCPU(void);
int debugger_setGlobalDebugState(BOOL state); int debugger_setGlobalDebugState(BOOL state);
void debugger_setStoreLBR(BOOL state); void debugger_setStoreLBR(BOOL state);