master 4da9c51f4c46 cached
4 files
9.1 KB
2.5k tokens
15 symbols
1 requests
Download .txt
Repository: beans42/kernel-read-write-using-ioctl
Branch: master
Commit: 4da9c51f4c46
Files: 4
Total size: 9.1 KB

Directory structure:
gitextract__zrcyrgw/

├── README.md
├── driver src/
│   └── driver.cpp
└── usermode example/
    ├── driver.hpp
    └── main.cpp

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# kernel-read-write-using-ioctl
simple driver to read and write to a process's memory using IOCTL as communication

driver can be mapped with kdmapper

usermode example is auto bhop for csgo

NOTE: disable security check when compiling driver if mapping with kdmapper

![disable security check picture](https://github.com/beans42/kernel-read-write-using-ioctl/blob/master/security_check.png)


================================================
FILE: driver src/driver.cpp
================================================
#include <ntifs.h>

extern "C" { //undocumented windows internal functions (exported by ntoskrnl)
	NTKERNELAPI NTSTATUS IoCreateDriver(PUNICODE_STRING DriverName, PDRIVER_INITIALIZE InitializationFunction);
	NTKERNELAPI NTSTATUS MmCopyVirtualMemory(PEPROCESS SourceProcess, PVOID SourceAddress, PEPROCESS TargetProcess, PVOID TargetAddress, SIZE_T BufferSize, KPROCESSOR_MODE PreviousMode, PSIZE_T ReturnSize);
}

constexpr ULONG init_code  = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x775, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for setting g_target_process by target process id
constexpr ULONG read_code  = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x776, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for reading memory
constexpr ULONG write_code = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x777, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for writing memory

struct info_t { //message type that will be passed between user program and driver
	HANDLE target_pid = 0; //process id of process we want to read from / write to
	void*  target_address = 0x0; //address in the target proces we want to read from / write to
	void*  buffer_address = 0x0; //address in our usermode process to copy to (read mode) / read from (write mode)
	SIZE_T size = 0; //size of memory to copy between our usermode process and target process
	SIZE_T return_size = 0; //number of bytes successfully read / written
};

NTSTATUS ctl_io(PDEVICE_OBJECT device_obj, PIRP irp) {
	UNREFERENCED_PARAMETER(device_obj);
	
	static PEPROCESS s_target_process;

	irp->IoStatus.Information = sizeof(info_t);
	auto stack = IoGetCurrentIrpStackLocation(irp);
	auto buffer = (info_t*)irp->AssociatedIrp.SystemBuffer;

	if (stack) { //add error checking
		if (buffer && sizeof(*buffer) >= sizeof(info_t)) {
			const auto ctl_code = stack->Parameters.DeviceIoControl.IoControlCode;

			if (ctl_code == init_code) //if control code is find process, find the target process by its id and put it into g_target_process
				PsLookupProcessByProcessId(buffer->target_pid, &s_target_process);

			else if (ctl_code == read_code) //if control code is read, copy target process memory to our process
				MmCopyVirtualMemory(s_target_process, buffer->target_address, PsGetCurrentProcess(), buffer->buffer_address, buffer->size, KernelMode, &buffer->return_size);

			else if (ctl_code == write_code) //if control code is write, copy our process memory to target process memory
				MmCopyVirtualMemory(PsGetCurrentProcess(), buffer->buffer_address, s_target_process, buffer->target_address, buffer->size, KernelMode, &buffer->return_size);
		}
	}

	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS unsupported_io(PDEVICE_OBJECT device_obj, PIRP irp) {
	UNREFERENCED_PARAMETER(device_obj);
	
	irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return irp->IoStatus.Status;
}

NTSTATUS create_io(PDEVICE_OBJECT device_obj, PIRP irp) {
	UNREFERENCED_PARAMETER(device_obj);

	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return irp->IoStatus.Status;
}

NTSTATUS close_io(PDEVICE_OBJECT device_obj, PIRP irp) {
	UNREFERENCED_PARAMETER(device_obj);
	
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return irp->IoStatus.Status;
}

NTSTATUS real_main(PDRIVER_OBJECT driver_obj, PUNICODE_STRING registery_path) {
	UNREFERENCED_PARAMETER(registery_path);
	
	UNICODE_STRING dev_name, sym_link;
	PDEVICE_OBJECT dev_obj;

	RtlInitUnicodeString(&dev_name, L"\\Device\\cartidriver"); //die lit
	auto status = IoCreateDevice(driver_obj, 0, &dev_name, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &dev_obj);
	if (status != STATUS_SUCCESS) return status;

	RtlInitUnicodeString(&sym_link, L"\\DosDevices\\cartidriver");
	status = IoCreateSymbolicLink(&sym_link, &dev_name);
	if (status != STATUS_SUCCESS) return status;

	SetFlag(dev_obj->Flags, DO_BUFFERED_IO); //set DO_BUFFERED_IO bit to 1

	for (int t = 0; t <= IRP_MJ_MAXIMUM_FUNCTION; t++) //set all MajorFunction's to unsupported
		driver_obj->MajorFunction[t] = unsupported_io;

	//then set supported functions to appropriate handlers
	driver_obj->MajorFunction[IRP_MJ_CREATE] = create_io; //link our io create function
	driver_obj->MajorFunction[IRP_MJ_CLOSE] = close_io; //link our io close function
	driver_obj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ctl_io; //link our control code handler
	driver_obj->DriverUnload = NULL; //add later

	ClearFlag(dev_obj->Flags, DO_DEVICE_INITIALIZING); //set DO_DEVICE_INITIALIZING bit to 0 (we are done initializing)
	return status;
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT driver_obj, PUNICODE_STRING registery_path) {
	UNREFERENCED_PARAMETER(driver_obj);
	UNREFERENCED_PARAMETER(registery_path);

	UNICODE_STRING  drv_name;
	RtlInitUnicodeString(&drv_name, L"\\Driver\\cartidriver");
	IoCreateDriver(&drv_name, &real_main); //so it's kdmapper-able

	return STATUS_SUCCESS;
}


================================================
FILE: usermode example/driver.hpp
================================================
#pragma once
#include <Windows.h>

constexpr DWORD init_code  = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x775, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for setting g_target_process by target process id
constexpr DWORD read_code  = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x776, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for reading memory
constexpr DWORD write_code = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x777, METHOD_BUFFERED, FILE_SPECIAL_ACCESS); //custom io control code for writing memory

class driver_manager {
	HANDLE m_driver_handle = nullptr; //handle to our driver

    struct info_t { //message type that will be passed between user program and driver
        UINT64 target_pid = 0; //process id of process we want to read from / write to
        UINT64 target_address = 0x0; //address in the target proces we want to read from / write to
        UINT64 buffer_address = 0x0; //address in our usermode process to copy to (read mode) / read from (write mode)
        UINT64 size = 0; //size of memory to copy between our usermode process and target process
        UINT64 return_size = 0; //number of bytes successfully read / written
    };

public:
    driver_manager(const char* driver_name, DWORD target_process_id) {
		m_driver_handle = CreateFileA(driver_name, GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); //get a handle to our driver
        attach_to_process(target_process_id); //tell driver to find the process with this id and put it into g_target_process
	}

    void attach_to_process(DWORD process_id) {
        info_t io_info;
        
        io_info.target_pid = process_id;

        DeviceIoControl(m_driver_handle, init_code, &io_info, sizeof(io_info), &io_info, sizeof(io_info), nullptr, nullptr);
    }

    template<typename T> T RPM(const UINT64 address) {
        info_t io_info;
        T read_data;

        io_info.target_address = address;
        io_info.buffer_address = (UINT64)&read_data;
        io_info.size = sizeof(T);

        DeviceIoControl(m_driver_handle, read_code, &io_info, sizeof(io_info), &io_info, sizeof(io_info), nullptr, nullptr);
        if (io_info.return_size != sizeof(T))
            throw 0xBEEF; //partial read
        return read_data;
    }

    template<typename T> bool WPM(const UINT64 address, const T buffer) {
        info_t io_info;

        io_info.target_address = address;
        io_info.buffer_address = (UINT64)&buffer;
        io_info.size = sizeof(T);

        DeviceIoControl(m_driver_handle, write_code, &io_info, sizeof(io_info), &io_info, sizeof(io_info), nullptr, nullptr);
        return io_info.return_size == sizeof(T);
    }
};


================================================
FILE: usermode example/main.cpp
================================================
#include "driver.hpp"
#include <TlHelp32.h>

constexpr uintptr_t dwLocalPlayer = 0xD2FB94;
constexpr uintptr_t dwForceJump = 0x51ED760;
constexpr uintptr_t m_fFlags = 0x104;
constexpr uintptr_t FL_ONGROUND = 1 << 0;

auto get_module(const char* module_name, DWORD process_id) {
	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, process_id);
	if (hSnap != INVALID_HANDLE_VALUE) {
		MODULEENTRY32 modEntry;
		modEntry.dwSize = sizeof(modEntry);
		if (Module32First(hSnap, &modEntry)) {
			do {
				if (!strcmp(modEntry.szModule, module_name)) {
					CloseHandle(hSnap);
					return modEntry;
				}
			} while (Module32Next(hSnap, &modEntry));
		}
	}
}

