IntroductionHi, this is my first article, and English is not my natural language. So first, please excuse my terrible language. This article is about hooking software/hardware interrupts and will also show you, how to retrieve device resource information from the registry. I ASSUME A LITTLE BIT OF DRIVER CODING KNOWLEDGE FOR THIS ARTICLE! Background/How this worksOk, now I'll explain, how interrupt hooking works. When an interrupt (software or hardware) occurs, the cpu uses the idt (interrupt descriptor table) to read the necessary information about how to handle that interrupt. You can get the table's memory address like this: Collapse
#pragma pack(1) // 2 works, tootypedef struct tagIDT
{
WORD wLimit;
DWORD dwBase;
} IDT, *PIDT;
#pragma pack()VOID
LoadIDT(
OUT PIDT pIdt )
{
__asm
{
MOV EAX, [pIdt] // load offset into EAX SIDT [EAX]
}
}
The command SIDT saves the idt information, which consists of the idt base address and the size(limit) of the table, to the specified memory address. Now you can read single descriptors from the table. Here is their structure:#pragma pack(1)
typedef struct tagINT_VECTOR
{
WORD wLowOffset; // LOWORD of the handler's offset WORD wSelector; // selector of the handler's offset BYTE bAccess; // 0-3: Type // 4: ?(=0) // 5-6: DPL // 7: Present BYTE wUnused; // 0, 0, 0, unused (binary) WORD wHighOffset; // HIWORD of the handler's offset} INT_VECTOR, *PINT_VECTOR;
#pragma pack(1) // 2 works, tootypedef struct tagIDT
{
WORD wLimit;
DWORD dwBase;
} IDT, *PIDT;
#pragma pack()VOID
LoadIDT(
OUT PIDT pIdt )
{
__asm
{
MOV EAX, [pIdt] // load offset into EAX SIDT [EAX]
}
}
The command SIDT saves the idt information, which consists of the idt base address and the size(limit) of the table, to the specified memory address. Now you can read single descriptors from the table. Here is their structure:#pragma pack(1)
typedef struct tagINT_VECTOR
{
WORD wLowOffset; // LOWORD of the handler's offset WORD wSelector; // selector of the handler's offset BYTE bAccess; // 0-3: Type // 4: ?(=0) // 5-6: DPL // 7: Present BYTE wUnused; // 0, 0, 0, unused (binary) WORD wHighOffset; // HIWORD of the handler's offset} INT_VECTOR, *PINT_VECTOR;
#pragma pack()
Here are the functions to load/save a descriptor:VOID
LoadINTVector(
IN PIDT pIdt,
IN UCHAR iVector,
OUT PINT_VECTOR pVector )
{
__try
{
DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
memcpy( pVector, (const void *)dwBase, sizeof(INT_VECTOR) );
}
__except( 1 )
{
DPRINT( "LoadINTVector: Exception\n" );
} DPRINT( "LoadINTVector: Vector 0x%.2X successfully dumped\n",
iVector );
} VOID
SaveINTVector(
IN PIDT pIdt,
IN UCHAR iVector,
IN PINT_VECTOR pVector )
{
__try
{
DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
Read more: Codeproject
LoadINTVector(
IN PIDT pIdt,
IN UCHAR iVector,
OUT PINT_VECTOR pVector )
{
__try
{
DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
memcpy( pVector, (const void *)dwBase, sizeof(INT_VECTOR) );
}
__except( 1 )
{
DPRINT( "LoadINTVector: Exception\n" );
} DPRINT( "LoadINTVector: Vector 0x%.2X successfully dumped\n",
iVector );
} VOID
SaveINTVector(
IN PIDT pIdt,
IN UCHAR iVector,
IN PINT_VECTOR pVector )
{
__try
{
DWORD dwBase = pIdt->dwBase + iVector * sizeof(INT_VECTOR);
Read more: Codeproject
0 comments:
Post a Comment