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