Click here to Skip to main content
Click here to Skip to main content

Tagged as

Entering Ring 0 using minimalistic approach

, 21 Jun 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Kernel adventures of brave developer and other scary tales

What this article is not

This article is meant for people who need easer way of Ring 0 (developing debugging profiling, performance monitoring tools, etc.) and therefore already know what Ring 0 is. Considering how many great tutorials about Protected Mode are already out there. Like Intel 80386 Reference Programmer's Manual or Protected mode programming tutorial it would be like bringing wood to forest. But greatest source are of course Intel and Amd cpu manufacturer manuals themselves.

Introduction

I recently started development of program called SysMon. It is utility simmilar to RegMon or FileMon but it will monitor systemcalls instead. It requires reading some registers (MSRs etc) that are unfortunately accessible only in mysterious ring 0 land. yet thanks to great idea sharing sites like CodeProject I found interesting way how tho get this data without all that inhuman kernel driver debugging galore just to read one register. Plus printf is printf Wink | ;)

Background

I was inspired by many great articles for example here on CodeProject those from old Kernel Adventurer Anton Bassov. Unfortunately many of those were relaying on some offsets which as we know change all the time. Since that code was not working on my version of windows I started windows version independent offset free approach plus I am minimalist so I decimated and decimated and this is the last extract of that mysterious kernel manna. I didn't tested it on vista.

The code

If you remember Msdos days you will some day realize that Windows itself is just another oversized protected mode Application. If you look at any protected mode manual you will find that Intel did build 3 ways of switching between ring levels. Interrupts syscalls or Call Gates ( don't bother, he never picks up )... Anyway Call Gate is exactly what this code does since it's simplest. We read Global Descriptor Table and write back address of our function on first free spot + desired ring level. So when we call this function it begins running at desired ring 0 but returns to previous ring 3 level. As an example I read cr0 register and return some text. So Enjoy it. And I am open to any further ideas how to make this code even simpler.

Word of Advice

Use Windows XP images and VirtualPC from here or similar software to test any changes. As is true with any Device Driver Development. This is Ring 0. Any slightest mistake usually means immediate Reset or Frozen computer.

VirtualPc 2007 have Bug thou. it don't have implemented sgdt in ring 3 so you need to replace this instruction with fixed value while testing.

Following values are valid For XP SP2:

// __asm sgdt gdtr
gdtr.base = 0x8003f000;
gdtr.limit = 0x03ff;

#include    <span class="code-keyword"><windows.h></span>
#include    <span class="code-keyword"><stdio.h></span>

#pragma pack(1)

struct  CALL_GATE { WORD addrlo; WORD seg; BYTE arg:5; BYTE u:3; BYTE typ:5; BYTE dpl:2; BYTE pres:1; WORD addrhi; } ;

#define Virtual(a,b,c,d) { struct VIRTUAL{void* A;void* B;DWORD C;}; VIRTUAL v={(void*)(a),b,c}; hr=NtSystemDebugControl(d,&v,sizeof(v),0,0,0); }


void Ring0( DWORD cs, char*& text ) {
    text = "Hello World from Ring 0 \n";        
    __asm mov eax,cr0
    __asm leave
    __asm retf 4
}

int main() {

    LONG (NTAPI *NtSystemDebugControl)     (int,void*,DWORD,void*,DWORD,DWORD*);
    *(DWORD*)   &NtSystemDebugControl    =(DWORD)GetProcAddress(LoadLibrary("ntdll"),"NtSystemDebugControl");

    TOKEN_PRIVILEGES pv={1},po; pv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; HANDLE t; int hr; DWORD no;
    
    // This will enable NtSystemDebugControl usage
    hr = LookupPrivilegeValue(  0, SE_DEBUG_NAME, &pv.Privileges[0].Luid );
    hr = OpenProcessToken(      GetCurrentProcess(), TOKEN_ALL_ACCESS,&t);
    hr = AdjustTokenPrivileges( t,0,&pv,sizeof(po),&po, &no);
    
    // This ensures that on multi cpu/core systems we patch the right GDT for right cpu
    hr = SetThreadAffinityMask (GetCurrentThread(),1); Sleep(100);

    // We read GDT table
    LDT_ENTRY gdt[1000]={0}; struct {WORD limit;DWORD base;} gdtr; __asm sgdt gdtr
    
    // Find free spot
    Virtual(gdtr.base, &gdt,gdtr.limit,8);    for(int gate=1;gate<100;gate++)    { if(!gdt[gate].HighWord.Bits.Pres) break; }    
    
    // Construct Call Gate pointing to Ring0 proc and write it there
    DWORD addr=(DWORD)Ring0; CALL_GATE g={addr&0xffff,8,1,0,12,3,1,addr>>16}; Virtual(gdtr.base+gate*8, &g,8,9); 
    
    // Quite ugly way to do far call 
    WORD farcall[3]={0,0,(gate<<3)}; char* param=0,**p=&param; long result=0; 

    // Switch from Ring 3 to Ring 0 is just normal call ;)
    __asm push p
    __asm call fword ptr [farcall]
    __asm mov  result, eax

    // Cleanup Call Gate from GDT
    __int64 c=0; Virtual(gdtr.base+gate*8, &c,8,9); 

    printf("\n %s\n  CR0 = %X ",param,result); getchar();    

    return 0;
}
   

Locations of visitors

Locations of visitors to this page

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ladislav Nevery
Software Developer (Senior)
Slovakia Slovakia
Past Projects:
[Siemens.sk]Mobile network software: HLR-Inovation for telering.at (Corba)
Medical software: CorRea module for CT scanner
[cauldron.sk]Computer Games:XboxLive/net code for Conan, Knights of the temple II, GeneTroopers, CivilWar, Soldier of fortune II
[www.elveon.com]Computer Games:XboxLive/net code for Elveon game based on Unreal Engine 3
ESET Reasearch.
Looking for job

Comments and Discussions

 
GeneralMy vote of 5 Pinmembergndnet5-Jan-11 23:36 
GeneralGreat Article PinmemberShaneMcDonald11-Nov-10 14:05 
QuestionHow to go into ring0 Pinmemberredvc28-May-10 17:10 
GeneralAwesome! PinmemberBartosz Wojcik11-Jan-10 17:02 
GeneralMore arguments Pinmemberunix_soul31-Jul-09 2:31 
QuestionHelp Please? PinmemberTurion18-Jul-09 20:09 
Generalproblem occured beacuse of "__asm call fword ptr [farcall]" Pinmemberwyybaba28-Mar-09 20:03 
GeneralVista/Windows Server 2003 SP1 Pinmemberfrench_rt1525-Nov-08 6:46 
GeneralRe: Vista/Windows Server 2003 SP1 Pinmembermaddin5-Jul-11 2:23 
Generalx64... [modified] PinmemberMichael Chourdakis23-Jul-08 23:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 21 Jun 2008
Article Copyright 2008 by Ladislav Nevery
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid