A forum for reverse engineering, OS internals and malware analysis 

Forum for announcements and questions about tools and software.
 #32180  by HoShiMin
 Wed Oct 10, 2018 8:47 pm
Hey, guys! I've started writing the kernel framework for easy development of drivers.

It includes:
* Usigned drivers mapping
* Remote code execution
* Read/write/allocate memory of another processes without handles
* API for memory, processes and threads manipulations
* IO ports, MSRs and more CPU-specific functions
* Creating user and system threads
* Full support of C++17 (without C++ exceptions)
* Ready-to-use IOCTL dispatcher and minifilter template
* Usermode wrapper and *.dll with all supported functions
* Usermode callbacks for handles, processes/threads creation, modules loading (ObRegisterCallbacks and PsSet***NotifyRoutine usermode filters)

Files hierarchy:
Kernel API: /Kernel-Bridge/API
Usermode API: /User-Bridge/API & /SharedTypes/

All of supported functions you can see in "SharedTypes/CtlTypes.h".
GitHub link: https://github.com/HoShiMin/Kernel-Bridge

Samples:

Reading process memory:
Code: Select all
#include <Windows.h>
 
#include "WdkTypes.h"
#include "CtlTypes.h"
#include "User-Bridge.h"
 
...
 
// Loading as minifilter with specified altitude to use extended features:
KbLoader::KbLoadAsFilter(L"N:\\Folder\\Kernel-Bridge.sys", L"260000");
 
constexpr int Size = 64;
UCHAR Buffer[Size] = {};
 
using namespace Processes::MemoryManagement;
 
BOOL Status = KbReadProcessMemory(
    ProcessId,
    0x7FFF0000, // Desired address in context of ProcessId
    &Buffer,
    Size
);
 
if (Status) printf("All good!\r\n");
 
...
 
KbLoader::KbUnload();
Unsigned drivers loading:
Code: Select all
#include "WdkTypes.h"
#include "CtlTypes.h"
#include "User-Bridge.h"
#include "Rtl-Bridge.h"
 
...
 
// Read *.sys from disk:
PVOID SysImage = VirtualAlloc(...);
ReadFile(hSysImage, SysImage, ...);
 
// Load unsigned driver:
KbRtl::KbMapDriver(SysImage, L"\\Driver\\YourDriverName");
Remote code execution through an APC delivery:
Code: Select all
#include "CtlTypes.h"
#include "User-Bridge.h"
 
...
 
using namespace Processes::Apc;
 
// Delivery APC to the current NON-ALERTABLE (!) thread:
KbQueueUserApc(
    GetCurrentThreadId(),
    [](PVOID Argument) -> VOID {
        printf(
            "APC delivered to non-alertable thread %i with arg %lli\r\n", 
            GetCurrentThreadId(), 
            reinterpret_cast<UINT64>(Argument)
        );
    },
    reinterpret_cast<PVOID>(0x12345)
);
Execution custom usermode shells in Ring0:
Code: Select all
#include "CtlTypes.h"
#include "User-Bridge.h"
 
using namespace KernelShells;
 
...
 
ULONG Result = 0;
KbExecuteShellCode(
    [](
        _GetKernelProcAddress GetKernelProcAddress, 
        OPTIONAL IN OUT PVOID Argument
    ) -> ULONG {
        using _KeStallExecutionProcessor = VOID(NTAPI*)(ULONG);
        auto Stall = static_cast<_KeStallExecutionProcessor>(
            GetKernelProcAddress(L"KeStallExecutionProcessor")
        );
 
        Stall(1000 * 1000); // Stall CPU for 1 second
 
        return 1337;
    },
    NULL,
    &Result
);
Usermode Ps*** and Ob*** callbacks:
Code: Select all
#include <Windows.h>
#include <fltUser.h>
 
#include "CommPort.h"
#include "WdkTypes.h"
#include "FltTypes.h"
#include "Flt-Bridge.h"
 
...
 
// ObRegisterCallbacks notifier:
CommPortListener<KB_FLT_OB_CALLBACK_INFO, KbObCallbacks> ObCallbacks;
 
// Prevent to open our process with PROCESS_VM_READ rights:
Status = ObCallbacks.Subscribe([](CommPort& Port, MessagePacket<KB_FLT_OB_CALLBACK_INFO>& Message) -> VOID {
    auto Data = static_cast<PKB_FLT_OB_CALLBACK_INFO>(Message.GetData());
    if (Data->Target.ProcessId == GetCurrentProcessId()) {
        Data->CreateResultAccess &= ~PROCESS_VM_READ;
        Data->DuplicateResultAccess &= ~PROCESS_VM_READ;
    }
    ReplyPacket<KB_FLT_OB_CALLBACK_INFO> Reply(Message, ERROR_SUCCESS, *Data);
    Port.Reply(Reply); // Reply info to driver
});
 
 
// Ps***-callbacks:
CommPortListener<KB_FLT_PS_IMAGE_INFO, KbPsImage> ProcessCallbacks;
 
Status = ProcessCallbacks.Subscribe([](CommPort& Port, MessagePacket<KB_FLT_PS_IMAGE_INFO>& Message) -> VOID {
    auto Data = static_cast<PKB_FLT_PS_IMAGE_INFO>(Message.GetData());
    printf("[PID: %i | Base: 0x%I64X | Size: %ull]: %ws\r\n", (int)Data->ProcessId, Data->BaseAddress, (int)Data->ImageSize, Data->FullImageName);
});