📄 irqs.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 + -