Reading GDT from Ring 3

 

w.c

#include <stdio.h>

#include <windows.h>

#include <aclapi.h>

LARGE_INTEGER pAddress;

PVOID MappedAddress;

typedef struct gdtr

{

short Limit,BaseLow,BaseHigh;

} Gdtr_t, *PGdtr_t;

struct GDTINFO

{

unsigned short IDTLimit , LowIDTbase , HiIDTbase;

};

struct UNICODE_STRING

{

USHORT  Length,MaximumLength;

PWSTR  Buffer;

};

struct OBJECT_ATTRIBUTES

{

ULONG Length;

HANDLE RootDirectory;

struct UNICODE_STRING *ObjectName;

ULONG Attributes;

long a[2];

};

struct GDT

{

unsigned Limit1  : 16; // bits 15..00

unsigned Base1  : 16; // bits 15..00

unsigned Base2  : 8; // bits 23..16

unsigned Type   : 4; // segment type

unsigned S    : 1; // type (0=system, 1=code/data)

unsigned DPL   : 2; // descriptor privilege level

unsigned P    : 1; // segment present

unsigned Limit2  : 4; // bits 19..16

unsigned AVL   : 1; // available to programmer

unsigned Reserved : 1;

unsigned DB    : 1; // 0=16-bit, 1=32-bit

unsigned G    : 1; // granularity (1=4KB)

unsigned Base3  : 8; // bits 31..24

};

struct GDT *g;

void (_stdcall *RtlInitUnicode)(struct UNICODE_STRING *DestinationString, const wchar_t *SourceString);

struct UNICODE_STRING uStr;

PACL OldDacl,NewDacl;

PSECURITY_DESCRIPTOR SecDesc;

EXPLICIT_ACCESS Access;

struct OBJECT_ATTRIBUTES oAttr;

HANDLE Section;

DWORD Size;

HANDLE hntdll;

int count,addr , limit;

#define MAKELONG(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))

#define MAKEBASE(a, b , c) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16 ) | ((unsigned long) ((unsigned short) (c))) << 24 )

#define MAKELIMIT(a, b) ((unsigned long) (((unsigned short) (a)) | ((unsigned long) ((unsigned short) (b))) << 16))

#define MAKEGRANULAR(a, b) ((unsigned long) ((((unsigned short) (a)) << 12) | ((unsigned long) ((unsigned short) (b)))))

char a[100];

__declspec(dllimport) long _stdcall NtMapViewOfSection(HANDLE SectionHandle,HANDLE ProcessHandle,PVOID *BaseAddress,ULONG ZeroBits,ULONG CommitSize,PLARGE_INTEGER SectionOffset,PSIZE_T ViewSize,int InheritDisposition,ULONG AllocationType,ULONG Protect);

__declspec(dllimport) long _stdcall NtOpenSection(PHANDLE SectionHandle,ACCESS_MASK DesiredAccess,struct OBJECT_ATTRIBUTES *ObjectAttributes);

void main()

{

struct GDTINFO gdt_info;

hntdll = GetModuleHandle("ntdll.dll");

*(FARPROC *)&RtlInitUnicode = GetProcAddress(hntdll, "RtlInitUnicodeString");

RtlInitUnicode(&uStr,L"\\device\\physicalmemory");

oAttr.Length = sizeof(struct OBJECT_ATTRIBUTES);

oAttr.Attributes = 0x00000040L;

oAttr.ObjectName = &uStr;

NtOpenSection(&Section,WRITE_DAC|READ_CONTROL,&oAttr);

GetSecurityInfo(Section,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,0,0,&OldDacl,0,&SecDesc);

Access.grfAccessPermissions=SECTION_ALL_ACCESS;

Access.grfAccessMode=GRANT_ACCESS;

Access.Trustee.ptstrName="CURRENT_USER";

SetEntriesInAcl(1,&Access,OldDacl,&NewDacl);

SetSecurityInfo(Section,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,0,0,NewDacl,0);

NtOpenSection(&Section,SECTION_MAP_READ|SECTION_MAP_WRITE, &oAttr);

__asm sgdt gdt_info

g = (struct GDT*) MAKELONG(gdt_info.LowIDTbase,gdt_info.HiIDTbase);

pAddress.LowPart = (DWORD)g & 0x1FFFF000;

Size = gdt_info.IDTLimit;

NtMapViewOfSection(Section,-1,&MappedAddress,0L,Size,&pAddress,&Size,1,0,PAGE_READWRITE);

printf("%x\n",MappedAddress);

g = MappedAddress;

for(count=0;count < 12 ; count++)

{

a[0] = 0;

if ( g->Type == 3)

strcpy(a,"DATA32");

if ( g->Type == 0x0b)

strcpy(a,"CODE32");

if ( g->Type == 0x09)

strcpy(a,"TSS32");

if ( g->Type == 0x02)

strcpy(a,"LDT");

limit = MAKELIMIT(g->Limit1,g->Limit2);

if ( g->G == 1)

limit = MAKEGRANULAR(limit, 0xfff);

printf("%x %s %x %x %d %s G=%d\n", count*8,a , MAKEBASE(g->Base1,g->Base2,g->Base3),limit, g->DPL , g->P == 1 ? "P" : "NP" , g->G);

printf("Base %x %x %x Limit %x %x Type=%x\n",g->Base1,g->Base2, g->Base3,g->Limit1,g->Limit2,g->Type);

g++;

}

}

 

z.bat

del w.obj

del w.exe

cl -W0 -c w.c

link w.obj  advapi32.lib ntdll.lib

w