EnjoyTheRing0 icon indicating copy to clipboard operation
EnjoyTheRing0 copied to clipboard

Any code to load and run some functions?

Open pps83 opened this issue 1 year ago • 6 comments

Specifically:

Недоступными в юзермоде регистрами (MSR, CR, DR)

However, going through the code, I don't see how to read/write CR4 from user mode. My goal is to enable rdpmc from user mode, which can be enabled by flipping bits in CR4:

                auto cr4val = __readcr4(); // Read CR4
                cr4val |= 0x100;       // Enable RDPMC
                cr4val &= ~4;          // Enable RDTSC
                __writecr4(cr4val);   // Write CR4

__readcr4/__writecr4 require ring0, while EnjoyTheRing0 description mentions that it provides read/write access to cr4, it doesn't seem like it's implemented, or I'm missing something?

Supposedly, OperateCrDrRegister(READ_CR4, 0) should do it, but it doesn't go through the driver, but would be executed in user mode. How to get this executed in ring0 on driver side?

thanks

pps83 avatar Dec 30 '24 18:12 pps83

Hi here! You can set any kernel registers directly from userspace using this: https://github.com/HoShiMin/EnjoyTheRing0/blob/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/IOCTLDispatcher.c#L237-L246 It will call the given callback with Ring0 privileges. So that, you can pass an address of your userspace function with __writecr4().

HoShiMin avatar Dec 30 '24 21:12 HoShiMin

I figured that I could use this one, but not sure how to call it.

Here's sample code:

void Mul2(void* in, void* out)
{
	const int* x = (int*)in;
	int* y = (int*)out;
	*y = *x * 2;
}

void TestRing0()
{
	int in = 1;
	int out;
	Mul2(&in, &out);
	printf("%d * 2 = %d\n", in, out);
}

how could I wrap it, so that TestRin0 calls Mul2 through ExecuteShell? Seems something like this:

SIZE_T __stdcall ShellProcMul2(PSHELL_CODE_ARGUMENTS Arguments)
{
	Mul2(Arguments->InputData, Arguments->OutputData);
	return 0;
}

void TestRing0()
{
	int in = 1;
	int out;
	//Mul2(&in, &out);
    EXECUTE_SHELL_CODE_INPUT shellex;
    shellex.EntryPoint = &ShellProcMul2;
    shellex.CodeBlock = ?...
		/// ?...

    printf("%d * 2 = %d\n", in, out);
}

pps83 avatar Dec 30 '24 22:12 pps83

I already forgot about details, but it looks like you could try something like this:

size_t __stdcall shell(PSHELL_CODE_ARGUMENTS args)
{
    // ... Your Ring0 code here...
    return 0;
}

// https://github.com/HoShiMin/EnjoyTheRing0/blob/ea426c4ce56e5cf406732a572dc8db8b3c5e6626/EnjoyTheRing0/ShellCode.h#L25-L29
struct UM_MEMORY_INFO
{
    PVOID address;
    ULONG size;
    unsigned char access;
}

void execShell()
{
    UM_MEMORY_INFO shellDesc{};
    shellDesc.address = shell;
    shellDesc.size = 0; // Means nothing for direct access.
    shellDesc.access = 0; // Perform direct access.

    int shellStatus = 0;

    EXECUTE_SHELL_CODE_INPUT shellInfo{};
    shellInfo.EntryPoint = shell;
    shellInfo.CodeBlock = &shellDesc;
    shellInfo.Result = &shellStatus;

    constexpr ULONG k_shellIoctl = CTL_CODE(0x8000, 0x81F, METHOD_NEITHER, FILE_ANY_ACCESS);

    DWORD bytesReturned = 0;
    DeviceIoControl(hDevice, &shellInfo, k_shellIoctl, sizeof(shellInfo), nullptr, 0, &bytesReturned, nullptr);
}

For Input and Output arguments is also required to pass UM_MEMORY_INFO with only address filled.

HoShiMin avatar Dec 31 '24 13:12 HoShiMin

Also, there is another driver with ability to call usermode shells with much more simple and straightforward implementation: https://github.com/HoShiMin/Kernel-Bridge/tree/master

HoShiMin avatar Dec 31 '24 13:12 HoShiMin

Also, there is another driver with ability to call usermode shells with much more simple and straightforward implementation: https://github.com/HoShiMin/Kernel-Bridge/tree/master

It looks like Kernel-Bridge or EnjoyTheRing0 both cannot be loaded now. Chrome completely blocks latest Kernel-Bridge.zip release from downloading, some older releases can be downloaded, but none of them can be started. StartService for EnjoyTheRing0 returns ERROR_INVALID_IMAGE_HASH, which means that the driver isn't signed (even though in properties it's shown as signed). StartService for Kernel-Bridge.sys returns 0x800b010c, which means:

@err,hr | 0x800b010c : A certificate was explicitly revoked by its issuer.

So far, only original WinRing0x64.sys can be loaded without disabling secure boot, but it doesn't give access to CR4. I wanted to access performance counters without messing with disabling secureboot/restart, but so far seems easiest is to somehow sign my own build of MSRDriver64.sys but I have no idea how to do it.

pps83 avatar Dec 31 '24 16:12 pps83

You can load your driver without signing using any mapper with any vulnerable driver (e.g., by Intel, nVidia or VirtualBox which can't be just blacklisted by Microsoft). The most famous is kdmapper. Try to load your driver with it.

HoShiMin avatar Dec 31 '24 18:12 HoShiMin