⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irqs.cpp

📁 用户模式下访问APIC修改中断重定向表,实现中断HOOK
💻 CPP
字号:
// irqs.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

MapViewOfSection NtMapViewOfSection;
UnmapViewOfSection NtUnmapViewOfSection;
OpenSection NtOpenSection;
Close NtClose;


USHORT selector; 

HANDLE event;



void kernelfunction(DWORD usercs,DWORD irq)
{

DWORD absent =0; BYTE gdtr[8];


//check if ioapic is present and enabled


if(irq<=23)
{

_asm 
{
 mov eax,1 
 cpuid 
 and edx, 0x00000200 
 cmp edx,0
 jne skip1
 mov absent,1
 skip1: mov ecx,0x1b 
 rdmsr 
 and eax,0x00000800
 cmp eax,0
 jne skip2
mov absent,1
}


//if APIC is enabled, get vector from it and return
skip2: if(!absent)
	   {
 //map ioapic - make sure that we map it to non-cached memory. Certainly,we have to do it only
//upon the function's very first invocation, i.e. when irq is 0	 	 

   if(!irq)
 {


_asm 
{

mov ebx,0xfec00000
or ebx,0x13
mov eax,0xc0000000
mov dword ptr[eax],ebx
 }
 }

   //now we are about to get interrupt vector
   PULONG array=NULL;

//write 0x10+2*irq to IOREGSEL
array[0]=0x10+2*irq;

// subsequent read from IOWIN returns 32 low-order bits of Redirection Table that corresponds to our IRQ. 
// 8 low-order bits are interrupt vector, corresponding to our IRQ 
DWORD vector=(array[4]&0xff);

// return interrupt vector. Dont forget that we must return with RETF, and pop 4 bytes
// off the stack


_asm
{

	//
mov eax,vector
mov esp,ebp
pop ebp
retf 4
}

}
}

//either apic is not supported, or irq is above 23,i.e. this is the last invocation
//therefore, clean up gdt and return 500 -the caller knows how to interpret it this value
_asm
{


//clean up gdt
sgdt gdtr
lea eax,gdtr
mov ebx,dword ptr[eax+2]
mov eax,0
mov ax,selector
shl eax,3
add ebx,eax
mov dword ptr[ebx],0
mov dword ptr[ebx+4],0

// adjust stack and return
mov eax,500
mov esp,ebp
pop ebp
retf 4
}


} 
void go()
{

EXPLICIT_ACCESS Access;PACL OldDacl=NULL, NewDacl=NULL; PVOID security;
HANDLE Section; NTSTATUS status; 
INIT_UNICODE_STRING(name, L"\\Device\\PhysicalMemory");
OBJECT_ATTRIBUTES oa ={sizeof(oa),0,&name,0,0,0};  
memset(&Access, 0, sizeof(EXPLICIT_ACCESS));
  NtOpenSection(&Section, WRITE_DAC | READ_CONTROL, &oa);
   
 GetSecurityInfo(Section, SE_KERNEL_OBJECT, 
                         DACL_SECURITY_INFORMATION, NULL, NULL, &OldDacl,
                         NULL, &security);
   
   Access.grfAccessPermissions = SECTION_ALL_ACCESS; 
   Access.grfAccessMode        = GRANT_ACCESS;
   Access.grfInheritance       = NO_INHERITANCE;
   Access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
   Access.Trustee.TrusteeForm  = TRUSTEE_IS_NAME;
   Access.Trustee.TrusteeType  = TRUSTEE_IS_USER;
  Access.Trustee.ptstrName = "CURRENT_USER";
  
  // update ACL
  SetEntriesInAcl(1, &Access, OldDacl, &NewDacl);
   
  
   SetSecurityInfo(Section, SE_KERNEL_OBJECT,
                         DACL_SECURITY_INFORMATION, NULL, NULL, NewDacl, 
                         NULL);
   

CloseHandle(Section);

//check how much RAM we've got
MEMORYSTATUS meminfo;GlobalMemoryStatus(&meminfo);

//get handle to RAM

status = NtOpenSection(&Section,SECTION_MAP_READ|SECTION_MAP_WRITE,&oa);
 
 
DWORD found=0,MappedSize,x;LARGE_INTEGER phys;DWORD* entry;  
PVOID DirectoryMappedAddress,TableMappedAddress; 
DWORD DirectoryOffset,TableOffset;  
 for(x=0;x<meminfo.dwTotalPhys;x+=0x1000)
   {
//map current page in RAM
MappedSize=4096; phys.QuadPart=x; DirectoryMappedAddress=0;
status = NtMapViewOfSection(Section, (HANDLE) -1, &DirectoryMappedAddress, 0L,MappedSize, &phys, &MappedSize, ViewShare,0, PAGE_READONLY);
if(status)continue;
entry=(DWORD*)DirectoryMappedAddress;

//get offsets
DirectoryOffset=(DWORD)DirectoryMappedAddress;TableOffset=(DWORD)DirectoryMappedAddress;
DirectoryOffset>>=22;TableOffset=(TableOffset>>12)&0x3ff;


//let's check if this page can be a page directory - 20 upper bits of 0x300-th entry must be 
//equal to P, and Present bit must be set in 0x300-th and V>>22-th entries. If not,proceed 
//to next page
if((entry[0x300]&0xfffff000)!=x ||(entry[0x300]&1)!=1 || (entry[DirectoryOffset]&1)!=1)
{NtUnmapViewOfSection((HANDLE) -1, DirectoryMappedAddress);continue;}


//seems to be OK for the time being. Now let's try to map a possible page table
MappedSize=4096; phys.QuadPart=(entry[DirectoryOffset]&0xfffff000); TableMappedAddress=0;
status = NtMapViewOfSection(Section, (HANDLE) -1, &TableMappedAddress, 0L,MappedSize, &phys, &MappedSize, ViewShare,0, PAGE_READONLY);

if(status){NtUnmapViewOfSection((HANDLE) -1, DirectoryMappedAddress);continue;}

//now let's check if this is really a page table If yes, 20 upper bits of (V>>12)&0x3ff-th 
//entry must be equal to P, and Present bit must be set in this entry. If the above is true, 
// P is really a page directory 
entry=(DWORD*)TableMappedAddress;
if((entry[TableOffset]&1)==1 && (entry[TableOffset]&0xfffff000)==x)found++;


NtUnmapViewOfSection((HANDLE) -1, TableMappedAddress);

//directory is found - no need to proceed further
if(found)break;
NtUnmapViewOfSection((HANDLE) -1, DirectoryMappedAddress);  
}

//get base address of gdt

BYTE gdtr[8]; DWORD gdtbase,physgdtbase; 
_asm
{
sgdt gdtr
lea eax,gdtr
mov ebx,dword ptr[eax+2]
mov gdtbase,ebx
}


//get directory and table offsets
DirectoryOffset=gdtbase;TableOffset=gdtbase;
DirectoryOffset>>=22;TableOffset=(TableOffset>>12)&0x3ff;

entry=(DWORD*)DirectoryMappedAddress;

//map page table - phys. address of it is 20 upper bits of (V-22)-th entry of page directory
MappedSize=4096; phys.QuadPart=(entry[DirectoryOffset]&0xfffff000); TableMappedAddress=0;
status = NtMapViewOfSection(Section, (HANDLE) -1, &TableMappedAddress, 0L,MappedSize, &phys, &MappedSize, ViewShare,0, PAGE_READONLY);

//phys page is in 20 upper bits of (V>>12)&0x3ff-th entry of page table- this is what we need
entry=(DWORD*)TableMappedAddress;
physgdtbase=(entry[TableOffset]&0xfffff000);
//unmap everything
NtUnmapViewOfSection((HANDLE) -1, TableMappedAddress);

NtUnmapViewOfSection((HANDLE) -1, DirectoryMappedAddress);

//now let's map gdt
PBYTE GdtMappedAddress=0;phys.QuadPart=physgdtbase;MappedSize=4096;
NtMapViewOfSection(Section, (HANDLE) -1, (PVOID*)&GdtMappedAddress, 0L,MappedSize, &phys, &MappedSize, ViewShare,0, PAGE_READWRITE);
gdtbase&=0xfff;
GdtMappedAddress+=gdtbase;

CallGateDescriptor * gate=(CallGateDescriptor * )GdtMappedAddress;

//now let's find free entry in GDT. Type of current gdt entry does not matter - Present
// bit is 48-th bit for all type of descriptors, so we interpret all descriptors as call gates
selector=1;
while(1)
{
if(!gate[selector].present)break;
selector++;
}

// now let's set up a call gate
gate[selector].offset_low  = (WORD) ((DWORD)kernelfunction & 0xFFFF);
gate[selector].selector     = 8;
gate[selector].param_count  = 1; //we will pass a parameter
gate[selector].unused    = 0;
gate[selector].type       = 0xc;     // 32-bit callgate 
      
gate[selector].dpl          = 3;      // must be 3
gate[selector].present      = 1;
gate[selector].offset_high = (WORD) ((DWORD)kernelfunction >> 16);
       

//we don't need physical memory any more
NtUnmapViewOfSection((HANDLE) -1, GdtMappedAddress);
CloseHandle(Section);

// now we will get interrupt vectors
DWORD res; DWORD resultarray[24];ZeroMemory(resultarray,sizeof(resultarray));

for (x=0;x<25;x++)
{

//let's call the function via the call gate. Are you ready???

WORD   farcall[3];farcall[2] = (selector<<3); 
_asm
 {

mov ebx,x
push ebx
call fword ptr [farcall]
mov res,eax

}

if(x==24)break;
//if the return value is 500 and this was not the final invocation, apic is not present
//inform the user about it, and that't it - it does not make sense to proceed with the loop
if(res==500)
{
MessageBox(GetDesktopWindow()," APIC is not supported","IRQs",MB_OK);
break;
}

resultarray[x]=res;
}

// inform the user
for (x=0;x<24;x++)
{
res=resultarray[x];
//if irq is not present, the return value is 0xFF, so proceed to the next entry
// if apic is not ebabled, the whole array is still filled with zeroes
if(res==0xff || res==0)continue;


// inform the user about mapping of current IRQ
char numbuff[8]; char buff[64];
strcpy(buff,"IRQ");
sprintf(numbuff,"%d\n",x);
strcat(buff,numbuff);

DWORD a=strlen(buff);
buff[a-1]='\0';
strcat(buff," maps to vector ");
sprintf(numbuff,"%X\n",res);
strcat(buff,numbuff);
a=strlen(buff);
buff[a-1]='\0';
MessageBox(GetDesktopWindow(),buff,"IRQs",MB_OK);

}

SetEvent(event);
}




int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
 
NtMapViewOfSection=(MapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtMapViewOfSection");	
NtUnmapViewOfSection=(UnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtUnmapViewOfSection");	
NtOpenSection=(OpenSection)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtOpenSection");	
NtClose=(Close)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtClose");

event=CreateEvent(0,0,0,"event");
DWORD dw;

HANDLE thread=CreateThread(0,0,(LPTHREAD_START_ROUTINE)go,0,CREATE_SUSPENDED,&dw);

SetThreadAffinityMask (thread,1);
ResumeThread(thread);
WaitForSingleObject(event,INFINITE);
	// TODO: Place code here.

	return 0;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -