📄 dbkfunc.c.svn-base
字号:
//#include "C:\WINDDK\3790\inc\ifs\w2k\ntifs.h"
#include "DBKFunc.h"
#include "vmxhelper.h"
#ifndef AMD64
void interrupt1( void );
void interrupt3( void );
void interruptD1( void );
#endif
ULONG Int1Address;
ULONG Int3Address;
ULONG IntD1Address;
INT_VECTOR NewInt1;
INT_VECTOR NewIntD1;
unsigned __int64 readMSR(ULONG msr)
{
ULONG a,b;
__asm
{
push ecx
push eax
push edx
mov ecx,msr
rdmsr
mov [a],eax
mov [b],edx
pop edx
pop eax
pop ecx
}
return ((INT64)b<<32) + a;
}
ULONG getCR3(void)
{
ULONG cr3reg;
__asm
{
mov eax,CR3
mov cr3reg,eax
}
return cr3reg;
}
ULONG getCR4(void)
{
#ifndef AMD64
ULONG cr4reg=0;
__try
{
__asm
{
__emit 0x0f //-|
__emit 0x20 //-|-mov eax,cr4
__emit 0xe0 //-|
mov cr4reg,eax
}
}
__except(1)
{
DbgPrint("Error getting CR4\n");
}
return cr4reg;
#else
return 0;
#endif
}
void setCR4(ULONG cr4reg)
{
__asm
{
mov eax,cr4reg
__emit 0x0f //-|
__emit 0x22 //-|-mov cr4,eax
__emit 0xe0 //-|
}
return;
}
unsigned long long getTSC(void)
{
ULONG a,b;
unsigned long long result;
__asm
{
push eax
push edx
rdtsc
mov [a],eax
mov [b],edx
pop edx
pop eax
}
result=a+((unsigned long long)(b) << 32);
return result;
}
void StopDebugging(void)
{
DebuggedProcessID=0;
ChangeRegs[0].Active=FALSE;
ChangeRegs[1].Active=FALSE;
ChangeRegs[2].Active=FALSE;
ChangeRegs[3].Active=FALSE;
ChangeRegistersOnBP=FALSE;
DbgPrint("Stopped the debugger\n");
//the int hooks can stay, they don't hurt anyhow
}
void StopChangeRegOnBP(int DebugRegNR)
{
int i;
DbgPrint("DBKKERNEL:StopChangeRegOnBP %d\n",DebugRegNR);
ChangeRegs[DebugRegNR].Active=FALSE;
ChangeRegs[DebugRegNR].BreakAddress=0;
for(i=0; i<4; i++)
{
if (ChangeRegs[DebugRegNR].Active)
{
ChangeRegistersOnBP=TRUE;
DbgPrint("Still one debugreg active, so keep changing others\n" );
return;
}
}
ChangeRegistersOnBP=FALSE;
}
BOOLEAN ChangeRegOnBP(DWORD ProcessID, int DebugRegNR, PChangeReg CR)
{
//This gets called just before the usermode app sets the debugreg
//CR->Active ignored in this case, becomes true
DbgPrint("Going to enable the debugger to set a change reg breakpoint on ProcessID %d(%x) for debugreg %d",ProcessID,ProcessID,DebugRegNR);
CR->Active=TRUE;
ChangeRegs[DebugRegNR]=*CR;
ChangeRegs[DebugRegNR].Active=TRUE;
DebuggedProcessID=ProcessID;
PsLookupProcessByProcessId((PVOID)ProcessID,&DebuggedProcessPEPROCESS);
ChangeRegistersOnBP=TRUE;
return TRUE; //always
}
BOOLEAN DebugProcess(DWORD ProcessID, DWORD Address, BYTE Length, BYTE RWE)
{
DbgPrint("Going to debug a process for 1 process+debug address\nProcessID=%d (%x)\n",ProcessID,ProcessID);
//EventsMissed=0;
DebuggedProcessID=ProcessID;
PsLookupProcessByProcessId((PVOID)ProcessID,&DebuggedProcessPEPROCESS);
DebuggedAddress=Address;
DebuggedAddressLength=Length;
DebuggedAddressRWE=RWE;
DbgPrint("DebuggedAddress=%x\n",DebuggedAddress);
/*
setting the debug registers in the context will be done from usermode (unless I figure out how to call
NtSetContextThread which doesn't seem to be in ntos so requires user32.sys which is fucking buggy to use
but, the threadid's can be retrieved using a toolhelpsnapshot, (or a notify routine for created threads)
and can be opened using OpenThread (win2k+ but I dont give a shit about that...)
*/
DbgPrint("Still here so I gues it works!\n");
return TRUE;
}
unsigned short GetTR(void)
{
unsigned short result;
#ifndef AMD64
__asm
{
STR AX
mov result,ax
}
#endif;
return result;
}
void GetGDT(PGDT pGdt)
{
#ifndef AMD64
__asm
{
MOV EAX, [pGdt]
SGDT [EAX]
}
#endif;
}
void GetLDT(PGDT pLdt)
{
#ifndef AMD64
__asm
{
MOV EAX, [pLdt]
SLDT [EAX]
}
#endif;
}
void GetIDT(PIDT pIdt)
{
//I should do this for each logical processor
#ifndef AMD64
__asm
{
MOV EAX, [pIdt]
SIDT [EAX]
}
#endif;
}
void SetIDT(PIDT pIdt)
{
__asm
{
MOV EAX, [pIdt]
LIDT [EAX]
}
}
BOOLEAN HookInt1(void)
{
#ifndef AMD64
IDT idt;
//DbgPrint("Going to hook int1\n");
GetIDT(&idt);
__try
{
if (OriginalInt1.wHighOffset==0)
{
DebugReg7 DR_7;
//DbgPrint("New hook, so storing the original Int1Handler\n");
OriginalInt1=idt.vector[1];
NewInt1=idt.vector[1];
//NewIntD1=idt.vector[0xd1];
Int1Address=idt.vector[1].wLowOffset+(idt.vector[1].wHighOffset << 16); //save the original address of the int3 handler
NewInt1.wLowOffset=(WORD)&interrupt1;
NewInt1.wHighOffset=(WORD)((DWORD)&interrupt1 >> 16);
if (globaldebug)
{
//set the global debug bit and start tasksurfing
__asm
{
mov eax,dr7
mov DR_7,eax
}
DR_7.GD=1;
__asm
{
mov eax,DR_7
mov dr7,eax
}
}
}
//now overwrite the vector so it points to my handler
//DbgPrint("Changing the vector to point to my handler\n");
if (vmxusable)
{
DbgPrint("using VMX idt1 bypass\n");
__try
{
vmx_redirect_interrupt1(1, 0, NewInt1.wSelector, (DWORD)&interrupt1); //idt bypass hook
}
__except(1)
{
DbgPrint("VMX idt1 bypass failed\n");
return FALSE;
}
}
else
{
__asm
{
PUSHFD //no idea why, I doubt it's usefull, but let's use it too....
CLI
}
idt.vector[1]=NewInt1;
__asm
{
STI
POPFD
}
}
return TRUE;
}
__except(1)
{
DbgPrint("Exception while hooking int1\n");
return FALSE;
}
#else
return FALSE;
#endif
}
BOOLEAN HookInt3(void)
{
#ifndef AMD64
IDT idt;
//DbgPrint("Going to hook int3\n");
GetIDT(&idt);
__try
{
OriginalInt3=idt.vector[3];
Int3Address=idt.vector[3].wLowOffset+(idt.vector[3].wHighOffset << 16); //save the original address of the int3 handler
//now overwrite the vector so it points to my handler
__asm
{
PUSHFD //no idea why, I doubt it's usefull, but let's use it too....
CLI
}
idt.vector[3].wLowOffset=(WORD)&interrupt3;
idt.vector[3].wHighOffset=(WORD)((DWORD)&interrupt3 >> 16);
__asm
{
STI
POPFD
}
//DbgPrint("Hooking int3 was successful\n");
return TRUE;
}
__except(1)
{
DbgPrint("Exception while hooking int3\n");
return FALSE;
}
#else
return FALSE;
#endif
}
int cpunr(void)
{
unsigned int b;
__asm
{
push eax
push ebx
push ecx
push edx
mov eax,1
cpuid
mov [b],ebx
pop edx
pop ecx
pop ebx
pop eax
}
return (b >> 24)+1;
}
struct {
ULONG DR0;
ULONG DR1;
ULONG DR2;
ULONG DR3;
ULONG DR6;
ULONG DR7;
} CPUDebugRegisterState[256]; //might optimize this in the future by allocating only the needed part... for now, fuck memory
ULONG r1,r2;
ULONG __stdcall GeneralHandler(IN ULONG iInt,IN PULONG Stacklocation )
{
#ifndef AMD64
/* //check the current priviledge level
DbgPrint("Welcome to my int handler. (I need to find out how this instruction gets me in ring0)\n");
DbgPrint("Processid=%d (%x)\n",PsGetCurrentProcessId(),PsGetCurrentProcessId());
*/
ULONG result=0; //by default do handle the interrupt by the os
ULONG DR_0,DR_1,DR_2,DR_3,ef;
DebugReg6 DR_6;
DebugReg7 DR_7;
/*
DbgPrint("Int1: CPUnr=%d",cpunr());
*/
__asm{
mov eax,dr0
mov DR_0,eax
mov eax,dr1
mov DR_1,eax
mov eax,dr2
mov DR_2,eax
mov eax,dr3
mov DR_3,eax
mov eax,dr6
mov DR_6,eax
mov eax,dr7
mov DR_7,eax
pushfd
pop eax
mov ef,eax
};
/*
DbgPrint("Hello from int1\n");
DbgPrint("eax=%x\n",Stacklocation[-1]);
DbgPrint("ebx=%x\n",Stacklocation[-4]);
DbgPrint("ecx=%x\n",Stacklocation[-2]);
DbgPrint("edx=%x\n",Stacklocation[-3]);
DbgPrint("esi=%x\n",Stacklocation[-7]);
DbgPrint("edi=%x\n",Stacklocation[-8]);
DbgPrint("ebp=%x\n",Stacklocation[-6]);
DbgPrint("ss=%x\n",Stacklocation[4]);
DbgPrint("esp=%x\n",Stacklocation[3]);
DbgPrint("eflags=%x\n",Stacklocation[2]);
DbgPrint("cs=%x\n",Stacklocation[1]); //it was a break
DbgPrint("eip=%x\n",Stacklocation[0]); //it was a break
DbgPrint("DR0=%x\n",DR_0);
DbgPrint("DR1=%x\n",DR_1);
DbgPrint("DR2=%x\n",DR_2);
DbgPrint("DR3=%x\n",DR_3);
DbgPrint("DR6=%x\n",DR_6);
DbgPrint("DR7=%x\n",DR_7);
DbgPrint("Int1 DR6=%x DR7=%x int_eflags=%x\n",DR_6,DR_7,ef);*/
if (globaldebug)
{
DR_7.GD=1; //re-set GD bit , but don't set it in the DR7 register yet
if (DR_6.BD)
{
char *instruction=(char *)(Stacklocation[0]);
int ip;
int rm,reg;
int id=cpunr();
PEFLAGS flags;
//gd bit is already 0 now
flags=(PEFLAGS)(&Stacklocation[2]);
//flags->RF=1;
DR_6.BD=0;
__asm
{
mov eax,DR_6
mov dr6,eax
}
//check which instruction it is, read/write, has prefixes etc...
//which registers used, and store that / retrieve it
//0f 21 = read
//0f 23 = write
for (ip=0; instruction[ip]!=0x0f; ip++) ;
reg=(instruction[ip+2] >> 3) & 7; //affected debug register
rm=instruction[ip+2] & 7; //used general purpose register
//get current cpu id to find out what drx should be or where to write the current state to
if (instruction[ip+1] == 0x21)
{
//emulate read: rm,reg
//return what the process has set it to
switch (reg)
{
case 0:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR0; //-1-rm because it's a inverse and starts at -1
break;
case 1:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR1;
break;
case 2:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR2;
break;
case 3:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR3;
break;
case 4:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR6;
break;
case 5:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR7;
break;
case 6:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR6;
break;
case 7:
Stacklocation[-1-rm]=CPUDebugRegisterState[id].DR7;
break;
}
}
else if (instruction[ip+1] == 0x23)
{
ULONG debugregvalue=Stacklocation[-1-rm];
//emulate write: reg,rm
switch (reg)
{
case 0:
CPUDebugRegisterState[id].DR0=debugregvalue; //-1-rm because it's a inverse and starts at -1
//and set the real register if allowed
__asm
{
mov eax,debugregvalue
mov dr0,eax
}
break;
case 1:
CPUDebugRegisterState[id].DR1=debugregvalue;
__asm
{
mov eax,debugregvalue
mov dr1,eax
}
break;
case 2:
CPUDebugRegisterState[id].DR2=debugregvalue;
__asm
{
mov eax,debugregvalue
mov dr2,eax
}
break;
case 3:
CPUDebugRegisterState[id].DR3=debugregvalue;
__asm
{
mov eax,debugregvalue
mov dr3,eax
}
break;
case 4:
CPUDebugRegisterState[id].DR6=debugregvalue;
__asm
{
mov eax,debugregvalue
mov dr6,eax
}
break;
case 5:
CPUDebugRegisterState[id].DR7=debugregvalue;
break;
case 6:
CPUDebugRegisterState[id].DR6=debugregvalue;
__asm
{
mov eax,debugregvalue
mov dr6,eax
}
break;
case 7:
CPUDebugRegisterState[id].DR7=debugregvalue;
break;
}
}
else
DbgPrint("Something crappy has just happened\n");
//if a global breakpoint is set check which debug breakpoint can be used and configure it
//DebuggedAddress and DebuggedAddressLength
*(ULONG *)&DR_7=CPUDebugRegisterState[id].DR7;
DR_7.GD=1; //I could do a or operation in assembler, but i'm lazy
if (DebuggedProcessID!=0)
{
__asm
{
mov eax,DebuggedAddress
mov dr0,eax
}
DR_7.G0=1;
DR_7.L0=1;
DR_7.LEN0=3;
DR_7.RW0=3;
}
__asm
{
mov eax,DR_7
mov dr7,eax //don't touch debug regs now
};
Stacklocation[0]+=ip+3;
return 1;
}
}
//DbgPrint("DebuggedProcessID==%d\n", DebuggedProcessID);
if (DebuggedProcessID==0)
return 0; //no debugging going on
//DbgPrint("Int1: PsGetCurrentProcess()=%x DebuggedProcessPEPROCESS=%x\n", (ULONG)PsGetCurrentProcess(), (ULONG)DebuggedProcessPEPROCESS);
if ((ULONG)PsGetCurrentProcess()==(ULONG)DebuggedProcessPEPROCESS)
{
//this is inside the memory of my debugged process
//DbgPrint("(ULONG)PsGetCurrentProcess()==(ULONG)DebuggedProcessPEPROCESS\n");
//DbgPrint("iInt=%d\n",iInt);
if (iInt==1)
{
if ((ULONG)PsGetCurrentProcessId()!=DebuggedProcessID)
{
//different processid, probably caused by a keattachprocess
//DbgPrint("Access by other process :%d\n",(ULONG)PsGetCurrentProcessId());
}
/*
DbgPrint("Hello from int1\n");
DbgPrint("eax=%x\n",Stacklocation[-1]);
DbgPrint("ebx=%x\n",Stacklocation[-4]);
DbgPrint("ecx=%x\n",Stacklocation[-2]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -