|
|
Comments and Discussions
|
|
 |
|

|
Small changes to work on VS2008 Windows XP included below. No luck with Windows 7. Overall Great Article.
#include <windows.h>
#include <stdio.h>
#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(TEXT("ntdll")),"NtSystemDebugControl");
TOKEN_PRIVILEGES pv={1},po; pv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; HANDLE t; int hr; DWORD no;
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);
hr = SetThreadAffinityMask (GetCurrentThread(),1); Sleep(100);
LDT_ENTRY gdt[1000]={0}; struct {WORD limit;DWORD base;} gdtr; __asm sgdt gdtr
int gate;
Virtual(gdtr.base, &gdt,gdtr.limit,8); for(gate=1;gate<100;gate++) { if(!gdt[gate].HighWord.Bits.Pres) break; }
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);
WORD farcall[3]={0,0,(gate<<3)}; char* param=0,**p=¶m; long result=0;
__asm push p
__asm call fword ptr [farcall]
__asm mov result, eax
__int64 c=0; Virtual(gdtr.base+gate*8, &c,8,9);
printf("\n %s\n CR0 = %X ",param,result); getchar();
return 0;
}
|
|
|
|

|
First, I'm a newer for the ring0.
I have two question.
1. How to into the ring0? where's the code?
2. How to work with function Ring0Call()? Do it execute a function, then go into ring0?
|
|
|
|

|
I haven't seen anything similar since z0mbie's ring3->ring0 tricks hehe
PS. Do you have your GPU related source codes available anywhere?
|
|
|
|

|
What about if user want to use function Ring0 with 2 or 3 arguments like
void Ring0(DWORD cs, char *text, long *, char *text);
|
|
|
|

|
Your code is great for entering Ring 0! I just have a problem actually using this ability to call kernel functions.
When I call a kernel function such as ObQueryNameString, it sometimes works correctly, but I typically get an access violation reading 0x00000000 when I run it the first time, and it may BSOD depending on what I'm querying. Here's my entire code; I'm using VC++ 2008 and linking only to NTDLL.dll (I'm delay-loading the kernel and not linking to any VC++ runtimes). I modified your code a bit, to make it more generic.
#pragma pack (push, 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;
};
struct SYSDBG_VIRTUAL
{
void* Address;
void* Buffer;
ULONG Length;
};
#pragma pack (pop)
struct QUERY_OBJECT_NAME_INFO
{
PVOID Object;
PVOID Buffer;
ULONG Length;
ULONG* LengthNeeded;
NTSTATUS Result;
};
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN struct _OBJECT_TYPE* ObjectType, IN KPROCESSOR_MODE AccessMode, IN struct _ACCESS_STATE* PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
{
OPEN_OBJECT_BY_NAME_INFO info = {0};
info.ObjectAttributes = ObjectAttributes;
info.ObjectType = ObjectType;
info.AccessMode = AccessMode;
info.PassedAccessState = PassedAccessState;
info.DesiredAccess = DesiredAccess;
info.ParseContext = ParseContext;
info.Handle = Handle;
NTSTATUS result = SystemCall((KERNELPROC)ObOpenObjectByNameInternal, &info);
if (NT_SUCCESS(result)) { result = info.Result; }
return result;
}
void NTAPI ObQueryNameStringInternal(IN OUT QUERY_OBJECT_NAME_INFO* pInfo)
{ pInfo->Result = (*pObQueryNameString)(pInfo->Object, pLocalBuffer, pInfo->Length, &lengthNeededLocal); }
void Ring0Call(DWORD, SYSCALL_INFO* info)
{
__try { (*info->Function)(info->Context); } __except (1) { }
__asm
{
mov eax, cr0
leave
retf 4
}
}
struct SYSCALL_INFO
{
KERNELPROC Function;
PVOID Context;
};
__inline NTSTATUS ReadVirtual(void* address, void* buffer, ULONG length) { SYSDBG_VIRTUAL v = { address, buffer, length }; return NtSystemDebugControl(8, &v, sizeof(v), 0, 0, 0); }
__inline NTSTATUS WriteVirtual(void* address, void* buffer, ULONG length) { SYSDBG_VIRTUAL v = { address, buffer, length }; return NtSystemDebugControl(9, &v, sizeof(v), 0, 0, 0); }
NTSTATUS SystemCall(KERNELPROC function, PVOID context)
{
NTSTATUS status;
THREAD_BASIC_INFORMATION threadInfo;
ULONG retLength;
status = NtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &threadInfo, sizeof(threadInfo), &retLength);
if (!NT_SUCCESS(status)) { return status; }
LDT_ENTRY gdt[1000] = {0};
short gate;
SYSCALL_INFO info = { function, context };
DWORD addr = (DWORD)Ring0Call;
CALL_GATE callGate = { addr & 0xFFFF, 8, 1, 0, 12, 3, 1, addr >> 16 };
#pragma pack (push, 1)
struct { WORD limit; DWORD base; } gdtr;
#pragma pack (pop)
KAFFINITY one = 1;
status = NtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &one, sizeof(one));
if (!NT_SUCCESS(status)) { return status; }
__try
{
Sleep(100);
int threadPriority = GetThreadPriority(GetCurrentThread());
if (threadPriority != THREAD_PRIORITY_ERROR_RETURN) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); }
__try
{
__asm sgdt gdtr
status = ReadVirtual((void*)gdtr.base, &gdt, gdtr.limit);
if (!NT_SUCCESS(status)) { return status; }
for (gate = 1; gate < 100; gate++)
{ if (!gdt[gate].HighWord.Bits.Pres) break; }
status = WriteVirtual((void*)(gdtr.base + gate * 8), &callGate, sizeof(callGate));
if (!NT_SUCCESS(status)) { return status; }
}
__finally { SetThreadPriority(GetCurrentThread(), threadPriority); }
}
__finally { NtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &threadInfo.AffinityMask, sizeof(threadInfo.AffinityMask)); }
__try
{
short farcall[3] = { 0, 0, gate << 3 };
PVOID pInfo = &info;
long result;
__asm
{
push pInfo
call fword ptr [farcall]
mov result, eax
}
}
__finally
{
__int64 c = 0;
status = WriteVirtual((void*)(gdtr.base + gate * 8), &c, sizeof(c));
}
return status;
}
void mainCRTStartup()
{
PVOID pSomeObject; hKernel = LoadLibrary(__TEXT("ntkrnlpa.exe"));
pObQueryNameString = (ObQueryNameStringPointer)GetProcAddress(hKernel, "ObQueryNameString");
char objectName[4096];
ULONG needed;
NTSTATUS status = ObQueryNameString(pSomeObject, objectName, sizeof(objectName), &needed);
}
Just run this in a new project with the settings I mentioned and you'll see what I mean.
|
|
|
|

|
hi:
i readed your document and then i try to test your code. i copy all your code to my vc++ project. i build a Test4.exe. but when i run the Test4.exe some problem occured. windows a display a dialog box and show me "Test4.exe has encountered a problem and needs to close. We are sorry for the inconvenience.". i debug this program and find the line
__asm call fword ptr [farcall]
cause this problem. it seems that windows found my bad appempt and terminated my program. i use windows XP sp2.please help me ,what's the problem of this?
|
|
|
|

|
Congratulation ! Works great on my XP SP2 !
However, documentation seems say that this code don't work on Vista and Windows Server 2003 SP1... Microsoft don't want let us access phisical memory with NtSystemDebugControl and CreateFile/"\\Device\\PhysicalMemory".
Is it the case ?
Is there any workaround ?
|
|
|
|

|
Will NEVER.
call gates work only til Windows XP 32 Bit. From Windows XP 64 Bit (Windows 2003 Server Kernel) Microsoft patched many Windows kernel security holes beside entering kernel mode through call gates.
Cheers
Maddin
|
|
|
|

|
The 32-bit version of course can't run under x64, but how about a x64 version of the article ?
It seems that we need a driver ....
modified on Thursday, July 24, 2008 12:25 PM
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Kernel adventures of brave developer and other scary tales
| Type | Article |
| Licence | CPOL |
| First Posted | 21 Jun 2008 |
| Views | 37,920 |
| Bookmarked | 50 times |
|
|