int main() {
	auto hwnd = FindWindowA(NULL, "Counter-Strike: Global Offensive");
	DWORD process_id; GetWindowThreadProcessId(hwnd, &process_id);
	auto client = get_module("client_panorama.dll", process_id);
	auto client_base = (uintptr_t)client.modBaseAddr;

	auto driver = new driver_manager("\\\\.\\cartidriver", process_id);

	while (true) {
		auto local_player = driver->RPM<uintptr_t>(client_base + dwLocalPlayer);
		if (!local_player) continue;
		auto flags = driver->RPM<DWORD>(local_player + m_fFlags);
		if (flags & FL_ONGROUND)
			if (GetAsyncKeyState(VK_SPACE) >> 15)
				driver->WPM<DWORD>(client_base + dwForceJump, 6);
		Sleep(5);
	}
}
Download .txt
gitextract__zrcyrgw/

├── README.md
├── driver src/
│   └── driver.cpp
└── usermode example/
    ├── driver.hpp
    └── main.cpp
Download .txt
SYMBOL INDEX (15 symbols across 3 files)

FILE: driver src/driver.cpp
  type info_t (line 12) | struct info_t { //message type that will be passed between user program ...
  function NTSTATUS (line 20) | NTSTATUS ctl_io(PDEVICE_OBJECT device_obj, PIRP irp) {
  function NTSTATUS (line 48) | NTSTATUS unsupported_io(PDEVICE_OBJECT device_obj, PIRP irp) {
  function NTSTATUS (line 56) | NTSTATUS create_io(PDEVICE_OBJECT device_obj, PIRP irp) {
  function NTSTATUS (line 63) | NTSTATUS close_io(PDEVICE_OBJECT device_obj, PIRP irp) {
  function NTSTATUS (line 70) | NTSTATUS real_main(PDRIVER_OBJECT driver_obj, PUNICODE_STRING registery_...
  function NTSTATUS (line 99) | NTSTATUS DriverEntry(PDRIVER_OBJECT driver_obj, PUNICODE_STRING register...

FILE: usermode example/driver.hpp
  class driver_manager (line 8) | class driver_manager {
    type info_t (line 11) | struct info_t { //message type that will be passed between user progra...
    method driver_manager (line 20) | driver_manager(const char* driver_name, DWORD target_process_id) {
    method attach_to_process (line 25) | void attach_to_process(DWORD process_id) {
    method T (line 33) | T RPM(const UINT64 address) {
    method WPM (line 47) | bool WPM(const UINT64 address, const T buffer) {

FILE: usermode example/main.cpp
  function get_module (line 9) | auto get_module(const char* module_name, DWORD process_id) {
  function main (line 25) | int main() {
Condensed preview — 4 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (10K chars).
[
  {
    "path": "README.md",
    "chars": 392,
    "preview": "# kernel-read-write-using-ioctl\nsimple driver to read and write to a process's memory using IOCTL as communication\n\ndriv"
  },
  {
    "path": "driver src/driver.cpp",
    "chars": 4912,
    "preview": "#include <ntifs.h>\n\nextern \"C\" { //undocumented windows internal functions (exported by ntoskrnl)\n\tNTKERNELAPI NTSTATUS "
  },
  {
    "path": "usermode example/driver.hpp",
    "chars": 2670,
    "preview": "#pragma once\n#include <Windows.h>\n\nconstexpr DWORD init_code  = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x775, METHOD_BUFFERED, FI"
  },
  {
    "path": "usermode example/main.cpp",
    "chars": 1333,
    "preview": "#include \"driver.hpp\"\n#include <TlHelp32.h>\n\nconstexpr uintptr_t dwLocalPlayer = 0xD2FB94;\nconstexpr uintptr_t dwForceJu"
  }
]

About this extraction

This page contains the full source code of the beans42/kernel-read-write-using-ioctl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 4 files (9.1 KB), approximately 2.5k tokens, and a symbol index with 15 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!