вот пример, как прочитать MSR из ring0. порты аналогично.
Код:
#pragma pack(1)
struct CALLGATE_DESCRIPTOR
{
WORD Offset_0_15;
WORD Selector;
union {
struct {
WORD ParamCount : 5;
WORD Unused : 3;
WORD Type : 4;
WORD System : 1;
WORD DPL : 2;
WORD Present : 1;
};
WORD misc;
};
WORD Offset_16_31;
};
typedef struct CALLGATE_DESCRIPTOR GDT_DESCRIPTOR;
struct GDTR
{
WORD wGDTLimit;
DWORD dwGDTBase;
};
#pragma pack()
unsigned gdt_index = 0;
HANDLE hSection;
GDT_DESCRIPTOR *pGDTDescriptor;
unsigned r0_p1, r0_p2;
DWORD __inline QuasiMmGetPhysicalAddress(DWORD va) {
// only for NT and for 0x80000000 <= va <= 0xA0000000
return (va & 0x1FFFF000); // physical address (page aligned)
}
DWORD ring0(void *func, DWORD param1, void *param2 = 0)
{
if (!func && !gdt_index) return 1;
if (!gdt_index) { // try to allocate GDT entry
struct GDTR gdtr;
__asm sgdt [gdtr]
pGDTDescriptor = (GDT_DESCRIPTOR*)gdtr.dwGDTBase;
if (!running9x) { // map physical memory
if (!nt_imports() || !advapi32_imports()) return 0;
UNICODE_STRING PhMem;
_RtlInitUnicodeString(&PhMem, L"\\Device\\PhysicalMemory");
OBJECT_ATTRIBUTES oa = { sizeof oa, 0, &PhMem, OBJ_CASE_INSENSITIVE };
int r = _NtOpenSection(&hSection, SECTION_MAP_WRITE, &oa);
if (r) {
r = _NtOpenSection(&hSection, READ_CONTROL | WRITE_DAC, &oa);
if (r) { printerr1(_RtlNtStatusToDosError(r), "can't open PhysicalMemory"); return 0; }
r = _SetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
0, 0, 0, 0); // this will give access to everyone!
if (r) { printerr1(r, "can't SetSecurityInfo for PhysicalMemory"); return 0; }
CloseHandle(hSection);
r = _NtOpenSection(&hSection, SECTION_MAP_WRITE, &oa);
if (r) { printerr1(_RtlNtStatusToDosError(r), "can't open section"); return 0; }
}
DWORD offset = gdtr.dwGDTBase & 0x0FFF;
pGDTDescriptor = (GDT_DESCRIPTOR*)MapViewOfFile(hSection, SECTION_MAP_WRITE, 0,
QuasiMmGetPhysicalAddress(gdtr.dwGDTBase),
align(gdtr.wGDTLimit + offset, 0x1000));
if (!pGDTDescriptor) { printerr("MapViewOfFile()"); return 0; }
pGDTDescriptor = (GDT_DESCRIPTOR*)((char*)pGDTDescriptor + (gdtr.dwGDTBase & 0x0FFF));
}
// create callgate
for (int index = 1; index < gdtr.wGDTLimit/8; index++)
if (!pGDTDescriptor[index].misc) {
gdt_index = index;
#define pCallgate pGDTDescriptor[index]
pCallgate.misc = 0xEC00;
pCallgate.Selector = running9x ? 0x28 : 0x08;
#undef pCallgate
break;
}
}
if (!gdt_index) { printf("can't find free GDT entry\n"); return 0; }
if (func) {
WORD callgate[3];
callgate[2] = (gdt_index << 3) | 3;
#define pCallgate pGDTDescriptor[gdt_index]
pCallgate.Offset_0_15 = LOWORD(func);
pCallgate.Offset_16_31 = HIWORD(func);
#undef pCallgate
*(volatile unsigned*)func; // pagein! system hangs,if function not in RAM
*(volatile unsigned*)((int)func+0x1000);
__asm pushad
__asm push ebp
__asm mov eax, [param1]
__asm mov ecx, [param2]
__asm call fword ptr [callgate]
__asm pop ebp
__asm mov [param1], eax
__asm mov [r0_p1], ecx
__asm mov [r0_p2], edx
__asm popad
return param1;
} else { // delete callgate at gdt_index
*(unsigned*)&pGDTDescriptor[gdt_index] =
*(unsigned*)((char*)&pGDTDescriptor[gdt_index]+4) = 0;
if (!running9x) {
UnmapViewOfFile(pGDTDescriptor);
CloseHandle(hSection);
}
gdt_index = 0;
return 1;
}
}
__declspec(naked) void readMSR_r0(unsigned index)
{
__asm mov ecx, eax
__asm rdmsr
__asm retf
}
unsigned readMSR_DWORD(unsigned index)
{
unsigned res = ring0(readMSR_r0, index);
ring0(0,0); // заделываем дырку назад. это можно сделать перед окончанием операции с ring0
return res;
}