Tom's Guide | Tom's Hardware | Tom's Games
![]() |
![]() |
![]() |
Hi,
I need in my low-level sysinfo win32 app to read MSR register under w9x. It's privileged instructions so my app crashes. As I read the only oficial way is to write own VXD (just for one instruction?) which I dont understand even mingw32 linker cannot produce LE format needed for VXD.So other way - I found some hack using a callgate. I understand that I need to alloc new segment descriptor with RPL0 pointing to my ring0 function. I can use SGDT SLDT instruction in ring3, fine but what to do with physical address of GDT when I cannot access physical memory? I know how to do it under DPMI but it's not supported in win32 program. Any idea?

in-line ASM?
=====================================
If at first you don't succeed, you're about average.M2

I use MinGW32 GCC port for win32. It supports inlined assembler but with that crappy AT&T syntax so I'd like to minimize ASM code.
Well I succed to setup a callgate in GDT. I did't know that the mem maping of GDT is so simle. I readed something about segmentation nightmare but in other example I saw they makes simply a pointer from returned GDTR base and it works. So I can read/write GDT entries and setup my own.
But I still missing something:
1) I read that my ring0 function have to be __attribute__ ((naked)) and have some special prolog/epilog but compiler give me warning that attribute will be ingnored, why?2) what exactly I should do in ring0 func before executing my code? such some registers save, cli etc...?
3) Need to find how to exec FAR CALL in AT&T ASM.
4) I saw hardcoded callgate selector 28h in that example, why? It gives GDT index 5 with CPL=0. As I see from GDT, index 5 seems to be special with range: base=0 and limit=FFFFFFFFh is it right for all win9x?

Yeeah, I found a working code for win9x (MSVC) - this is a part of CrystalCPUID OpenSource:
//so now i try it to translate for gcc and found where i made mistake in my code...=================================================
msr9x.c:
-------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo^crystalmark*info
// Web : http://crystalmark.info/
// License : The modified BSD license
//
// Copyright 2002-2005 hiyohiyo, All rights reserved.
-------------------*/
#include <stdio.h>
#include "msr9x.h"//////////////////////////////////////////////////////////////////////
// RDMSR
//////////////////////////////////////////////////////////////////////
__declspec(naked) void Ring0ReadMSR()
{
_asm
{
rdmsr
mov [ebx],eax
mov [edi],edx
retf
}
}//////////////////////////////////////////////////////////////////////
// WRMSR
//////////////////////////////////////////////////////////////////////
__declspec(naked) void Ring0WriteMSR()
{
_asm
{
mov eax,[ebx]
mov edx,[edi]
wrmsr
retf
}
}//////////////////////////////////////////////////////////////////////
// This function makes it possible to call ring 0 code from a ring 3
// application.
//////////////////////////////////////////////////////////////////////
int CallRing0(PVOID pvRing0FuncAddr,ULONG ulECX,ULONG* pulEAX,ULONG* pulEDX)
{
GDT_DESCRIPTOR *pGDTDescriptor;
GDTR gdtr;
_asm sgdt [gdtr]
// Skip the null descriptor
pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);
// Search for a free GDT descriptor
for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
{
if (pGDTDescriptor->Type == 0 &&
pGDTDescriptor->System == 0 &&
pGDTDescriptor->DPL == 0 &&
pGDTDescriptor->Present == 0)
{
// Found one !
// Now we need to transform this descriptor into a callgate.
// Note that we're using selector 0x28 since it corresponds
// to a ring 0 segment which spans the entire linear address
// space of the processor (0-4GB).
CALLGATE_DESCRIPTOR *pCallgate;
pCallgate = (CALLGATE_DESCRIPTOR *) pGDTDescriptor;
pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
pCallgate->Selector = 0x28;
pCallgate->ParamCount = 0;
pCallgate->Unused = 0;
pCallgate->Type = 0xc;
pCallgate->System = 0;
pCallgate->DPL = 3;
pCallgate->Present = 1;
pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);
// Prepare the far call parameters
WORD CallgateAddr[3];
CallgateAddr[0] = 0x0;
CallgateAddr[1] = 0x0;
CallgateAddr[2] = (wGDTIndex << 3) | 3;
// Please fasten your seat belts!
// We're about to make a hyperspace jump into RING 0.
// MessageBox(NULL,"CallGate","START",MB_OK);
_asm mov ebx,pulEAX
_asm mov edi,pulEDX
_asm mov ecx,ulECX
_asm call fword ptr [CallgateAddr]
// We have made it !
// Now free the GDT descriptor
memset(pGDTDescriptor, 0, 8);
// Our journey was successful. Seeya.
return true;
}
// Advance to the next GDT descriptor
pGDTDescriptor++;
}
// Whoops, the GDT is full
return false;
}BOOL ReadMSR(ULONG ulECX,ULONG* pulEAX,ULONG* pulEDX)
{
CallRing0(Ring0ReadMSR,ulECX,pulEAX,pulEDX);
return TRUE;
}BOOL WriteMSR(ULONG ulECX,ULONG* pulEAX,ULONG* pulEDX)
{
CallRing0(Ring0WriteMSR,ulECX,pulEAX,pulEDX);
return TRUE;
}int main(void)
{
ULONG index=0x10, lo, hi;
ReadMSR(index,&lo,&hi);
printf("MSR[10h] = %X%Xh\n",hi,lo);
return(0);
}

![]() |
![]() |
![]() |

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.
| Ads by Google |