Full Code of dmarov/chamd for AI

master 5e5ca227cc6d cached
54 files
397.1 KB
126.1k tokens
314 symbols
1 requests
Download .txt
Showing preview only (415K chars total). Download the full file or copy to clipboard to get everything.
Repository: dmarov/chamd
Branch: master
Commit: 5e5ca227cc6d
Files: 54
Total size: 397.1 KB

Directory structure:
gitextract_ndahrtj5/

├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── scripts/
│   ├── builder.js
│   ├── context.js
│   ├── multibuilder.js
│   ├── paths.js
│   └── utils.js
├── src/
│   ├── DBKDrvr.c
│   ├── DBKDrvr.h
│   ├── DBKFunc.c
│   ├── DBKFunc.h
│   ├── IOPLDispatcher.c
│   ├── IOPLDispatcher.h
│   ├── amd64/
│   │   ├── dbkfunca.asm
│   │   ├── debuggera.asm
│   │   ├── noexceptionsa.asm
│   │   ├── ultimapa.asm
│   │   ├── vmxhelpera.asm
│   │   └── vmxoffloada.asm
│   ├── debugger.c
│   ├── debugger.h
│   ├── deepkernel.c
│   ├── deepkernel.h
│   ├── extradefines.h
│   ├── extraimports.h
│   ├── interruptHook.c
│   ├── interruptHook.h
│   ├── memscan.c
│   ├── memscan.h
│   ├── noexceptions.c
│   ├── noexceptions.h
│   ├── processlist.c
│   ├── processlist.h
│   ├── segmentinfo.asm
│   ├── threads.c
│   ├── threads.h
│   ├── ultimap.c
│   ├── ultimap.h
│   ├── ultimap2/
│   │   ├── apic.c
│   │   └── apic.h
│   ├── ultimap2.c
│   ├── ultimap2.h
│   ├── vmxhelper.c
│   ├── vmxhelper.h
│   ├── vmxoffload.c
│   └── vmxoffload.h
├── templates/
│   ├── CMakeLists.txt.tpl
│   ├── chamd.inf.tpl
│   ├── driver64.dat.tpl
│   └── makecat.cdf.tpl
└── wdk/
    └── FindWDK.cmake

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

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true


================================================
FILE: .gitignore
================================================
build
.cache
.env
node_modules
src/CMakeLists.txt
dist
dists


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Dmitry Marov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Chamd (Chameleon DBK64)

## Modified Driver Based on Cheat Engine DBK64

This project provides a modified version of the Cheat Engine DBK64 kernel driver aimed at bypassing detection by anti-cheat systems.
It has been tested with EAC and BattlEye, potentially working with other systems as well.

Current version is based on Cheat Engine version 7.5

![screen](images/screen.png "Screen")
*As shown below, the driver successfully bypasses EAC detection in Robocraft.*

## 0. Important Warning

Even if you manage to use this driver successfully, it does not guarantee that you will not be suspected of cheating.
The usage of this software and any actions outlined in this document are entirely at your own risk.

Please note that using these instructions **poses a significant security risk** to your system.
It is highly recommended to use an isolated computer for this purpose. Additionally, isolating the machine within a local network may further enhance security.

## 1. System Requirements and Preparation
- **Operating System**: Windows 11 only. This method will not work on Windows 10.
- **Disable Anti-Virus Software**: Turn off Virus and Threat Protection in Windows settings, as well as any other anti-virus or anti-malware programs. These can block the required files
- Install **Cheat Engine 7.5** by compiling it from [source](https://github.com/cheat-engine/cheat-engine/releases/tag/7.5), which is preferred method, or using the [installer](https://www.cheatengine.org/downloads.php).

## 2. Obtain your driver

2.1. **Download the Compiled Driver**
Visit [GitHub](https://github.com/dmarov/chamd/releases/tag/v1.4) to download the compiled driver, which includes a multibuild file.

2.2. **Extract the Archive**
Once downloaded, extract the archive containing over 1000+ drivers. This extensive number of drivers is strategically provided to minimize the chances of multiple users using the same
driver instance, thereby reducing detection risk.

2.3. **Select and Copy the Driver**
From the extracted files, choose any one random driver. Copy all three associated files to the directory where `cheatengine-x86_64.exe` is located.

Why Multiple Drivers?
Using a unique driver decreases the chances of your setup being flagged or blacklisted by anti-cheat systems.
The way anti-cheat works, is that it develops signatures for popular cheats and flags it in the database. Of cousre there's more to anti-cheat.

For better reliability, consider compiling your own driver following the instructions in Section 7. This process creates a custom driver, reducing the chances of
detection.

## 3. Bypassing **Digital Signature Enforcement**

At this point you have driver signed with untrusted certificate.
There are a few options to load it.
In this section the method based on bypass of **Patchguard** and **Digital Signature Enforcement** will be explained.
Refer to section 8 for some extra method.

- [Video tutorial 1](https://www.youtube.com/watch?v=EJGuJp2fqpM)
- [Video tutorial 2](https://www.youtube.com/watch?v=zsw3xoG3zgs)

3.1. Create bootable usb drive

3.1.1. Download [EfiGuard](https://github.com/Mattiwatti/EfiGuard/releases/) version >= 1.4.

3.1.2. Mount you usb drive. 2GB drive should be more than enough.

3.1.3. Format your usb drive as `FAT32`. **be carefull to format the correct device**, because it will erase all data on USB drive

3.1.4. Partition your device as bootable `GPT` with `EFI` partition.
**be carefull to partition the correct device!!!**

Open command prompt as administrator and perform the following commands:

```shell
diskpart
list disk // detect your USB drive
select disk {put number of your USB drive here} // SELECTING CORRECT DISK!!!
list disk // make sure correct disk is selected
clean // wipe out your drive
create partition primary size=512 // create EFI partition
list partitions // created partition shoud be displayed
select partition 1 // select created partition
active // mark partition as active
format quick fs=fat32 // create filesystem
assign // disk should be mounted
exit
```

3.1.5. Copy files to USB drive

Copy `EFI` directory from the extracted archive to the root of created partition.

3.1.6. Rename bootloader

Locate `EFI/Boot/Loader.efi` on the USB drive, than rename it to `EFI/Boot/bootx64.efi`.

3.2. Boot your system from USB drive.

Restart your computer and enter the UEFI settings (usually by pressing F2, F12, or DEL during startup).
Set the first boot option to your USB drive (UEFI). The second option should be your windows drive (UEFI).
Ensure Secure Boot is disabled since EFIGuard rootkit isn't signed.

3.3. Copy files for digital signature enforcement bypass

3.3.1. In the directory containing `cheatengine-x86_64.exe`, create a new file named `run.bat` with the following content:

```shell
"%~dp0\EfiDSEFix.exe" -d
start /d "%~dp0" cheatengine-x86_64.exe
timeout /t 20
"%~dp0\EfiDSEFix.exe" -e
```

Before doing that, make sure that file explored is not configured to hide known file extensions.

3.3.2. Copy `EfiDSEFix.exe` from the archive to the same directory as `cheatengine-x86_64.exe`.

## 4. Configure Cheat Engine

Make sure that

`Edit` > `Settings` > `Extra` > `Query memory region routines` is checked

`Edit` > `Settings` > `Extra` > `Read/Write process memory` is checked

Click `OK`.

It might end up with errors. Close Cheat Engine.

## 5. Run Cheat Engine.

### If you followed section 3:

Run `run.bat` as Administrator.

Do not close the window that pops out manually!!! Wait for it to close automatically.

After the driver has been successfully loaded, you can directly run `cheatengine-x86_64.exe` without needing to execute `run.bat`.

### If you followed section 8:

Run `cheatengine-x86_64.exe`

## 6. Congratulations

You have successfully loaded the DBK64 driver signed with an untrusted certificate.
This allows kernel mode anti-cheat (EAC) to permit starting the game and performing operations on the
game memory. Note: The last tested version was confirmed on EAC as of April 19, 2025.

## 7. [Extra] Compile the driver from source

Anti-cheat systems may collect signatures of suspicious drivers used by a small number of users to block them. To mitigate this, it is recommended to compile your own version of the
driver with a unique signature.

#### **Note:**
Use PowerShell or Cmder for these steps.

[Video Tutorial](https://www.youtube.com/watch?v=7ARwpxZPpE8)

7.1. Clone this repository

```shell
git clone https://github.com/dmarov/chamd.git
cd chamd
```

Ensure you have Git installed on your system before cloning.

7.2. Install [nodejs](https://nodejs.org/en/). Version `>=19` is required.

7.3. Install packages
Run the following command in your terminal:

```shell
npm install
```

This will install all required packages for building the driver.

7.4. Copy `.env.tpl` to `.env`
Create a copy of the template environment file by running:

```shell
cp .env.tpl .env
```

7.5. Optionaly set `CHAMD_DBK_DRIVER_NAME` in `.env`.

Edit the `.env` file and set the `CHAMD_DBK_DRIVER_NAME` variable to a unique name if desired.

Example:
```env
CHAMD_DBK_DRIVER_NAME=mysupercooldrv
```

7.6. Install Visual Studio

Install **Visual Studio 2022** (Community or Enterprise) with support for C++ development.

[Download Visual Studio](https://visualstudio.microsoft.com/downloads/)

Ensure you select the following components during installation:
- **Desktop Development with C++**
- **MSVC v143 (C++ Compiler)**

7.7. Install [Windows SDK and WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)
Carefully follow the instructions from the link. It is important that SDK and WDK have the same version.
Correct versions of spectre mitigated libraries should be installed in the process.

7.8. Install openssl. The most straightforward way is to use Chocolatey package manager.

```shell
choco install openssl
```

This command has to be performed as Admininstrator.

7.9. Run build

```shell
npm run all
```

Note:

You can use [EV certificate](https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/code-signing-cert-manage)
to sign driver. You could skip digital signature enforcement bypass this way. They are costly though and can be revoked when misused.

7.10. Copy all files from the 'dist' directory to directory where `cheatengine-x86_64.exe`
is located.

7.11. If you've managed to compile this driver successfully and want to share few
randomized copies then run `npm run multibuild 10`. `dist` directory will
contain `10` randomized drivers.

Then go to section 3.

## 8. [Extra] Another Method of dealing with *Digital Signature Enforcement*

If you want to bypass digital signature enforcement temporarily (for testing purposes only), follow these steps:

8.1. Enable Test Signing Mode:
```shell
bcdedit /set testsigning on
```
This command modifies the boot configuration to allow loading of unsigned or self-signed drivers.

8.2. Reboot Your System:
The changes take effect after a system reboot.

8.3. Proceed with Section 4:
Load the driver as outlined in section 4.

8.4. Disable Test Signing Mode:
After testing, disable test signing mode to restore normal security settings.
```shell
bcdedit /set testsigning off
```

Enabling test signing mode is intended for development and troubleshooting purposes only.
It temporarily reduces the system's security by allowing unsigned drivers to load.
This method does not work with anti-cheat systems, as they typically enforce strict driver signature requirements.


================================================
FILE: package.json
================================================
{
  "type": "module",
  "dependencies": {
    "dotenv": "^10.0.0",
    "handlebars": "^4.7.7"
  },
  "scripts": {
    "all": "node --unhandled-rejections=strict ./scripts/builder.js all",
    "purge": "node --unhandled-rejections=strict ./scripts/builder.js purge",
    "compile": "node --unhandled-rejections=strict ./scripts/builder.js compile",
    "geninf": "node --unhandled-rejections=strict ./scripts/builder.js geninf",
    "sign": "node --unhandled-rejections=strict ./scripts/builder.js sign",
    "multibuild": "node --unhandled-rejections=strict ./scripts/multibuilder.js"
  }
}


================================================
FILE: scripts/builder.js
================================================
import dotenv from 'dotenv';
import Context from './context.js';
import generateRandomName from './utils.js';
import path from 'path';
import { __dirname } from './paths.js';

const env = dotenv.config().parsed;
const driverName = env.CHAMD_DBK_DRIVER_NAME ?? generateRandomName();
const args = process.argv.slice(2);
const command = args[0];
const distDir = path.normalize(__dirname + '\\..\\dist\\');
const context = new Context(driverName, distDir);

await Context.purgeDir(distDir);

switch (command) {
    case 'all':
        await context.all();
        break;
    case 'purge':
        await context.purge();
        break;
    case 'compile':
        await context.generateCmakeFile();
        await context.compile();
        break;
    case 'geninf':
        await context.createInfFile();
        await context.stampInfFile();
        break;
    case 'sign':
        await context.signDriver();
        await context.createInfFile();
        break;
}


================================================
FILE: scripts/context.js
================================================
import path from 'path';
import fs from 'fs';
import handlebars from 'handlebars';
import { spawn } from 'child_process';
import { __dirname } from './paths.js';

export default class Context {
    buildDir = path.normalize(__dirname + '\\..\\build\\');

    vcvarsCommunityPath = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat';
    vcvarsEnterprisePath = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat';
    vcPath = null;

    cmakeTplPath = path.normalize(__dirname + '\\..\\templates\\CMakeLists.txt.tpl');
    infTplPath = path.normalize(__dirname + '\\..\\templates\\chamd.inf.tpl');
    makeCatTplPath = path.normalize(__dirname + '\\..\\templates\\makecat.cdf.tpl');
    datTplPath = path.normalize(__dirname + '\\..\\templates\\driver64.dat.tpl');
    datPath = `${this.buildDir}driver64.dat`;
    srcDir = path.normalize(__dirname + '\\..\\src\\');
    cmakeConfigPath = this.srcDir + 'CMakeLists.txt';

    constructor(driverName, distDir) {
        this.distDir = distDir;
        this.driverName = driverName
            .replace(/[^a-z0-9_]/gi, '')
            .toLowerCase();

        const communityVs = fs.existsSync(this.vcvarsCommunityPath);
        const enterpriseVs = fs.existsSync(this.vcvarsEnterprisePath);

        if (communityVs) {
            this.vcPath = this.vcvarsCommunityPath;
        }

        if (enterpriseVs) {
            this.vcPath = this.vcvarsEnterprisePath;
        }

        this.makeCatPath = `${this.buildDir}${this.driverName}.cdf`;
    }

    async all() {
        console.log(`Generating ${this.driverName} driver ...`);
        await this.purge();
        await this.generateCmakeFile();
        await this.compile();
        await this.createMakeCatFile();
        await this.makeCatFile();
        await this.signDriver();
        await this.createDriverDatFile();
        await this.install();
        await this.clearBuildDir();
        console.log(`Success!!!`);
        console.log(`Now copy all files from ${this.distDir} to directory where cheatengine.exe is located`);
    }

    async purge() {
        await this.clearBuildDir();

        if (!fs.existsSync(this.cmakeConfigPath)) {
            return;
        }

        fs.rmSync(this.cmakeConfigPath);
    }

    static async purgeDir(dir) {

        if (!fs.existsSync(dir)) {
            return;
        }

        fs.rmSync(dir, { recursive: true })
    }

    async generateCmakeFile() {
        await this.templateToFile(
            this.cmakeTplPath,
            this.cmakeConfigPath,
            {
                DRIVER_NAME: this.driverName,
            }
        );
    }

    async templateToFile(src, dist, vars) {
        const templateContent = fs.readFileSync(src, 'utf-8');
        const template = handlebars.compile(templateContent);
        const res = template(vars)

        fs.writeFileSync(dist, res);
    }

    async compile() {
        console.log('Compiling');
        if (this.vcPath === null) {
            throw new Error('Visual studio not found');
        }

        if (!fs.existsSync(this.buildDir)) {
            fs.mkdirSync(this.buildDir);
        }

        const cmd = `"${this.vcPath}" amd64 && cd "${this.buildDir}" && cmake -G "Visual Studio 17 2022" -A x64 -T v143 "${this.srcDir}" && cmake --build . --config Release`;
        await this.execute(cmd, this.buildDir);
    }

    async createMakeCatFile() {
        console.log('Creating makecat file');
        await this.templateToFile(
            this.makeCatTplPath,
            this.makeCatPath, {
                DRIVER_NAME: this.driverName,
            },
        );
    }

    async makeCatFile() {
        console.log('Makeing cat file');
        const cmd = `"${this.vcPath}" amd64 && MakeCat.exe -v .\\${this.driverName}.cdf`
        await this.execute(cmd, this.buildDir);
    }

    async signDriver() {
        console.log('Signing driver');
        const openssl = `openssl req -nodes -newkey rsa:2048 -keyout ${this.driverName}.key -out ${this.driverName}.csr -subj "/CN=${this.driverName}.com/O=${this.driverName} LTD./C=US"`
        const crt = `openssl x509 -signkey ${this.driverName}.key -in ${this.driverName}.csr -req -days 365 -out ${this.driverName}.crt`;
        const pfx = `openssl pkcs12 -export -out ${this.driverName}.pfx -inkey ${this.driverName}.key -in ${this.driverName}.crt -password pass:`;
        const vc = `"${this.vcPath}" amd64`;
        const signtool = `signtool sign /fd SHA256 -f "./${this.driverName}.pfx" -t "http://timestamp.digicert.com" -v "${this.driverName}.cat"`;

        const cmd = `${openssl} && ${crt} && ${pfx} && ${vc} && ${signtool}`;

        await this.execute(cmd, this.buildDir);
    }

    async execute(cmd, cwd, params = []) {
        console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
        console.log(`Executing: ${cmd}`);

        return new Promise((res, rej) => {
            const proc = spawn(cmd, params, {
                cwd,
                shell: true,
            });

            proc.stderr.setEncoding('utf-8');
            proc.stdout.pipe(process.stdout);
            proc.stderr.pipe(process.stderr);

            proc.on('close', (code) => {
                code == 0 ? res() : rej();
            });
        });
    }

    async createDriverDatFile() {
        console.log('Creating dat file');
        await this.templateToFile(
            this.datTplPath,
            this.datPath, {
                DRIVER_NAME: this.driverName,
            },
        );
    }

    async install() {
        console.log('Installing');

        if (!fs.existsSync(this.distDir)) {
            fs.mkdirSync(this.distDir, { recursive: true });
        }

        fs.copyFileSync(
            `${this.buildDir}${this.driverName}.sys`,
            `${this.distDir}${this.driverName}.sys`
        );

        fs.copyFileSync(
            `${this.buildDir}${this.driverName}.cat`,
            `${this.distDir}${this.driverName}.cat`
        );

        fs.copyFileSync(
            `${this.buildDir}driver64.dat`,
            `${this.distDir}driver64.dat`
        );
    }

    async clearBuildDir() {
        await Context.purgeDir(this.buildDir);
    }
}


================================================
FILE: scripts/multibuilder.js
================================================
import Context from './context.js';
import generateRandomName from './utils.js';
import path from 'path';
import http from 'http';
import { __dirname } from './paths.js';

const args = process.argv.slice(2);
const cnt = args[0] ? parseInt(args[0]) : 5;
const distDir = path.normalize(__dirname + '\\..\\dist\\');

async function getRandomWord() {
    return new Promise((res, rej) => {
        const options = {
            host: 'random-word-api.herokuapp.com',
            path: '/word'
        };

        const callback = function(response) {
            let str = '';

            response.on('data', function (chunk) {
                str += chunk;
            });

            response.on('end', function () {
                res(str);
            });

        }

        const req = http.request(options, callback);

        req.on('error', function (e) {
            rej(e);
        });

        req.end();
    });
}

await Context.purgeDir(distDir);

const max = 15;
const min = 4;

for (let i = 0; i < cnt; i++) {
    const len = min + Math.floor(Math.random() * (max - min));
    let name = generateRandomName(len);

    try {
        const result = await getRandomWord();
        name = JSON.parse(result)[0]
            .replace(/[^a-z0-9_]/gi, '')
            .toLowerCase();
    } catch(e) {
        console.log(e);
    }

    const context = new Context(name, distDir + name + '\\');

    await context.all();
}


================================================
FILE: scripts/paths.js
================================================
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);

export const __dirname = path.dirname(__filename);



================================================
FILE: scripts/utils.js
================================================
export default (length) => {
    let result = '';
    const characters = 'abcdefghijklmnopqrstuvwxyz';
    const charactersLength = characters.length;

    for (let i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }

    return result;
}


================================================
FILE: src/DBKDrvr.c
================================================
#pragma warning( disable: 4100 4101 4103 4189)

#include "DBKFunc.h"
#include <ntifs.h>
#include <windef.h>
#include "DBKDrvr.h"

#include "deepkernel.h"
#include "processlist.h"
#include "memscan.h"
#include "threads.h"
#include "vmxhelper.h"
#include "debugger.h"
#include "vmxoffload.h"

#include "IOPLDispatcher.h"
#include "interruptHook.h"
#include "ultimap.h"
#include "ultimap2.h"
#include "noexceptions.h"

#include "ultimap2\apic.h"


#if (AMD64 && TOBESIGNED)
#include "sigcheck.h"
#endif


#ifdef CETC
	#include "cetc.h"
#endif


void UnloadDriver(PDRIVER_OBJECT DriverObject);

NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);


#ifndef AMD64
//no api hooks for x64

//-----NtUserSetWindowsHookEx----- //prevent global hooks
typedef ULONG (NTUSERSETWINDOWSHOOKEX)(
    IN HANDLE hmod,
    IN PUNICODE_STRING pstrLib OPTIONAL,
    IN DWORD idThread,
    IN int nFilterType,
    IN PVOID pfnFilterProc,
    IN DWORD dwFlags
);
NTUSERSETWINDOWSHOOKEX OldNtUserSetWindowsHookEx;
ULONG NtUserSetWindowsHookEx_callnumber;
//HHOOK NewNtUserSetWindowsHookEx(IN HANDLE hmod,IN PUNICODE_STRING pstrLib OPTIONAL,IN DWORD idThread,IN int nFilterType, IN PROC pfnFilterProc,IN DWORD dwFlags);


typedef NTSTATUS (*ZWSUSPENDPROCESS)
(
    IN ULONG ProcessHandle  // Handle to the process
);
ZWSUSPENDPROCESS ZwSuspendProcess;

NTSTATUS ZwCreateThread(
	OUT PHANDLE  ThreadHandle,
	IN ACCESS_MASK  DesiredAccess,
	IN POBJECT_ATTRIBUTES  ObjectAttributes,
	IN HANDLE  ProcessHandle,
	OUT PCLIENT_ID  ClientId,
	IN PCONTEXT  ThreadContext,
	IN PVOID  UserStack,
	IN BOOLEAN  CreateSuspended);

//PVOID GetApiEntry(ULONG FunctionNumber);
#endif





typedef NTSTATUS(*PSRCTNR)(__in PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine);
PSRCTNR PsRemoveCreateThreadNotifyRoutine2;

typedef NTSTATUS(*PSRLINR)(__in PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);
PSRLINR PsRemoveLoadImageNotifyRoutine2;

UNICODE_STRING  uszDeviceString;
PVOID BufDeviceString=NULL;



void hideme(PDRIVER_OBJECT DriverObject)
{
#ifndef AMD64
	
	typedef struct _MODULE_ENTRY {
	LIST_ENTRY le_mod;
	DWORD  unknown[4];
	DWORD  base;
	DWORD  driver_start;
	DWORD  unk1;
	UNICODE_STRING driver_Path;
	UNICODE_STRING driver_Name;
} MODULE_ENTRY, *PMODULE_ENTRY;

	PMODULE_ENTRY pm_current;

	pm_current =  *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14)); //eeeeew

	*((PDWORD)pm_current->le_mod.Blink)        = (DWORD) pm_current->le_mod.Flink;
	pm_current->le_mod.Flink->Blink            = pm_current->le_mod.Blink;
	HiddenDriver=TRUE;

#endif
}


int testfunction(int p1,int p2)
{
	DbgPrint("Hello\nParam1=%d\nParam2=%d\n",p1,p2);
	


	return 0x666;
}


void* functionlist[1];
char  paramsizes[1];
int registered=0;

#ifdef DEBUG1
VOID TestPassive(UINT_PTR param)
{
	DbgPrint("passive cpu call for cpu %d\n", KeGetCurrentProcessorNumber());
}


VOID TestDPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2)
{
	EFLAGS e=getEflags();
	
    DbgPrint("Defered cpu call for cpu %d (Dpc=%p  IF=%d IRQL=%d)\n", KeGetCurrentProcessorNumber(), Dpc, e.IF, KeGetCurrentIrql());
}
#endif


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath)
	/*++

	Routine Description:

	This routine is called when the driver is loaded by NT.

	Arguments:

	DriverObject - Pointer to driver object created by system.
	RegistryPath - Pointer to the name of the services node for this driver.

	Return Value:

	The function value is the final status from the initialization operation.

	--*/
{


	NTSTATUS        ntStatus;
	PVOID           BufDriverString = NULL, BufProcessEventString = NULL, BufThreadEventString = NULL;
	UNICODE_STRING  uszDriverString;

	UNICODE_STRING  uszProcessEventString;
	UNICODE_STRING	uszThreadEventString;
	PDEVICE_OBJECT  pDeviceObject;
	HANDLE reg = 0;
	OBJECT_ATTRIBUTES oa;

	UNICODE_STRING temp;
	char wbuf[100];
	WORD this_cs, this_ss, this_ds, this_es, this_fs, this_gs;
	ULONG cr4reg;



	criticalSection csTest;

	HANDLE Ultimap2Handle;


	KernelCodeStepping = 0;
	KernelWritesIgnoreWP = 0;



	this_cs = getCS();
	this_ss = getSS();
	this_ds = getDS();
	this_es = getES();
	this_fs = getFS();
	this_gs = getGS();

	temp.Buffer = (PWCH)wbuf;
	temp.Length = 0;
	temp.MaximumLength = 100;

	//DbgPrint("Loading driver\n");
	if (RegistryPath)
	{
		//DbgPrint("Registry path = %S\n", RegistryPath->Buffer);

		InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE, NULL, NULL);
		ntStatus = ZwOpenKey(&reg, KEY_QUERY_VALUE, &oa);
		if (ntStatus == STATUS_SUCCESS)
		{
			UNICODE_STRING A, B, C, D;
			PKEY_VALUE_PARTIAL_INFORMATION bufA, bufB, bufC, bufD;
			ULONG ActualSize;

			//DbgPrint("Opened the key\n");

			BufDriverString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
			BufDeviceString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
			BufProcessEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
			BufThreadEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);

			bufA = BufDriverString;
			bufB = BufDeviceString;
			bufC = BufProcessEventString;
			bufD = BufThreadEventString;

			RtlInitUnicodeString(&A, L"A");
			RtlInitUnicodeString(&B, L"B");
			RtlInitUnicodeString(&C, L"C");
			RtlInitUnicodeString(&D, L"D");

			if (ntStatus == STATUS_SUCCESS)
				ntStatus = ZwQueryValueKey(reg, &A, KeyValuePartialInformation, bufA, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
			if (ntStatus == STATUS_SUCCESS)
				ntStatus = ZwQueryValueKey(reg, &B, KeyValuePartialInformation, bufB, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
			if (ntStatus == STATUS_SUCCESS)
				ntStatus = ZwQueryValueKey(reg, &C, KeyValuePartialInformation, bufC, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
			if (ntStatus == STATUS_SUCCESS)
				ntStatus = ZwQueryValueKey(reg, &D, KeyValuePartialInformation, bufD, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);

			if (ntStatus == STATUS_SUCCESS)
			{
				//DbgPrint("Read ok\n");
				RtlInitUnicodeString(&uszDriverString, (PCWSTR)bufA->Data);
				RtlInitUnicodeString(&uszDeviceString, (PCWSTR)bufB->Data);
				RtlInitUnicodeString(&uszProcessEventString, (PCWSTR)bufC->Data);
				RtlInitUnicodeString(&uszThreadEventString, (PCWSTR)bufD->Data);

				//DbgPrint("DriverString=%S\n", uszDriverString.Buffer);
				//DbgPrint("DeviceString=%S\n", uszDeviceString.Buffer);
				//DbgPrint("ProcessEventString=%S\n", uszProcessEventString.Buffer);
				//DbgPrint("ThreadEventString=%S\n", uszThreadEventString.Buffer);
			}
			else
			{
				ExFreePool(bufA);
				ExFreePool(bufB);
				ExFreePool(bufC);
				ExFreePool(bufD);

				//DbgPrint("Failed reading the value\n");
				ZwClose(reg);
				return STATUS_UNSUCCESSFUL;;
			}

		}
		else
		{
			//DbgPrint("Failed opening the key\n");
			return STATUS_UNSUCCESSFUL;;
		}
	}
	else
		loadedbydbvm = TRUE;

	ntStatus = STATUS_SUCCESS;





	if (!loadedbydbvm)
	{

		// Point uszDriverString at the driver name
#ifndef CETC


		// Create and initialize device object
		ntStatus = IoCreateDevice(DriverObject,
			0,
			&uszDriverString,
			FILE_DEVICE_UNKNOWN,
			0,
			FALSE,
			&pDeviceObject);

		if (ntStatus != STATUS_SUCCESS)
		{
			//DbgPrint("IoCreateDevice failed\n");
			ExFreePool(BufDriverString);
			ExFreePool(BufDeviceString);
			ExFreePool(BufProcessEventString);
			ExFreePool(BufThreadEventString);


			if (reg)
				ZwClose(reg);

			return ntStatus;
		}

		// Point uszDeviceString at the device name

		// Create symbolic link to the user-visible name
		ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);

		if (ntStatus != STATUS_SUCCESS)
		{
			//DbgPrint("IoCreateSymbolicLink failed: %x\n", ntStatus);
			// Delete device object if not successful
			IoDeleteDevice(pDeviceObject);

			ExFreePool(BufDriverString);
			ExFreePool(BufDeviceString);
			ExFreePool(BufProcessEventString);
			ExFreePool(BufThreadEventString);


			if (reg)
				ZwClose(reg);

			return ntStatus;
		}

#endif
	}

	//when loaded by dbvm driver object is 'valid' so store the function addresses


	//DbgPrint("DriverObject=%p\n", DriverObject);

	// Load structure to point to IRP handlers...
	DriverObject->DriverUnload = UnloadDriver;
	DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;

	if (loadedbydbvm)
		DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchIoctlDBVM;
	else
		DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;



	//Processlist init
#ifndef CETC
	ProcessEventCount = 0;
	ExInitializeResourceLite(&ProcesslistR);
#endif

	CreateProcessNotifyRoutineEnabled = FALSE;

	//threadlist init
	ThreadEventCount = 0;

	processlist = NULL;

#ifndef AMD64
	//determine if PAE is used
	cr4reg=(ULONG)getCR4();

	if ((cr4reg & 0x20)==0x20)
	{
		PTESize=8; //pae
		PAGE_SIZE_LARGE=0x200000;
		MAX_PDE_POS=0xC0604000;
		MAX_PTE_POS=0xC07FFFF8;


	}
	else
	{
		PTESize=4;
		PAGE_SIZE_LARGE=0x400000;
		MAX_PDE_POS=0xC0301000;
		MAX_PTE_POS=0xC03FFFFC;
	}
#else
	PTESize = 8; //pae
	PAGE_SIZE_LARGE = 0x200000;
	//base was 0xfffff68000000000ULL

	//to 
	MAX_PTE_POS = 0xFFFFF6FFFFFFFFF8ULL; // base + 0x7FFFFFFFF8
	MAX_PDE_POS = 0xFFFFF6FB7FFFFFF8ULL; // base + 0x7B7FFFFFF8
#endif



#ifdef CETC
	DbgPrint("Going to initialice CETC\n");
	InitializeCETC();
#endif


	//hideme(DriverObject); //ok, for those that see this, enabling this WILL fuck up try except routines, even in usermode you'll get a blue sreen

	DbgPrint("Initializing debugger\n");
	debugger_initialize();


	// Return success (don't do the devicestring, I need it for unload)
	DbgPrint("Cleaning up initialization buffers\n");
	if (BufDriverString)
	{
		ExFreePool(BufDriverString);
		BufDriverString = NULL;
	}

	if (BufProcessEventString)
	{
		ExFreePool(BufProcessEventString);
		BufProcessEventString = NULL;
	}

	if (BufThreadEventString)
	{
		ExFreePool(BufThreadEventString);
		BufThreadEventString = NULL;
	}

	if (reg)
	{
		ZwClose(reg);
		reg = 0;
	}



	//fetch cpu info
	{
		DWORD r[4];
		DWORD a;

		__cpuid(r, 0);
		DbgPrint("cpuid.0: r[1]=%x", r[1]);
		if (r[1] == 0x756e6547) //GenuineIntel
		{

			__cpuid(r, 1);

			a = r[0];

			cpu_stepping = a & 0xf;
			cpu_model = (a >> 4) & 0xf;
			cpu_familyID = (a >> 8) & 0xf;
			cpu_type = (a >> 12) & 0x3;
			cpu_ext_modelID = (a >> 16) & 0xf;
			cpu_ext_familyID = (a >> 20) & 0xff;

			cpu_model = cpu_model + (cpu_ext_modelID << 4);
			cpu_familyID = cpu_familyID + (cpu_ext_familyID << 4);

			vmx_init_dovmcall(1);
			setup_APIC_BASE(); //for ultimap

		}
		else
		{
			DbgPrint("Not an intel cpu");
			if (r[1] == 0x68747541)
			{
				DbgPrint("This is an AMD\n");
				vmx_init_dovmcall(0);
			}

		}



	}

#ifdef DEBUG1
	{
		APIC y;

		DebugStackState x;
		DbgPrint("offset of LBR_Count=%d\n", (UINT_PTR)&x.LBR_Count - (UINT_PTR)&x);


		DbgPrint("Testing forEachCpu(...)\n");
		forEachCpu(TestDPC, NULL, NULL, NULL, NULL);

		DbgPrint("Testing forEachCpuAsync(...)\n");
		forEachCpuAsync(TestDPC, NULL, NULL, NULL, NULL);

		DbgPrint("Testing forEachCpuPassive(...)\n");
		forEachCpuPassive(TestPassive, 0);

		DbgPrint("LVT_Performance_Monitor=%x\n", (UINT_PTR)&y.LVT_Performance_Monitor - (UINT_PTR)&y);
	}
#endif

#ifdef DEBUG2
	DbgPrint("No exceptions test:");
	if (NoExceptions_Enter())
	{
		int o = 45678;
		int x = 0, r = 0;
		//r=NoExceptions_CopyMemory(&x, &o, sizeof(x));

		r = NoExceptions_CopyMemory(&x, (PVOID)0, sizeof(x));

		DbgPrint("o=%d x=%d r=%d", o, x, r);


		DbgPrint("Leaving NoExceptions mode");
		NoExceptions_Leave();
	}
#endif


	RtlInitUnicodeString(&temp, L"PsSuspendProcess");
	PsSuspendProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);

	RtlInitUnicodeString(&temp, L"PsResumeProcess");
	PsResumeProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);
	
	
    return STATUS_SUCCESS;
}


NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp)
{
	// Check for SeDebugPrivilege. (So only processes with admin rights can use it)

	LUID sedebugprivUID;
	sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;
	sedebugprivUID.HighPart=0;

	Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;



	if (SeSinglePrivilegeCheck(sedebugprivUID, UserMode))
	{		
		Irp->IoStatus.Status = STATUS_SUCCESS;
#ifdef AMD64
#ifdef TOBESIGNED
		{
			NTSTATUS s=SecurityCheck();	
			Irp->IoStatus.Status = s; 		
		}
	//	DbgPrint("Returning %x (and %x)\n", Irp->IoStatus.Status, s);
#endif
#endif


	}
	else
	{
		DbgPrint("A process without SeDebugPrivilege tried to open the dbk driver\n");
		Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
	}

    Irp->IoStatus.Information=0;

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


NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,
                       IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information=0;

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





void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
	cleanupDBVM();
	
	if (!debugger_stopDebugging())
	{
		DbgPrint("Can not unload the driver because of debugger\n");
		return; //
	}

	debugger_shutdown();

	ultimap_disable();
	DisableUltimap2();
	UnregisterUltimapPMI();

	clean_APIC_BASE();

	NoExceptions_Cleanup();
	
	if ((CreateProcessNotifyRoutineEnabled) || (ImageNotifyRoutineLoaded)) 
	{
		PVOID x;
		UNICODE_STRING temp;

		RtlInitUnicodeString(&temp, L"PsRemoveCreateThreadNotifyRoutine");
		PsRemoveCreateThreadNotifyRoutine2 = (PSRCTNR)MmGetSystemRoutineAddress(&temp);

		RtlInitUnicodeString(&temp, L"PsRemoveCreateThreadNotifyRoutine");
		PsRemoveLoadImageNotifyRoutine2 = (PSRLINR)MmGetSystemRoutineAddress(&temp);
		
		RtlInitUnicodeString(&temp, L"ObOpenObjectByName");
		x=MmGetSystemRoutineAddress(&temp);
		
		DbgPrint("ObOpenObjectByName=%p\n",x);
			

		if ((PsRemoveCreateThreadNotifyRoutine2) && (PsRemoveLoadImageNotifyRoutine2))
		{
			DbgPrint("Stopping processwatch\n");

			if (CreateProcessNotifyRoutineEnabled)
			{
				DbgPrint("Removing process watch");
#if (NTDDI_VERSION >= NTDDI_VISTASP1)
				PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx,TRUE);
#else
				PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,TRUE);
#endif

				
				DbgPrint("Removing thread watch");
				PsRemoveCreateThreadNotifyRoutine2(CreateThreadNotifyRoutine);
			}

			if (ImageNotifyRoutineLoaded)
				PsRemoveLoadImageNotifyRoutine2(LoadImageNotifyRoutine);
		}
		else return;  //leave now!!!!!		
	}


	DbgPrint("Driver unloading\n");

    IoDeleteDevice(DriverObject->DeviceObject);

#ifdef CETC
#ifndef CETC_RELEASE
	UnloadCETC(); //not possible in the final build
#endif
#endif

#ifndef CETC_RELEASE
	DbgPrint("DeviceString=%S\n",uszDeviceString.Buffer);
	{
		NTSTATUS r = IoDeleteSymbolicLink(&uszDeviceString);
		DbgPrint("IoDeleteSymbolicLink: %x\n", r);
	}
	ExFreePool(BufDeviceString);
#endif

	CleanProcessList();

	ExDeleteResourceLite(&ProcesslistR);

	RtlZeroMemory(&ProcesslistR, sizeof(ProcesslistR));

#if (NTDDI_VERSION >= NTDDI_VISTA)
	if (DRMHandle)
	{
		DbgPrint("Unregistering DRM handle");
		ObUnRegisterCallbacks(DRMHandle);
		DRMHandle = NULL;
	}
#endif
}


================================================
FILE: src/DBKDrvr.h
================================================
#ifndef DBKDRVR_H
#define DBKDRVR_H



#define dbkversion 2000027


#endif

================================================
FILE: src/DBKFunc.c
================================================
#pragma warning( disable: 4103)

#include <ntifs.h>
#include <ntddk.h>
#include "DBKFunc.h"

/*
#include "vmxhelper.h"
#include "interruptHook.h"
*/

#ifdef TESTCOMPILE
//small bypass to make test compiles function (this compiler doesn't have CLI/STI )
void _enable() {}
void _disable() {}
#endif


void forEachCpuPassive(PF f, UINT_PTR param)
/*
calls a specific function for each cpu that runs in passive mode
*/
{
	CCHAR cpunr;
	KAFFINITY cpus, original;
	ULONG cpucount;

	
	//KeIpiGenericCall is not present in xp
	
	//count cpus first KeQueryActiveProcessorCount is not present in xp)
	cpucount=0;
	cpus=KeQueryActiveProcessors();
	original=cpus;
	while (cpus)
	{
		if (cpus % 2)
			cpucount++;

		cpus=cpus / 2;		
	}

	cpus=KeQueryActiveProcessors();
	cpunr=0;
	while (cpus)
	{
		if (cpus % 2)
		{
			//bit is set
#if (NTDDI_VERSION >= NTDDI_VISTA)
			KAFFINITY oldaffinity;
#endif
			KAFFINITY newaffinity;


			
			//DbgPrint("Calling passive function for cpunr %d\n", cpunr);
			//set affinity

			newaffinity=(KAFFINITY)(1 << cpunr);

#if (NTDDI_VERSION >= NTDDI_VISTA)
			oldaffinity=KeSetSystemAffinityThreadEx(newaffinity);
#else
			//XP and earlier (this routine is not called often, only when the user asks explicitly
			{
				LARGE_INTEGER delay;
				delay.QuadPart=-50; //short wait just to be sure... (the docs do not say that a switch happens imeadiatly for the no Ex version)
				
				KeSetSystemAffinityThread(newaffinity);
				KeDelayExecutionThread(UserMode, FALSE, &delay);
			}
#endif



			//call function
			f(param);

#if (NTDDI_VERSION >= NTDDI_VISTA)
			KeRevertToUserAffinityThreadEx(oldaffinity);
#endif

		}

		cpus=cpus / 2;
		cpunr++;
	}

#if (NTDDI_VERSION < NTDDI_VISTA)
	KeSetSystemAffinityThread(original);
#endif
}

void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
{
	PKDPC dpc;

	if (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments
		preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);
	

	dpc = ExAllocatePool(NonPagedPool, sizeof(KDPC));
	KeInitializeDpc(dpc, dpcfunction, DeferredContext);
	KeSetTargetProcessorDpc(dpc, cpunr);
	KeInsertQueueDpc(dpc, SystemArgument1, SystemArgument2);
	KeFlushQueuedDpcs();

	ExFreePool(dpc);
}

void forEachCpu(PKDEFERRED_ROUTINE dpcfunction,  PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
/*
calls a specified dpcfunction for each cpu on the system
*/
{
	CCHAR cpunr;
	KAFFINITY cpus;
	ULONG cpucount;
	PKDPC dpc;
	int dpcnr;


	//KeIpiGenericCall is not present in xp
	
	//count cpus first KeQueryActiveProcessorCount is not present in xp)
	cpucount=0;
	cpus=KeQueryActiveProcessors();
	while (cpus)
	{
		if (cpus % 2)
			cpucount++;

		cpus=cpus / 2;		
	}

	dpc=ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);

		

	cpus=KeQueryActiveProcessors();
	cpunr=0;
	dpcnr=0;
	while (cpus)
	{
		if (cpus % 2)
		{
			//bit is set
			
			//DbgPrint("Calling dpc routine for cpunr %d (dpc=%p)\n", cpunr, &dpc[dpcnr]);

			if (preDPCCallback)
				preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);

			KeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);
			KeSetTargetProcessorDpc (&dpc[dpcnr], cpunr);
			KeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);
			KeFlushQueuedDpcs();
			dpcnr++;
		}

		cpus=cpus / 2;
		cpunr++;
	}


	ExFreePool(dpc);
}


void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
/*
calls a specified dpcfunction for each cpu on the system
*/
{
	CCHAR cpunr;
	KAFFINITY cpus;
	ULONG cpucount;
	PKDPC dpc;
	int dpcnr;



	//KeIpiGenericCall is not present in xp

	//count cpus first KeQueryActiveProcessorCount is not present in xp)
	cpucount = 0;
	cpus = KeQueryActiveProcessors();
	while (cpus)
	{
		if (cpus % 2)
			cpucount++;

		cpus = cpus / 2;
	}

	dpc = ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);

	cpus = KeQueryActiveProcessors();
	cpunr = 0;
	dpcnr = 0;
	while (cpus)
	{
		if (cpus % 2)
		{
			//bit is set

			//DbgPrint("Calling dpc routine for cpunr %d\n", cpunr);
			if (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments
				preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);

			KeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);
			KeSetTargetProcessorDpc(&dpc[dpcnr], cpunr);
			KeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);			
			dpcnr++;
		}

		cpus = cpus / 2;
		cpunr++;
	}

	KeFlushQueuedDpcs();


	ExFreePool(dpc);
}



//own critical section implementation for use when the os is pretty much useless (dbvm tech)
void spinlock(volatile LONG *lockvar)
{
	while (1)
	{

		//it was 0, let's see if we can set it to 1
		//race who can set it to 1:
		if (_InterlockedExchange((volatile LONG *)lockvar, 1)==0)
			return; //lock aquired, else continue loop

		_mm_pause();

	}

}

void csEnter(PcriticalSection CS)
{ 
	EFLAGS oldstate=getEflags();
	
	if ((CS->locked) && (CS->cpunr==cpunr())) 
	{
	    //already locked but the locker is this cpu, so allow, just increase lockcount
	    CS->lockcount++;
	    return; 
	} 

	disableInterrupts(); //disable interrupts to prevent taskswitch in same cpu
	
	spinlock(&(CS->locked)); //sets CS->locked to 1
  
	//here so the lock is aquired and locked is 1
	CS->lockcount=1;
	CS->cpunr=cpunr();  
	CS->oldIFstate=oldstate.IF;
}

void csLeave(PcriticalSection CS)
{
	if ((CS->locked) && (CS->cpunr==cpunr()))
	{
	    CS->lockcount--;
	    if (CS->lockcount==0)
	    {
			//unlock    
			if (CS->oldIFstate)
				enableInterrupts();				

			CS->cpunr=-1; //set to an cpunr
			CS->locked=0;
		} 
	}
	
}


int getCpuCount(void)
{
	KAFFINITY ap=KeQueryActiveProcessors();
	int count=0;
	while (ap>0)
	{
		if (ap % 2)
			count++;

		ap=ap / 2;
	}
	return count;
}

int isPrefix(unsigned char b)
{
	switch (b)
	{
		case 0x26:
		case 0x2e:
		case 0x36:
		case 0x3e:		
		case 0x64:
		case 0x65:
		case 0x66:
		case 0x67:
		case 0xf0: //lock
		case 0xf2: //repne
		case 0xf3: //rep
			return 1;

		default:
			return 0;

	}

}

UINT64 getDR7(void)
{
	return __readdr(7);

}

int cpunr(void)
{	
	DWORD x[4];
	__cpuid(&x[0],1);
	
	return (x[1] >> 24)+1;

}

EFLAGS getEflags(void)
{
	UINT64 x=__getcallerseflags();
	PEFLAGS y = (PEFLAGS)&x;
	return *y;
}

UINT64 readMSR(DWORD msr)
{
	return __readmsr(msr);
}

void setCR0(UINT64 newcr0)
{
	__writecr0(newcr0);
}

UINT64 getCR0(void)
{
	return __readcr0();
}

UINT64 getCR2(void)
{
	return __readcr2();
}



void setCR3(UINT64 newCR3)
{
	__writecr3((UINT_PTR)newCR3);
}

UINT64 getCR3(void)
{
	return __readcr3();
}



void setCR4(UINT64 newcr4)
{
	__writecr4(newcr4);
}

UINT64 getCR4(void)
{
	return __readcr4();
}

void GetIDT(PIDT pIdt)
{
	__sidt(pIdt);
}

void enableInterrupts(void)
{
#ifdef AMD64
	_enable();
#else
	__asm{sti};
#endif
}

void disableInterrupts(void)
{
#ifdef AMD64
	_disable();
#else
	__asm{cli};
#endif
}

UINT64 getTSC(void)
{
	return __rdtsc();
}

#ifndef AMD64
//function declarations that can be done inline without needing an .asm file
_declspec( naked ) WORD getSS(void)
{
	__asm
	{
		mov ax,ss
		ret
	}
}

_declspec( naked ) WORD getCS(void)
{
	__asm
	{
		mov ax,cs
		ret
	}
}

_declspec( naked ) WORD getDS(void)
{
	__asm
	{
		mov ax,ds
		ret
	}
}

_declspec( naked ) WORD getES(void)
{
	__asm
	{
		mov ax,es
		ret
	}
}

_declspec( naked ) WORD getFS(void)
{
	__asm
	{
		mov ax,fs
		ret
	}
}

_declspec( naked ) WORD getGS(void)
{
	__asm
	{
		mov ax,gs
		ret
	}
}


_declspec( naked ) ULONG getRSP(void) //...
{
	__asm
	{
		mov eax,esp
		add eax,4 //don't add this call
		ret
	}
}

_declspec( naked ) ULONG getRBP(void)
{
	__asm
	{
		mov eax,ebp
		ret
	}
}

_declspec( naked ) ULONG getRAX(void)
{
	__asm
	{
		mov eax,eax
		ret
	}
}
_declspec( naked ) ULONG getRBX(void)
{
	__asm
	{
		mov eax,ebx
		ret
	}
}
_declspec( naked ) ULONG getRCX(void)
{
	__asm
	{
		mov eax,ecx
		ret
	}
}
_declspec( naked ) ULONG getRDX(void)
{
	__asm
	{
		mov eax,edx
		ret
	}
}
_declspec( naked ) ULONG getRSI(void)
{
	__asm
	{
		mov eax,esi
		ret
	}
}
_declspec( naked ) ULONG getRDI(void)
{
	__asm
	{
		mov eax,edi
		ret
	}
}

_declspec( naked ) unsigned short GetTR(void)
{
	__asm{
		STR AX
		ret
	}	
}


void GetGDT(PGDT pGdt)
{
	__asm
    {
		MOV EAX, [pGdt]
	    SGDT [EAX]
    }       
}

_declspec( naked )WORD GetLDT()
{	
	__asm
	{		
		SLDT ax
		ret
	}
}

#endif


================================================
FILE: src/DBKFunc.h
================================================
#ifndef DBKFUNC_H
#define DBKFUNC_H

#pragma warning( disable: 4214 )

#include <ntifs.h>
#include <ntstrsafe.h>

#include <windef.h>

#include "interruptHook.h"

#ifdef RELEASE
#define DbgPrint(...)
#endif

int _fltused;


typedef VOID F(UINT_PTR param);
typedef F *PF;

typedef VOID PREDPC_CALLBACK(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID DeferredContext, PVOID *SystemArgument1, PVOID *SystemArgument2);

typedef PREDPC_CALLBACK *PPREDPC_CALLBACK;


typedef struct _criticalSection
{
  LONG locked;
  int cpunr; //unique id for a cpu
  int lockcount;
  int oldIFstate;
} criticalSection, *PcriticalSection;


//ntosp.h

typedef
_Function_class_(KNORMAL_ROUTINE)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KNORMAL_ROUTINE(
	_In_opt_ PVOID NormalContext,
	_In_opt_ PVOID SystemArgument1,
	_In_opt_ PVOID SystemArgument2
);
typedef KNORMAL_ROUTINE *PKNORMAL_ROUTINE;

typedef
_Function_class_(KKERNEL_ROUTINE)
_IRQL_requires_max_(APC_LEVEL)
_IRQL_requires_min_(APC_LEVEL)
_IRQL_requires_(APC_LEVEL)
_IRQL_requires_same_
VOID
KKERNEL_ROUTINE(
	_In_ struct _KAPC *Apc,
	_Inout_ PKNORMAL_ROUTINE *NormalRoutine,
	_Inout_ PVOID *NormalContext,
	_Inout_ PVOID *SystemArgument1,
	_Inout_ PVOID *SystemArgument2
);
typedef KKERNEL_ROUTINE *PKKERNEL_ROUTINE;


typedef
_Function_class_(KRUNDOWN_ROUTINE)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KRUNDOWN_ROUTINE(
	_In_ struct _KAPC *Apc
);
typedef KRUNDOWN_ROUTINE *PKRUNDOWN_ROUTINE;


typedef
_IRQL_requires_same_
_Function_class_(KENUM_ROUTINE)
VOID
KENUM_ROUTINE(
	_In_reads_(_Inexpressible_(Length)) PVOID Data,
	_In_ ULONG Length,
	_In_ PVOID Context
);

typedef KENUM_ROUTINE *PKENUM_ROUTINE;

typedef enum _KAPC_ENVIRONMENT {
	OriginalApcEnvironment,
	AttachedApcEnvironment,
	CurrentApcEnvironment,
	InsertApcEnvironment
} KAPC_ENVIRONMENT;



NTKERNELAPI
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KeEnumerateQueueApc(
	_Inout_ PKTHREAD Thread,
	_In_ PKENUM_ROUTINE CallbackRoutine,
	_In_ PVOID Context,
	_In_opt_ KPROCESSOR_MODE *ApcMode
);


NTKERNELAPI
_IRQL_requires_same_
_When_(Environment != OriginalApcEnvironment, __drv_reportError("Caution: "
	"Using an APC environment other than the original environment can lead to "
	"a system bugcheck if the target thread is attached to a process with APCs "
	"disabled. APC environments should be used with care."))
	VOID
	KeInitializeApc(
		_Out_ PRKAPC Apc,
		_In_ PRKTHREAD Thread,
		_In_ KAPC_ENVIRONMENT Environment,
		_In_ PKKERNEL_ROUTINE KernelRoutine,
		_In_opt_ PKRUNDOWN_ROUTINE RundownRoutine,
		_In_opt_ PKNORMAL_ROUTINE NormalRoutine,
		_In_opt_ KPROCESSOR_MODE ProcessorMode,
		_In_opt_ PVOID NormalContext
	);

NTKERNELAPI
_Must_inspect_result_
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_same_
BOOLEAN
KeInsertQueueApc(
	_Inout_ PRKAPC Apc,
	_In_opt_ PVOID SystemArgument1,
	_In_opt_ PVOID SystemArgument2,
	_In_ KPRIORITY Increment
);



NTSYSAPI
NTSTATUS
NTAPI
ZwOpenThread(
	OUT PHANDLE             ThreadHandle,
	IN ACCESS_MASK          DesiredAccess,
	IN POBJECT_ATTRIBUTES   ObjectAttributes,
	IN PCLIENT_ID           ClientId
);



struct PTEStruct
{
	unsigned P         :  1; // present (1 = present)
	unsigned RW        :  1; // read/write
	unsigned US        :  1; // user/supervisor
	unsigned PWT       :  1; // page-level write-through
	unsigned PCD       :  1; // page-level cache disabled
	unsigned A         :  1; // accessed
	unsigned Reserved  :  1; // dirty
	unsigned PS        :  1; // page size (0 = 4-KB page)
	unsigned G         :  1; // global page
	unsigned A1		   :  1; // available 1 aka copy-on-write
	unsigned A2		   :  1; // available 2/ is 1 when paged to disk
	unsigned A3		   :  1; // available 3
	unsigned PFN       : 20; // page-frame number
};

//typedef struct PTEStruct *PPDPTE;
//typedef struct PTEStruct *PPDE;
//typedef struct PTEStruct *PPTE;

struct PTEStruct64
{
	unsigned long long P : 1; // present (1 = present)
	unsigned long long RW : 1; // read/write
	unsigned long long US : 1; // user/supervisor
	unsigned long long PWT : 1; // page-level write-through
	unsigned long long PCD : 1; // page-level cache disabled
	unsigned long long A : 1; // accessed
	unsigned long long Reserved : 1; // dirty
	unsigned long long PS : 1; // page size (0 = 4-KB page)
	unsigned long long G : 1; // global page
	unsigned long long A1 : 1; // available 1 aka copy-on-write
	unsigned long long A2 : 1; // available 2/ is 1 when paged to disk
	unsigned long long A3 : 1; // available 3
	unsigned long long PFN : 52; // page-frame number
};

//typedef struct PTEStruct64 *PPDPTE_PAE;
//typedef struct PTEStruct64 *PPDE_PAE;
//typedef struct PTEStruct64 *PPTE_PAE;


typedef struct tagDebugregs
{
	ULONG DR0;
	ULONG DR1;
	ULONG DR2;
	ULONG DR3;
	ULONG DR5;
	ULONG DR6;
	ULONG DR7;
} Debugregs;



typedef struct 
{
	unsigned CF			:1; // 0
	unsigned reserved1	:1; // 1
	unsigned PF			:1; // 2
	unsigned reserved2	:1; // 3
	unsigned AF			:1; // 4
	unsigned reserved3	:1; // 5
	unsigned ZF			:1; // 6
	unsigned SF			:1; // 7
	unsigned TF			:1; // 8
	unsigned IF			:1; // 9
	unsigned DF			:1; // 10
	unsigned OF			:1; // 11
	unsigned IOPL		:2; // 12+13
	unsigned NT			:1; // 14
	unsigned reserved4	:1; // 15
	unsigned RF			:1; // 16
	unsigned VM			:1; // 17
	unsigned AC			:1; // 18
	unsigned VIF		:1; // 19
	unsigned VIP		:1; // 20
	unsigned ID			:1; // 21
	unsigned reserved5	:10; // 22-31
#ifdef AMD64
	unsigned reserved6	:8;
	unsigned reserved7	:8;
	unsigned reserved8	:8;
	unsigned reserved9	:8;
#endif
} EFLAGS,*PEFLAGS;

typedef struct tagDebugReg7
{
	unsigned L0			:1; //			0
	unsigned G0			:1; //			1
	unsigned L1			:1; //			2
	unsigned G1			:1; //			3
	unsigned L2			:1; //			4
	unsigned G2			:1; //			5
	unsigned L3			:1; //			6
	unsigned G3			:1; //			7
	unsigned GL			:1; //			8
	unsigned GE			:1; //			9
	unsigned undefined_1: 1; //1       10
	unsigned RTM		: 1; //        11
	unsigned undefined_0: 1; //0       12
	unsigned GD			:1; //		   13
	unsigned undefined2	:2; // 00 
	unsigned RW0		:2;
	unsigned LEN0		:2;
	unsigned RW1		:2;
	unsigned LEN1		:2;
	unsigned RW2		:2;
	unsigned LEN2		:2;
	unsigned RW3		:2;
	unsigned LEN3		:2;
#ifdef AMD64
	unsigned undefined3	:8;
	unsigned undefined4	:8;
	unsigned undefined5	:8;
	unsigned undefined6	:8;
#endif
} DebugReg7;

typedef struct DebugReg6
{
	unsigned B0			:1;
	unsigned B1			:1;
	unsigned B2			:1;
	unsigned B3			:1;
	unsigned undefined1	:9; // 011111111
	unsigned BD			:1;
	unsigned BS			:1;
	unsigned BT			:1;
	unsigned RTM       : 1; //0=triggered
	unsigned undefined2	:15; // 111111111111111
#ifdef AMD64
	unsigned undefined3	:8;
	unsigned undefined4	:8;
	unsigned undefined5	:8;
	unsigned undefined6	:8;
#endif
} DebugReg6;




#pragma pack(2) //allignment of 2 bytes
typedef struct tagGDT
{    
    WORD wLimit;
	PVOID vector;
} GDT, *PGDT;
#pragma pack()

//UCHAR BufferSize;

void GetIDT(PIDT pIdt);

#ifdef AMD64
extern void _fxsave(volatile void *);
extern void GetGDT(PGDT pGdt);
extern WORD GetLDT();
extern WORD GetTR(void);
#else
void GetGDT(PGDT pGdt);
WORD GetLDT();
WORD GetTR(void);
#endif



UINT64 readMSR(DWORD msr);
UINT64 getDR7(void);
void setCR0(UINT64 newCR0);
UINT64 getCR0(void);
UINT64 getCR2(void);
void setCR3(UINT64 newCR3);
UINT64 getCR3(void);
UINT64 getCR4(void);
void setCR4(UINT64 newcr4);
UINT64 getTSC(void);

#ifdef AMD64

extern WORD getCS(void);
extern WORD getSS(void);
extern WORD getDS(void);
extern WORD getES(void);
extern WORD getFS(void);
extern WORD getGS(void);
extern UINT64 getRSP(void);
extern UINT64 getRBP(void);
extern UINT64 getRAX(void);
extern UINT64 getRBX(void);
extern UINT64 getRCX(void);
extern UINT64 getRDX(void);
extern UINT64 getRSI(void);
extern UINT64 getRDI(void);
#else
WORD getCS(void);
WORD getSS(void);
WORD getDS(void);
WORD getES(void);
WORD getFS(void);
WORD getGS(void);
ULONG getRSP(void);
ULONG getRBP(void);
ULONG getRAX(void);
ULONG getRBX(void);
ULONG getRCX(void);
ULONG getRDX(void);
ULONG getRSI(void);
ULONG getRDI(void);
#endif

extern UINT64 getR8(void);
extern UINT64 getR9(void);
extern UINT64 getR10(void);
extern UINT64 getR11(void);
extern UINT64 getR12(void);
extern UINT64 getR13(void);
extern UINT64 getR14(void);
extern UINT64 getR15(void);

extern UINT64 getAccessRights(UINT64 segment);
extern UINT64 getSegmentLimit(UINT64 segment);


int getCpuCount(void);

BOOL loadedbydbvm;
int PTESize;
UINT_PTR PAGE_SIZE_LARGE;
UINT_PTR MAX_PDE_POS;
UINT_PTR MAX_PTE_POS;

int cpu_stepping;
int cpu_model;
int cpu_familyID;
int cpu_type;
int cpu_ext_modelID;
int cpu_ext_familyID;

int KernelCodeStepping;
int KernelWritesIgnoreWP;

int isPrefix(unsigned char b);
EFLAGS getEflags(void);
int cpunr(void);
void disableInterrupts(void);
void enableInterrupts(void);


void csEnter(PcriticalSection CS);
void csLeave(PcriticalSection CS);

void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpu(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpuPassive(PF f, UINT_PTR param);

#endif;

================================================
FILE: src/IOPLDispatcher.c
================================================
#pragma warning( disable: 4100 4101 4103 4189)


#include "IOPLDispatcher.h"
#include "DBKFunc.h"
#include "DBKDrvr.h"


#include "memscan.h"

#include "deepkernel.h"

#include "processlist.h"
#include "threads.h"

#include "interruptHook.h"
#include "debugger.h"

#include "vmxhelper.h"
#include "vmxoffload.h"
#include "ultimap.h"
#include "ultimap2.h"


UINT64 PhysicalMemoryRanges=0; //initialized once, and used thereafter. If the user adds/removes ram at runtime, screw him and make him the reload the driver
UINT64 PhysicalMemoryRangesListSize=0;

#if (NTDDI_VERSION >= NTDDI_VISTA)
PVOID DRMHandle = NULL;
PEPROCESS DRMProcess = NULL;
PEPROCESS DRMProcess2 = NULL;
#endif

typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process); 
GET_PROCESS_IMAGE_NAME PsGetProcessImageFileName; 


/*
typedef struct
{
	int listcount;
	char cpunrs[255];
} CPULISTFILLSTRUCT, *PCPULISTFILLSTRUCT;

VOID GetCPUIDS_all(PCPULISTFILLSTRUCT p)
{
	DbgPrint("GetCPUIDS_all(for cpu %d)\n", cpunr());
	if (p->listcount<255)
	{
		p->cpunrs[p->listcount]=cpunr();
		p->listcount++;
	}
}
*/

NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL);



void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
	ULONG_PTR iswow64;
	ExFreePool(Apc);
	DbgPrint("My second kernelmode apc!!!!\n");
	DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument1);
	DbgPrint("SystemArgument2=%x\n", *(PULONG)SystemArgument2);

	if (ZwQueryInformationProcess(ZwCurrentProcess(), ProcessWow64Information, &iswow64, sizeof(iswow64), NULL) == STATUS_SUCCESS)
	{
#if (NTDDI_VERSION >= NTDDI_VISTA)	
		if (iswow64)
		{
			DbgPrint("WOW64 apc");
			PsWrapApcWow64Thread(NormalContext, (PVOID*)NormalRoutine);
		}
#endif
	}

}

void nothing2(PVOID arg1, PVOID arg2, PVOID arg3)
{
	
	return;
}

void mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
	//kernelmode apc, always gets executed
	PKAPC      kApc;
	LARGE_INTEGER Timeout;

	kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));

	ExFreePool(Apc);

	DbgPrint("My kernelmode apc!!!!(irql=%d)\n", KeGetCurrentIrql());
	
	DbgPrint("NormalRoutine=%p\n",*(PUINT_PTR)NormalRoutine);
	DbgPrint("NormalContext=%p\n",*(PUINT_PTR)NormalContext);
	DbgPrint("SystemArgument1=%p\n",*(PUINT_PTR)SystemArgument1);
	DbgPrint("SystemArgument2=%p\n",*(PUINT_PTR)SystemArgument2);
	
	
	
	KeInitializeApc(kApc,
		            (PKTHREAD)PsGetCurrentThread(),
                    0,
                    (PKKERNEL_ROUTINE)mykapc2,
                    NULL,
                    (PKNORMAL_ROUTINE)*(PUINT_PTR)SystemArgument1,
                    UserMode,
                    (PVOID)*(PUINT_PTR)NormalContext
                    );

	KeInsertQueueApc (kApc, (PVOID)*(PUINT_PTR)SystemArgument1, (PVOID)*(PUINT_PTR)SystemArgument2, 0);


	//wait in usermode (so interruptable by a usermode apc)
	Timeout.QuadPart = 0;
	KeDelayExecutionThread(UserMode, TRUE, &Timeout);

	return;
}

void nothing(PVOID arg1, PVOID arg2, PVOID arg3)
{
	return;
}


void CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)
{
	
	PKTHREAD   kThread;
	PKAPC      kApc;

	kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));

	kThread=(PKTHREAD)getPEThread(threadid);
	DbgPrint("(PVOID)KThread=%p\n",kThread);
	DbgPrint("addresstoexecute=%p\n", addresstoexecute);
	
   
	KeInitializeApc(kApc,
		            kThread,
                    0,
                    (PKKERNEL_ROUTINE)mykapc,
                    NULL,
                    (PKNORMAL_ROUTINE)nothing,
                    KernelMode,
                    0
                    );

	KeInsertQueueApc (kApc, addresstoexecute, addresstoexecute, 0);
}

#define PROCESS_TERMINATE                  (0x0001)  
#define PROCESS_CREATE_THREAD              (0x0002)  
#define PROCESS_SET_SESSIONID              (0x0004)  
#define PROCESS_VM_OPERATION               (0x0008)  
#define PROCESS_VM_READ                    (0x0010)  
#define PROCESS_VM_WRITE                   (0x0020)  
#define PROCESS_DUP_HANDLE                 (0x0040)  
#define PROCESS_CREATE_PROCESS             (0x0080)  
#define PROCESS_SET_QUOTA                  (0x0100)  
#define PROCESS_SET_INFORMATION            (0x0200)  
#define PROCESS_QUERY_INFORMATION          (0x0400)  
#define PROCESS_SUSPEND_RESUME             (0x0800)  
#define PROCESS_QUERY_LIMITED_INFORMATION  (0x1000)  


#if (NTDDI_VERSION >= NTDDI_VISTA)
OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{		
	if (DRMProcess == NULL)
		return OB_PREOP_SUCCESS;

	if (PsGetCurrentProcess() == DRMProcess)
		return OB_PREOP_SUCCESS;

	if (OperationInformation->ObjectType == *PsThreadType)
	{		
		if ((PsGetProcessId(DRMProcess) == PsGetThreadProcessId(OperationInformation->Object)) || ((DRMProcess2) && (PsGetProcessId(DRMProcess2) == PsGetThreadProcessId(OperationInformation->Object))))
		{
			//probably block it

			if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
			{
				//create handle			

				ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;

				DbgPrint("PID %d opened a handle to the a CE thread with access mask %x", PsGetCurrentProcessId(), da);

				da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);

				OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
			}
			else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
			{
				//duplicate handle
				ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;

				DbgPrint("PID %d duplicated a handle to a CE thread with access mask %x", PsGetCurrentProcessId(), da);

				da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);
				OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
			}
		}
	}
	return OB_PREOP_SUCCESS;
}


VOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
	//DbgPrint("ProcessPostCallback");
}


OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
	if (DRMProcess == NULL)
		return OB_PREOP_SUCCESS;

	//if (PsGetCurrentProcess() == DRMProcess)
	//	return OB_PREOP_SUCCESS;

	if (OperationInformation->ObjectType == *PsProcessType)
	{
		if ((OperationInformation->Object == DRMProcess) || (OperationInformation->Object == DRMProcess2))
		{
			//probably block it

			if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
			{
				//create handle			
				
				ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;

				DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);

				da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);

				//da = da & PROCESS_SUSPEND_RESUME;

				OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
			}
			else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
			{
				//duplicate handle
				ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;

				DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);


				da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);

				//da = da & PROCESS_SUSPEND_RESUME;

				OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
			}
		}
	}
	return OB_PREOP_SUCCESS;
}


VOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
	//DbgPrint("ProcessPostCallback");
}
#endif


BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned)
/*
Called if dbvm has loaded the driver. Use this to setup a fake irp
*/
{
	//allocate a in and out buffer
	//setup a fake IRP
	IRP FakeIRP;
	BOOL r;
	PVOID buffer;
	buffer=ExAllocatePool(PagedPool, max(nInBufferSize, nOutBufferSize));
	RtlCopyMemory(buffer, lpInBuffer, nInBufferSize);	


	DbgPrint("DispatchIoctlDBVM\n");

	FakeIRP.AssociatedIrp.SystemBuffer=buffer;
	FakeIRP.Flags=IoControlCode; //(ab)using an unused element

	r=DispatchIoctl(DeviceObject, &FakeIRP)==STATUS_SUCCESS;


	RtlCopyMemory(lpOutBuffer, buffer, nOutBufferSize);

	ExFreePool(buffer);

	return r;
}

NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;

    PIO_STACK_LOCATION     irpStack=NULL;
	LUID sedebugprivUID;
	ULONG IoControlCode;

	if (!loadedbydbvm)
	{
		irpStack=IoGetCurrentIrpStackLocation(Irp);
		IoControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
	}
	else
		IoControlCode=Irp->Flags;
		
	//DbgPrint("DispatchIoctl. IoControlCode=%x\n", IoControlCode);
#ifdef TOBESIGNED
    sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;
	sedebugprivUID.HighPart=0;
	
	if (SeSinglePrivilegeCheck(sedebugprivUID, UserMode)==FALSE)
	{
		DbgPrint("DispatchIoctl called by a process without SeDebugPrivilege");
		return STATUS_UNSUCCESSFUL;
	}
#endif
	

	
    switch(IoControlCode)
    {
		
        case IOCTL_CE_READMEMORY:			
			__try
			{
				struct input
				{
					UINT64 processid;
					UINT64 startaddress;
					WORD bytestoread;
				} *pinp;

				pinp=Irp->AssociatedIrp.SystemBuffer;

				ntStatus=ReadProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestoread,pinp) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
			}
			__except(1)
			{
				ntStatus = STATUS_UNSUCCESSFUL;
			};
				
            break;
			

        case IOCTL_CE_WRITEMEMORY:
			__try
			{
				struct input
				{
					UINT64 processid;
					UINT64 startaddress;
					WORD bytestowrite;
				} *pinp,inp;

				DbgPrint("sizeof(inp)=%d\n",sizeof(inp));
				pinp=Irp->AssociatedIrp.SystemBuffer;
				ntStatus=WriteProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestowrite,(PVOID)((UINT_PTR)pinp+sizeof(inp))) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
			}
			__except(1)
			{
				//something went wrong and I don't know what
				ntStatus = STATUS_UNSUCCESSFUL;
			};


				
            break;


		case IOCTL_CE_OPENPROCESS:
			{					
				PEPROCESS selectedprocess = NULL;
				ULONG processid=*(PULONG)Irp->AssociatedIrp.SystemBuffer;
				HANDLE ProcessHandle = GetHandleForProcessID((HANDLE)processid);
				struct out
				{
					UINT64 h;
					BYTE   Special;
				} *POutput = Irp->AssociatedIrp.SystemBuffer;


				ntStatus = STATUS_SUCCESS;
				if (ProcessHandle == 0)
				{
					POutput->Special = 0;
					__try
					{
						ProcessHandle = 0;

						if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid), &selectedprocess) == STATUS_SUCCESS)
						{

							//DbgPrint("Calling ObOpenObjectByPointer\n");
							ntStatus = ObOpenObjectByPointer(
								selectedprocess,
								0,
								NULL,
								PROCESS_ALL_ACCESS,
								*PsProcessType,
								KernelMode, //UserMode,
								&ProcessHandle);

							//DbgPrint("ntStatus=%x",ntStatus);
						}
					}
					__except (1)
					{
						ntStatus = STATUS_UNSUCCESSFUL;
					}
				}
				else
				{
					//DbgPrint("ProcessHandle=%x", (int)ProcessHandle);
					POutput->Special = 1;					
				}

				if (selectedprocess)
				{
					ObDereferenceObject(selectedprocess);
				}
				
				POutput->h=(UINT64)ProcessHandle;
				break;
			}
			

		case IOCTL_CE_OPENTHREAD:
			{
				HANDLE ThreadHandle;
				CLIENT_ID ClientID;
				OBJECT_ATTRIBUTES ObjectAttributes;
	
				RtlZeroMemory(&ObjectAttributes,sizeof(OBJECT_ATTRIBUTES));

				ntStatus=STATUS_SUCCESS;

				ClientID.UniqueProcess=0;
				ClientID.UniqueThread=(HANDLE)(UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer;
				ThreadHandle=0;

				__try
				{
					ThreadHandle=0;
					ntStatus=ZwOpenThread(&ThreadHandle,PROCESS_ALL_ACCESS,&ObjectAttributes,&ClientID);									
				}
				__except(1)
				{
					ntStatus=STATUS_UNSUCCESSFUL;
				}
			
				*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)ThreadHandle;
				

				break;
			}

			
		case IOCTL_CE_MAKEWRITABLE:
			{
#ifdef AMD64
				//untill I know how win64 handles paging, not implemented
#else
				struct InputBuf
				{
				    UINT64 StartAddress;
					ULONG Size;
					BYTE CopyOnWrite;
				} *PInputBuf;

				PInputBuf=Irp->AssociatedIrp.SystemBuffer;
				
				ntStatus=MakeWritable((PVOID)(UINT_PTR)PInputBuf->StartAddress,PInputBuf->Size,(PInputBuf->CopyOnWrite==1)) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 
#endif
				break;
			}
			


		case IOCTL_CE_QUERY_VIRTUAL_MEMORY:
			{
				struct InputBuf
				{
				    UINT64 ProcessID;
					UINT64 StartAddress;
				} *PInputBuf;

				struct OutputBuf
				{				
					UINT64 length;
					DWORD protection;
				} *POutputBuf;

				
			     
				UINT_PTR BaseAddress;
				UINT_PTR length;
				BOOL ShowResult=0;

				
                ntStatus=STATUS_SUCCESS;
				PInputBuf=Irp->AssociatedIrp.SystemBuffer;
				POutputBuf=Irp->AssociatedIrp.SystemBuffer;


				if (PInputBuf->StartAddress==(UINT64)0x12000)
					ShowResult=1;
				

				__try
				{
					ntStatus = GetMemoryRegionData((DWORD)PInputBuf->ProcessID, NULL, (PVOID)(UINT_PTR)(PInputBuf->StartAddress), &(POutputBuf->protection), &length, &BaseAddress);
				}
				__except(1)
				{
					DbgPrint("GetMemoryRegionData error");
					ntStatus = STATUS_UNSUCCESSFUL;
					break;
				}

				POutputBuf->length=(UINT64)length;

				if (ShowResult)
				{									
				  DbgPrint("GetMemoryRegionData returned %x\n",ntStatus);
				  DbgPrint("protection=%x\n",POutputBuf->protection);
				  DbgPrint("length=%p\n",POutputBuf->length);
				  DbgPrint("BaseAddress=%p\n", BaseAddress);
				}


				
				break;
			}
			

		case IOCTL_CE_TEST: //just a test to see it's working
			{
				UNICODE_STRING test;
				PVOID x;
				QWORD a, b;

				_disable();
				a = __rdtsc();
				b = __rdtsc();

				_enable();

				
				DbgPrint("%d\n", (int)(b - a));				
				break;
			}

		case IOCTL_CE_GETPETHREAD:
			{
				
				*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)getPEThread((UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer);
				ntStatus= STATUS_SUCCESS;
				break;
			}
			

		case IOCTL_CE_GETPEPROCESS:
			{
				DWORD processid=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;
				PEPROCESS selectedprocess;
			

				if (processid==0)
				{
					ntStatus=STATUS_UNSUCCESSFUL;
				}
				else
				{
					if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid),&selectedprocess)==STATUS_SUCCESS)
					{
#ifdef AMD64
						*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)selectedprocess;
#else
						*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(DWORD)selectedprocess;
#endif
						//DbgPrint("PEProcess=%llx\n", *(PUINT64)Irp->AssociatedIrp.SystemBuffer);
						ObDereferenceObject(selectedprocess);

					}
					else
						*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
				}

				

				ntStatus= STATUS_SUCCESS;				
				break;
			}

			
		case IOCTL_CE_READPHYSICALMEMORY:
			{
				struct input
				{
					UINT64 startaddress;
					UINT64 bytestoread;
				} *pinp;
				pinp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_READPHYSICALMEMORY:pinp->startaddress=%x, pinp->bytestoread=%d", pinp->startaddress, pinp->bytestoread); 


				ntStatus = ReadPhysicalMemory((PVOID)(UINT_PTR)pinp->startaddress, (UINT_PTR)pinp->bytestoread, pinp);
				break;



			}

		case IOCTL_CE_WRITEPHYSICALMEMORY:
			{
				HANDLE			physmem;
				UNICODE_STRING	physmemString;
				OBJECT_ATTRIBUTES attributes;
				WCHAR			physmemName[] = L"\\device\\physicalmemory";
				UCHAR*			memoryview;

				RtlInitUnicodeString( &physmemString, physmemName );	

            	InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );	
			    ntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );
				if (ntStatus==STATUS_SUCCESS)
				{
					//hey look, it didn't kill it
					struct input
					{
						UINT64 startaddress;
						UINT64 bytestoread;
					} *pinp;

					UCHAR* pinp2;

					SIZE_T length;
					PHYSICAL_ADDRESS	viewBase;
					UINT_PTR offset;
					UINT_PTR toread;

					
					pinp=Irp->AssociatedIrp.SystemBuffer;
					pinp2=(UCHAR *)pinp;
					viewBase.QuadPart = (ULONGLONG)(pinp->startaddress);					
					
					length=0x2000;//pinp->bytestoread;
					toread=(UINT_PTR)pinp->bytestoread;

					memoryview=NULL;
					ntStatus=ZwMapViewOfSection(
						physmem,  //sectionhandle
						NtCurrentProcess(), //processhandle
						&memoryview, //BaseAddress
						0L, //ZeroBits
						length, //CommitSize
						&viewBase, //SectionOffset
						&length, //ViewSize
						ViewShare,
						0,
						PAGE_READWRITE);

					if (ntStatus==STATUS_SUCCESS)
					{
                        offset=(UINT_PTR)(pinp->startaddress)-(UINT_PTR)viewBase.QuadPart;
						RtlCopyMemory(&memoryview[offset],&pinp2[16],toread);

						ZwUnmapViewOfSection(
							NtCurrentProcess(), //processhandle
							memoryview);
					}

					ZwClose(physmem);
				}

				break;
			}

			

		case IOCTL_CE_GETPHYSICALADDRESS:
			{
				struct input
				{
					UINT64  ProcessID;
					UINT64 BaseAddress; 
				} *pinp;

				PEPROCESS selectedprocess;
				PHYSICAL_ADDRESS physical;
				physical.QuadPart = 0;

				ntStatus=STATUS_SUCCESS;
				pinp=Irp->AssociatedIrp.SystemBuffer;

				//DbgPrint("IOCTL_CE_GETPHYSICALADDRESS. ProcessID(%p)=%x BaseAddress(%p)=%x\n",&pinp->ProcessID, pinp->ProcessID, &pinp->BaseAddress, pinp->BaseAddress);

				__try
				{
					//switch to the selected process
					if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(pinp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
					{
						KAPC_STATE apc_state;
						RtlZeroMemory(&apc_state,sizeof(apc_state));					
    					KeStackAttachProcess((PVOID)selectedprocess,&apc_state);
                 
						__try
						{
							physical=MmGetPhysicalAddress((PVOID)(UINT_PTR)pinp->BaseAddress);
						}
						__finally
						{
							KeUnstackDetachProcess(&apc_state);
						}
	

						ObDereferenceObject(selectedprocess);

					}
				}
				__except(1)
				{
						ntStatus=STATUS_UNSUCCESSFUL;
				}

				if (ntStatus==STATUS_SUCCESS)
				{
					//DbgPrint("physical.LowPart=%x",physical.LowPart);
                    RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&physical.QuadPart,8);

				}
				
				
				break;
			}

		case IOCTL_CE_GETMEMORYRANGES:
			{
				
				struct output
				{
					UINT64 address;
					UINT64 size;
				} *poutp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_GETMEMORYRANGES\n");


				if (PhysicalMemoryRanges==0)
				{
					__try
					{
						PPHYSICAL_MEMORY_RANGE mr=MmGetPhysicalMemoryRanges();
						
						if (mr)
						{
							//find the end
							int i;
							PhysicalMemoryRanges=(UINT64)mr;
							for (i=0; mr[i].NumberOfBytes.QuadPart || mr[i].BaseAddress.QuadPart; i++);

							PhysicalMemoryRangesListSize=(UINT64)(&mr[i])-(UINT64)(&mr[0]);
						}
						


					}
					__except(1)
					{
						//just in case this function decides to bug out in the future
					}
				}
				
				poutp->address=PhysicalMemoryRanges;
				poutp->size=PhysicalMemoryRangesListSize;

				ntStatus=STATUS_SUCCESS;

				break;
			}
			
		case IOCTL_CE_GETSDTADDRESS:
			{
				DbgPrint("Obsolete\n");
				ntStatus=STATUS_UNSUCCESSFUL;
				break;
			}
			

		case IOCTL_CE_GETCR0:
			{
				*(UINT64*)Irp->AssociatedIrp.SystemBuffer=getCR0();
				ntStatus=STATUS_SUCCESS;

				break;
			}
			

		case IOCTL_CE_GETCR4:
			{
				//seems CR4 isn't seen as a register...
				*(UINT64*)Irp->AssociatedIrp.SystemBuffer=(UINT64)getCR4();
				ntStatus=STATUS_SUCCESS;

				break;
			}
			

		case IOCTL_CE_SETCR4:
			{
				//seems CR4 isn't seen as a register...
				ULONG cr4reg=*(ULONG*)Irp->AssociatedIrp.SystemBuffer;
				setCR4((UINT64)cr4reg);
				ntStatus=STATUS_SUCCESS;
				break;
			}
			

		case IOCTL_CE_GETCR3:
			{
				UINT_PTR cr3reg=0;
				PEPROCESS selectedprocess;


				ntStatus=STATUS_SUCCESS;

				//switch context to the selected process.  (processid is stored in the systembuffer)
				if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(*(ULONG*)Irp->AssociatedIrp.SystemBuffer),&selectedprocess)==STATUS_SUCCESS)
				{
					__try
					{
						KAPC_STATE apc_state;
						RtlZeroMemory(&apc_state,sizeof(apc_state));					
    					KeStackAttachProcess((PVOID)selectedprocess,&apc_state);

						__try
						{
							cr3reg=(UINT_PTR)getCR3();

						}
						__finally
						{
							KeUnstackDetachProcess(&apc_state);
						}

					}
					__except(1)
					{
						ntStatus=STATUS_UNSUCCESSFUL;
						break;
					}

					ObDereferenceObject(selectedprocess);

				}

				DbgPrint("cr3reg=%p\n",cr3reg);

				*(UINT64*)Irp->AssociatedIrp.SystemBuffer=cr3reg;

				break;
			}

			

		case IOCTL_CE_GETSDT:
			{
				//returns the address of KeServiceDescriptorTable
				ntStatus = STATUS_UNSUCCESSFUL;
				break;
			}	
			


		case IOCTL_CE_GETIDT:
			{
				//returns the address of the IDT of the current CPU
				IDT idt;
				RtlZeroMemory(&idt,sizeof(IDT));				
				GetIDT(&idt);
				RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); //so that the 32-bit version doesn't have to deal with garbage at the end
				RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&idt,sizeof(IDT)); //copy idt
				ntStatus=STATUS_SUCCESS;
			
				break;
			}	

		case IOCTL_CE_GETGDT:
			{
				//returns the address of the IDT of the current CPU
				GDT gdt;
				RtlZeroMemory(&gdt,sizeof(GDT));
				GetGDT(&gdt);
				RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); 
				RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&gdt,sizeof(GDT)); //copy gdt
				ntStatus=STATUS_SUCCESS;
			
				break;
			}
			
		case IOCTL_CE_LAUNCHDBVM:
			{
				struct intput
				{
					UINT64 dbvmimgpath;	
					DWORD32 cpuid;
				} *pinp;
				pinp=Irp->AssociatedIrp.SystemBuffer;
				DbgPrint("IOCTL_CE_LAUNCHDBVM\n");

				initializeDBVM((PCWSTR)(UINT_PTR)pinp->dbvmimgpath);

				if (pinp->cpuid == 0xffffffff) {
					forEachCpu(vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);
					cleanupDBVM();
				}
				else
					forOneCpu((CCHAR)pinp->cpuid, vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);

				DbgPrint("Returned from vmxoffload()\n");
				break;
			}
			

		case IOCTL_CE_HOOKINTS: //hooks the DEBUG interrupts
			{
				DbgPrint("IOCTL_CE_HOOKINTS\n");
				forEachCpu(debugger_initHookForCurrentCPU_DPC, NULL, NULL, NULL, NULL);
				ntStatus=STATUS_SUCCESS;

				/*
				DbgPrint("IOCTL_CE_HOOKINTS for cpu %d\n", cpunr());
				if (debugger_initHookForCurrentCPU())
					ntStatus=STATUS_SUCCESS;
				else
				    ntStatus=STATUS_UNSUCCESSFUL;*/

				break;
			}

		case IOCTL_CE_USERDEFINEDINTERRUPTHOOK:
			{
				struct intput
				{
					UINT64 interruptnumber;
					UINT64 newCS;
					UINT64 newRIP;
					UINT64 addressofjumpback;
				} *pinp;
				DbgPrint("IOCTL_CE_USERDEFINEDINTERRUPTHOOK\n");

				pinp=Irp->AssociatedIrp.SystemBuffer;


				inthook_HookInterrupt((unsigned char)(pinp->interruptnumber), (int)pinp->newCS, (ULONG_PTR)pinp->newRIP, (PJUMPBACK)(UINT_PTR)(pinp->addressofjumpback));
				DbgPrint("After the hook\n");
				ntStatus=STATUS_SUCCESS;
				break;
			}


		case IOCTL_CE_UNHOOKALLINTERRUPTS:
			{
				int i;
				DbgPrint("IOCTL_CE_UNHOOKALLINTERRUPTS for cpu %d\n",cpunr());
				for (i=0; i<256; i++)
					inthook_UnhookInterrupt((unsigned char)i);

				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_SETGLOBALDEBUGSTATE:
			{
				struct intput
				{
					BOOL newstate;
				} *pinp;
				pinp=Irp->AssociatedIrp.SystemBuffer;

				debugger_setGlobalDebugState(pinp->newstate);
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_DEBUGPROCESS:
			{
				struct input
				{					
					DWORD	ProcessID;
				} *pinp;

				DbgPrint("IOCTL_CE_DEBUGPROCESS\n");			
				pinp=Irp->AssociatedIrp.SystemBuffer;
				debugger_startDebugging(pinp->ProcessID);

				ntStatus=STATUS_SUCCESS;

				break;

			}

		case IOCTL_CE_STOPDEBUGGING:
			{
				debugger_stopDebugging();
				ntStatus=STATUS_SUCCESS;
				break;
			}
			

			


		case IOCTL_CE_STARTPROCESSWATCH:
			{
				NTSTATUS r = STATUS_SUCCESS;
				DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");

				ProcessWatcherOpensHandles = *(char *)Irp->AssociatedIrp.SystemBuffer != 0;

				if (CreateProcessNotifyRoutineEnabled && WatcherProcess)
				{	
					ntStatus = STATUS_UNSUCCESSFUL;
					break;
				}							

				//still here
				ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);				
				ProcessEventCount=0;				
				ExReleaseResourceLite(&ProcesslistR);
				
				//DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");

				CleanProcessList();

					
				
				if ((r == STATUS_SUCCESS) && (CreateProcessNotifyRoutineEnabled == FALSE))
				{
					
					DbgPrint("calling PsSetCreateProcessNotifyRoutine\n");

					
#if (NTDDI_VERSION >= NTDDI_VISTASP1) 
					r=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx, FALSE);
					CreateProcessNotifyRoutineEnabled = r== STATUS_SUCCESS;
#else
				    CreateProcessNotifyRoutineEnabled = (PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,FALSE)==STATUS_SUCCESS);					
#endif
					if (CreateProcessNotifyRoutineEnabled)
						CreateThreadNotifyRoutineEnabled = (PsSetCreateThreadNotifyRoutine(CreateThreadNotifyRoutine) == STATUS_SUCCESS);
				}

				ntStatus=(CreateProcessNotifyRoutineEnabled) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;

				if (ntStatus==STATUS_SUCCESS)
					DbgPrint("CreateProcessNotifyRoutineEnabled worked\n");
				else
					DbgPrint("CreateProcessNotifyRoutineEnabled failed (r=%x)\n",r);
					

				break;
			}

			

		case IOCTL_CE_GETPROCESSEVENTS:
			{
				
				ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);

				*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ProcessEventCount;	
				RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ProcessEventdata[0],ProcessEventCount*sizeof(ProcessEventdta));
				ProcessEventCount=0; //there's room for new events

				ExReleaseResourceLite(&ProcesslistR);

				ntStatus=STATUS_SUCCESS;
				break;
			}
			

		case IOCTL_CE_GETTHREADEVENTS:
			{
				ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);

				*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ThreadEventCount;	
				RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ThreadEventData[0],ThreadEventCount*sizeof(ThreadEventDta));
				ThreadEventCount=0; //there's room for new events

				ExReleaseResourceLite(&ProcesslistR);

				ntStatus=STATUS_SUCCESS;
				break;
			}



		case IOCTL_CE_CREATEAPC:
			{
				struct input
				{
					UINT64 threadid;
					UINT64 addresstoexecute;										
				} *inp;
				inp=Irp->AssociatedIrp.SystemBuffer;

				CreateRemoteAPC((ULONG)inp->threadid,(PVOID)(UINT_PTR)inp->addresstoexecute);
				ntStatus=STATUS_SUCCESS;
				break;
			}

		
		case IOCTL_CE_SUSPENDTHREAD:
			{
				struct input
				{
					ULONG threadid;							
				} *inp;
				inp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("CE_SUSPENDTHREAD\n");

				DBKSuspendThread(inp->threadid);
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_RESUMETHREAD:            
			{
				struct input
				{
					ULONG threadid;							
				} *inp;
				inp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("CE_RESUMETHREAD\n");

				DBKResumeThread(inp->threadid);
				ntStatus=STATUS_SUCCESS;
				break;
            }
			

		case IOCTL_CE_SUSPENDPROCESS:
			{
				struct input
				{
					ULONG processid;							
				} *inp;
				inp=Irp->AssociatedIrp.SystemBuffer;

				

				DbgPrint("IOCTL_CE_SUSPENDPROCESS\n");

				if (PsSuspendProcess)
				{
					PEPROCESS selectedprocess;
					if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
					{
						ntStatus = PsSuspendProcess(selectedprocess);
						ObDereferenceObject(selectedprocess);
					}
					else
						ntStatus = STATUS_NOT_FOUND;
				}
				else
					ntStatus = STATUS_NOT_IMPLEMENTED;

				break;				
			}
			

		case IOCTL_CE_RESUMEPROCESS:            
			{
				struct input
				{
					ULONG processid;
				} *inp;
				inp = Irp->AssociatedIrp.SystemBuffer;



				DbgPrint("IOCTL_CE_RESUMEPROCESS\n");

				if (PsResumeProcess)
				{
					PEPROCESS selectedprocess;
					if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
					{
						ntStatus = PsResumeProcess(selectedprocess);
						ObDereferenceObject(selectedprocess);
					}
					else
						ntStatus = STATUS_NOT_FOUND;
				}
				else
					ntStatus = STATUS_NOT_IMPLEMENTED;

				break;
            }

		case IOCTL_CE_ALLOCATEMEM:
			{
				struct input
				{
					UINT64 ProcessID;
					UINT64 BaseAddress;
					UINT64 Size;
					UINT64 AllocationType;
					UINT64 Protect;
				} *inp;
				PEPROCESS selectedprocess;

				PVOID BaseAddress;
				SIZE_T RegionSize;


				inp=Irp->AssociatedIrp.SystemBuffer;
				BaseAddress=(PVOID)(UINT_PTR)inp->BaseAddress;
				RegionSize=(SIZE_T)(inp->Size);


				if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
				{
					__try
					{
						KAPC_STATE apc_state;
						RtlZeroMemory(&apc_state,sizeof(apc_state));					
    					KeAttachProcess((PVOID)selectedprocess); //local process is much more fun!!!!

						DbgPrint("Switched Process\n");
						__try
						{
							DbgPrint("Calling ZwAllocateVirtualMemory\n");
							DbgPrint("Before call: BaseAddress=%p\n", BaseAddress);		
							DbgPrint("Before call: RegionSize=%x\n", RegionSize);

							ntStatus=ZwAllocateVirtualMemory((HANDLE)-1, &BaseAddress, 0, &RegionSize, (ULONG)inp->AllocationType, (ULONG)inp->Protect);

							if ((ntStatus==STATUS_SUCCESS) && (HiddenDriver))
							{
								//initialize the memory with crap so it becomes paged
								int i;
								char *x;
								x=BaseAddress;
								for (i=0; i < (int)RegionSize;i++)
									x[i]=(unsigned char)i;
							}
							
							DbgPrint("ntStatus=%x\n", ntStatus);
							DbgPrint("BaseAddress=%p\n",BaseAddress);
							DbgPrint("RegionSize=%x\n",RegionSize);
							*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
							*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)BaseAddress;

						}
						__finally
						{
							KeDetachProcess();
						}

					}
					__except(1)
					{
						ntStatus=STATUS_UNSUCCESSFUL;
						break;
					}


					ObDereferenceObject(selectedprocess);
				}

				break;
			}
			

		case IOCTL_CE_ALLOCATEMEM_NONPAGED:
			{
				struct input
				{
					ULONG Size;
				} *inp;
				PVOID address;
				int size;

				inp=Irp->AssociatedIrp.SystemBuffer;
				size=inp->Size;

				address=ExAllocatePool(NonPagedPool,size);
				*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
				*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)address;
				

				if (address==0)
					ntStatus=STATUS_UNSUCCESSFUL;
				else
				{
					DbgPrint("Alloc success. Cleaning memory... (size=%d)\n",size);					
					
					DbgPrint("address=%p\n", address);
					RtlZeroMemory(address, size);
				
					ntStatus=STATUS_SUCCESS;
				}

				break;
			}

		case IOCTL_CE_FREE_NONPAGED:
			{
				struct input
				{
					UINT64 Address;
				} *inp;

				inp = Irp->AssociatedIrp.SystemBuffer;

				ExFreePool((PVOID)(UINT_PTR)inp->Address);

				ntStatus = STATUS_SUCCESS;

				break;
			}


		case IOCTL_CE_MAP_MEMORY:
			{
				struct input
				{
					UINT64 FromPID;
					UINT64 ToPID;
					UINT64 address;
					DWORD size;
				} *inp;

				struct output
				{
					UINT64 FromMDL;
					UINT64 Address;
				} *outp;

				KAPC_STATE apc_state;
				PEPROCESS selectedprocess;
				PMDL FromMDL=NULL;

				inp = Irp->AssociatedIrp.SystemBuffer;
				outp = Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_MAP_MEMORY\n");
				DbgPrint("address %x size %d\n", inp->address, inp->size);
				ntStatus = STATUS_UNSUCCESSFUL;				

				if (inp->FromPID)			
				{
					//switch
					DbgPrint("From PID %d\n", inp->FromPID);
					if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->FromPID), &selectedprocess) == STATUS_SUCCESS)
					{
						__try
						{
							RtlZeroMemory(&apc_state, sizeof(apc_state));
							KeStackAttachProcess((PVOID)selectedprocess, &apc_state); 

							__try
							{
								FromMDL=IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
								if (FromMDL)
									MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
							}
							__finally
							{
								KeUnstackDetachProcess(&apc_state);
							}

						}
						__except (1)
						{
							DbgPrint("Exception\n");
							ntStatus = STATUS_UNSUCCESSFUL;
							break;
						}	

						ObDereferenceObject(selectedprocess);
					}
				}
				else
				{
					DbgPrint("From kernel or self\n", inp->FromPID);
					__try
					{
						FromMDL = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
						if (FromMDL)
						{
							DbgPrint("IoAllocateMdl success\n");
							MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
						}
					}
					__except (1)
					{
						DbgPrint("Exception\n");

						if (FromMDL)
						{
							IoFreeMdl(FromMDL);
							FromMDL = NULL;
						}
					}
				}

				if (FromMDL)
				{
					DbgPrint("FromMDL is valid\n");

					if (inp->ToPID)
					{
						//switch
						DbgPrint("To PID %d\n", inp->ToPID);
						if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ToPID), &selectedprocess) == STATUS_SUCCESS)
						{
							__try
							{
								RtlZeroMemory(&apc_state, sizeof(apc_state));
								KeStackAttachProcess((PVOID)selectedprocess, &apc_state);

								__try
								{
									outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
									outp->FromMDL = (UINT64)FromMDL;
									ntStatus = STATUS_SUCCESS;
								}
								__finally
								{
									KeUnstackDetachProcess(&apc_state);
								}

							}
							__except (1)
							{
								DbgPrint("Exception part 2\n");
								ntStatus = STATUS_UNSUCCESSFUL;
								break;
							}

							ObDereferenceObject(selectedprocess);
						}
					}
					else
					{
						DbgPrint("To kernel or self\n", inp->FromPID);

						__try
						{
							outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
							outp->FromMDL = (UINT64)FromMDL;
							ntStatus = STATUS_SUCCESS;
						}
						__except (1)
						{
							DbgPrint("Exception part 2\n");
						}
					}



					

				}
				else
					DbgPrint("FromMDL==NULL\n");


				
				break;
			}

		case IOCTL_CE_UNMAP_MEMORY:
			{
				struct output
				{
					UINT64 FromMDL;
					UINT64 Address;
				} *inp;

				PMDL mdl;

				inp = Irp->AssociatedIrp.SystemBuffer;
				mdl = (PMDL)(UINT_PTR)inp->FromMDL;

				MmUnmapLockedPages((PMDL)(UINT_PTR)inp->Address, mdl);
				MmUnlockPages(mdl);
				IoFreeMdl(mdl);

				ntStatus = STATUS_SUCCESS; //no BSOD means success ;)

				break;
			}

		case IOCTL_CE_LOCK_MEMORY:
			{
				struct
				{
					UINT64 ProcessID;
					UINT64 address;
					UINT64 size;
				} *inp;
				
				struct
				{					
					UINT64 mdl;
				} *outp;
				KAPC_STATE apc_state;
				PEPROCESS selectedprocess;

				DbgPrint("IOCTL_CE_LOCK_MEMORY");
				inp = Irp->AssociatedIrp.SystemBuffer;
				outp = Irp->AssociatedIrp.SystemBuffer;
				 
				

				if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
				{
					PMDL mdl = NULL;
					KeStackAttachProcess(selectedprocess, &apc_state);

					__try
					{
						mdl = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, (ULONG)inp->size, FALSE, FALSE, NULL);
						if (mdl)
						{
							__try
							{
								MmProbeAndLockPages(mdl, UserMode, IoReadAccess);

								DbgPrint("MmProbeAndLockPages succeeded");
							}
							__except (1)
							{
								DbgPrint("MmProbeAndLockPages failed");
								IoFreeMdl(mdl);
								ntStatus = STATUS_UNSUCCESSFUL;
								break;
							}

						}
					}
					__finally
					{
						KeUnstackDetachProcess(&apc_state);
					}

					outp->mdl = (UINT_PTR)mdl;


					DbgPrint("Locked the page\n");
					ntStatus = STATUS_SUCCESS;
				}
				
				break;
			}

		case IOCTL_CE_UNLOCK_MEMORY:
		{
			struct
			{
				UINT64 mdl;
			} *inp;
			DbgPrint("IOCTL_CE_UNLOCK_MEMORY");
			inp = Irp->AssociatedIrp.SystemBuffer;

			MmUnlockPages((PMDL)(UINT_PTR)inp->mdl);
			IoFreeMdl((PMDL)(UINT_PTR)inp->mdl);
			break;
		}

		case IOCTL_CE_GETPROCADDRESS:
			{
				struct input
				{
					UINT64 s;
				} *inp;
				UNICODE_STRING y;
				UINT64 result;
				PVOID x;



				inp=Irp->AssociatedIrp.SystemBuffer;

				RtlInitUnicodeString(&y, (PCWSTR)(UINT_PTR)(inp->s));
				x=MmGetSystemRoutineAddress(&y);
				result=(UINT64)x;


				RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&result,8);
				ntStatus=STATUS_SUCCESS;

				break;
			}

		case IOCTL_CE_GETPROCESSNAMEADDRESS:
			{
				struct input
				{
					UINT64 PEPROCESS;
				} *inp;

				struct output
				{
					UINT64 Address;
				} *outp;

				UNICODE_STRING temp;

				inp=Irp->AssociatedIrp.SystemBuffer;
				outp=Irp->AssociatedIrp.SystemBuffer;

				RtlInitUnicodeString(&temp, L"PsGetProcessImageFileName");
				PsGetProcessImageFileName=(GET_PROCESS_IMAGE_NAME)MmGetSystemRoutineAddress(&temp);
				if (PsGetProcessImageFileName!=NULL)
				{
					outp->Address=(UINT_PTR)PsGetProcessImageFileName((PEPROCESS)((UINT_PTR)(inp->PEPROCESS)));
					ntStatus=STATUS_SUCCESS;
				}
				else 
				{
					DbgPrint("PsGetProcessImageFileName==NULL");
					ntStatus=STATUS_UNSUCCESSFUL;
				}

				
				break;
			}
/*x
		case IOCTL_CE_MAKEKERNELCOPY:
			{
				struct input
				{
					ULONG Base;
					ULONG KernelSize;
				} *inp;
				DbgPrint("IOCTL_CE_MAKEKERNELCOPY");
				inp=Irp->AssociatedIrp.SystemBuffer;
				ntStatus=makeKernelCopy(inp->Base, inp->KernelSize);			
				break;
			}
*/
			

		case IOCTL_CE_CONTINUEDEBUGEVENT:
			{
				struct input
				{
					BOOL handled;
				} *inp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_CONTINUEDEBUGEVENT\n");
				ntStatus=debugger_continueDebugEvent(inp->handled);
				break;

			}

		case IOCTL_CE_WAITFORDEBUGEVENT:
			{
				struct input
				{
					ULONG timeout;
				} *inp=Irp->AssociatedIrp.SystemBuffer;

				ntStatus=debugger_waitForDebugEvent(inp->timeout);

				break;

			}

		case IOCTL_CE_GETDEBUGGERSTATE:
			{	
				DbgPrint("IOCTL_CE_GETDEBUGGERSTATE\n");
				__try
				{
					ntStatus=debugger_getDebuggerState((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer));					
				}
				__except(1)
				{
					DbgPrint("Exception happened\n");
					ntStatus=STATUS_UNSUCCESSFUL;
				}
				
				DbgPrint("ntStatus=%x rax=%x\n",ntStatus, ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
				break;
			}

		case IOCTL_CE_SETDEBUGGERSTATE:
			{	
				DbgPrint("IOCTL_CE_SETDEBUGGERSTATE: state->rax=%x\n", ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
				__try
				{
					ntStatus=debugger_setDebuggerState((PDebugStackState)Irp->AssociatedIrp.SystemBuffer);
				}
				__except(1)
				{
					DbgPrint("Exception happened\n");
					ntStatus=STATUS_UNSUCCESSFUL;
				}
				break;
			}

		case IOCTL_CE_SETKERNELSTEPABILITY:
			{
				struct input
				{
					int state;
					
				} *inp=Irp->AssociatedIrp.SystemBuffer;
				KernelCodeStepping=inp->state;
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_WRITESIGNOREWP:
		{
			KernelWritesIgnoreWP = *(BYTE*)Irp->AssociatedIrp.SystemBuffer;
			ntStatus = STATUS_SUCCESS;
			break;
		}

		
		case IOCTL_CE_GD_SETBREAKPOINT:
			{
				struct input
				{
					BOOL active;
					int debugregspot;
					UINT64 address;
					DWORD breakType;
					DWORD breakLength;
				} *inp=Irp->AssociatedIrp.SystemBuffer;
				
				DbgPrint("sizeof(struct input)=%d\n",sizeof(struct input));
				//DbgPrint("address=%llx breakType=%d breakLength=%d\n",inp->address, inp->breakType,inp->breakLength);

				if (inp->active)
				{
					DbgPrint("activating breapoint %d\n", inp->debugregspot);
					ntStatus=debugger_setGDBreakpoint(inp->debugregspot, (UINT_PTR)inp->address, (BreakType)inp->breakType, (BreakLength)inp->breakLength);
				}
				else
				{					
					DbgPrint("Deactivating breakpoint :%d\n", inp->debugregspot);
					ntStatus=debugger_unsetGDBreakpoint(inp->debugregspot);
				}
				break;
			}

		case IOCTL_CE_TOUCHDEBUGREGISTER: //used after setting a global debug breakpoint
			{
				debugger_touchDebugRegister(0);
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_SETSTORELBR:
			{
				BOOL newstate=*(PBOOL)Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("Calling debugger_setStoreLBR(%d)\n", newstate);
				debugger_setStoreLBR(newstate);
				ntStatus=STATUS_SUCCESS;
				break;
			}	


		case IOCTL_CE_EXECUTE_CODE:
			{		
				typedef NTSTATUS (*PARAMETERLESSFUNCTION)(UINT64 parameters);
				PARAMETERLESSFUNCTION functiontocall;

				struct input
				{
					UINT64	functionaddress; //function address to call
					UINT64	parameters;
				} *inp=Irp->AssociatedIrp.SystemBuffer;
				DbgPrint("IOCTL_CE_EXECUTE_CODE\n");

				functiontocall=(PARAMETERLESSFUNCTION)(UINT_PTR)(inp->functionaddress);

				__try
				{
					ntStatus=functiontocall(inp->parameters);
					DbgPrint("Still alive\n");
					ntStatus=STATUS_SUCCESS;
				}
				__except(1)
				{
					DbgPrint("Exception occured\n");
					ntStatus=STATUS_UNSUCCESSFUL;
				}

				break;
			}


		case IOCTL_CE_GETVERSION:
			{
				DbgPrint("IOCTL_CE_GETVERSION. Version=%d\n",dbkversion);
				*(PULONG)Irp->AssociatedIrp.SystemBuffer=dbkversion;	
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_READMSR:
			{
				DWORD msr=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;

				//DbgPrint("IOCTL_CE_READMSR: msr=%x\n", msr);

				__try
				{
					*(PUINT64)Irp->AssociatedIrp.SystemBuffer=__readmsr(msr);
					//DbgPrint("Output: %llx\n",*(PUINT64)Irp->AssociatedIrp.SystemBuffer); 

					ntStatus=STATUS_SUCCESS;
				}
				__except(1)
				{
					ntStatus=STATUS_UNSUCCESSFUL;
				}

				break;
			}	

		case IOCTL_CE_WRITEMSR:
			{
				struct input
				{
					UINT64 msr;			
					UINT64 value;
				} *inp=Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_WRITEMSR:\n");
				DbgPrint("msr=%llx\n", inp->msr);
				DbgPrint("value=%llx\n", inp->value);

				__try
				{
					__writemsr(inp->msr, inp->value );					
					ntStatus=STATUS_SUCCESS;
				}
				__except(1)
				{
					DbgPrint("Error while writing value\n");
					ntStatus=STATUS_UNSUCCESSFUL;
				}
				break;
			}

		case IOCTL_CE_ULTIMAP2:
			{
				struct input
				{
					UINT32 PID;	
					UINT32 Size;
					UINT32 RangeCount;
					UINT32 NoPMI;
					UINT32 UserMode;
					UINT32 KernelMode;
					URANGE Ranges[8];
					WCHAR OutputPath[200];
				} *inp = Irp->AssociatedIrp.SystemBuffer;
				int i;

				DbgPrint("IOCTL_CE_ULTIMAP2");
				for (i = 0; i < (int)(inp->RangeCount); i++)
					DbgPrint("%d=%p -> %p", i, (PVOID)(UINT_PTR)inp->Ranges[i].StartAddress, (PVOID)(UINT_PTR)inp->Ranges[i].EndAddress);

				SetupUltimap2(inp->PID, inp->Size, inp->OutputPath, inp->RangeCount, inp->Ranges, inp->NoPMI, inp->UserMode, inp->KernelMode);

				ntStatus = STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_ULTIMAP2_WAITFORDATA:
		{

			ULONG timeout = *(ULONG *)Irp->AssociatedIrp.SystemBuffer;
			PULTIMAP2DATAEVENT output = Irp->AssociatedIrp.SystemBuffer;
			output->Address = 0;

			ntStatus = ultimap2_waitForData(timeout, output);

			break;
		}

		case IOCTL_CE_ULTIMAP2_LOCKFILE:
		{
			int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
			ultimap2_LockFile(cpunr);

			ntStatus = STATUS_SUCCESS;
			break;
		}

		case IOCTL_CE_ULTIMAP2_RELEASEFILE:
		{
			int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
			ultimap2_ReleaseFile(cpunr);

			ntStatus = STATUS_SUCCESS;				
			break;
		}

		case IOCTL_CE_ULTIMAP2_GETTRACESIZE:
		{
			*(UINT64*)Irp->AssociatedIrp.SystemBuffer = ultimap2_GetTraceFileSize();
			ntStatus = STATUS_SUCCESS;
			break;
		}

		case IOCTL_CE_ULTIMAP2_RESETTRACESIZE:
		{
			ultimap2_ResetTraceFileSize();
			ntStatus = STATUS_SUCCESS;
			break;
		}


		case IOCTL_CE_ULTIMAP2_CONTINUE:
		{
			int cpunr=*(int*)Irp->AssociatedIrp.SystemBuffer;
			ntStatus = ultimap2_continue(cpunr);

			break;
		}

		case IOCTL_CE_ULTIMAP2_FLUSH:
		{			
			ntStatus = ultimap2_flushBuffers();
			break;
		}

		case IOCTL_CE_ULTIMAP2_PAUSE:
		{
			ntStatus = ultimap2_pause();
			break;
		}

		case IOCTL_CE_ULTIMAP2_RESUME:
		{
			ntStatus = ultimap2_resume();
			break;
		}

		case IOCTL_CE_DISABLEULTIMAP2:
			{
				DisableUltimap2();
				break;
			}

		case IOCTL_CE_ULTIMAP:
			{
				#pragma pack(1)
				struct input
				{
					UINT64 targetCR3;
					UINT64 dbgctl;			
					UINT64 dsareasize;
					BOOL savetofile;
					int HandlerCount;
					WCHAR filename[200];				
				} *inp=Irp->AssociatedIrp.SystemBuffer;
				#pragma pack()

				
				DbgPrint("IOCTL_CE_ULTIMAP:\n");
				DbgPrint("ultimap(%I64x, %I64x, %d):\n", (UINT64)inp->targetCR3, (UINT64)inp->dbgctl, inp->dsareasize);

				if (inp->savetofile)
					DbgPrint("filename=%S\n", &inp->filename[0]);

				ntStatus=ultimap(inp->targetCR3, inp->dbgctl, (int)inp->dsareasize, inp->savetofile, &inp->filename[0], inp->HandlerCount);
				
			

				break;
			}

		case IOCTL_CE_ULTIMAP_DISABLE:
			{
				ultimap_disable();
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_ULTIMAP_WAITFORDATA:
			{
				
				ULONG timeout=*(ULONG *)Irp->AssociatedIrp.SystemBuffer;				
				PULTIMAPDATAEVENT output=Irp->AssociatedIrp.SystemBuffer;
				ntStatus=ultimap_waitForData(timeout, output);

				break;
			}

		case IOCTL_CE_ULTIMAP_CONTINUE:
			{
				PULTIMAPDATAEVENT input=Irp->AssociatedIrp.SystemBuffer;				
				ntStatus=ultimap_continue(input);

				break;
			}

		case IOCTL_CE_ULTIMAP_FLUSH:
			{
				ultimap_flushBuffers();
				ntStatus=STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_ULTIMAP_PAUSE:
		{			
			ultimap_pause();
			ntStatus = STATUS_SUCCESS;
			break;
		}

		case IOCTL_CE_ULTIMAP_RESUME:
		{			
			ultimap_resume();
			ntStatus = STATUS_SUCCESS;
			break;
		}

			/*
		case IOCTL_CE_GETCPUIDS:
			{
				CPULISTFILLSTRUCT x;	

				forEachCpuPassive(GetCPUIDS_all,&x);
			}*/

		case IOCTL_CE_STARTACCESMONITOR:
			{
				//this is used instead of writeProcessMemory for speed reasons (the reading out is still done with readProcessMemory because of easier memory management)
				struct input
				{
					UINT64 ProcessID;
				} *inp;
				PEPROCESS selectedprocess;

				PVOID BaseAddress;
				SIZE_T RegionSize;

				inp=Irp->AssociatedIrp.SystemBuffer;
				DbgPrint("IOCTL_CE_STARTACCESMONITOR(%d)\n", inp->ProcessID);


				ntStatus = STATUS_UNSUCCESSFUL;

				if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
				{
					ntStatus = markAllPagesAsNeverAccessed(selectedprocess);
					ObDereferenceObject(selectedprocess);
				}

				break;
			}

		case IOCTL_CE_ENUMACCESSEDMEMORY:
			{
				struct input
				{
					UINT64 ProcessID;
				} *inp;
				PEPROCESS selectedprocess;

				PVOID BaseAddress;
				SIZE_T RegionSize;

				inp = Irp->AssociatedIrp.SystemBuffer;
				DbgPrint("IOCTL_CE_ENUMACCESSEDMEMORY(%d)\n", inp->ProcessID);


				ntStatus = STATUS_UNSUCCESSFUL;

				if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
				{
					*(int *)Irp->AssociatedIrp.SystemBuffer = enumAllAccessedPages(selectedprocess);
					ObDereferenceObject(selectedprocess);
				}

				ntStatus = STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_GETACCESSEDMEMORYLIST:
			{
				int ListSizeInBytes = *(int *)Irp->AssociatedIrp.SystemBuffer;
				PPRANGE List = (PPRANGE)Irp->AssociatedIrp.SystemBuffer;

				DbgPrint("IOCTL_CE_GETACCESSEDMEMORYLIST\n"); 

				getAccessedPageList(List, ListSizeInBytes);

				DbgPrint("return from IOCTL_CE_GETACCESSEDMEMORYLIST\n");
				ntStatus = STATUS_SUCCESS;
				break;
			}

		case IOCTL_CE_INITIALIZE:
			{
				//find the KeServiceDescriptorTableShadow 
				struct input
				{
					UINT64 AddressOfWin32K;
					UINT64 SizeOfWin32K;
					UINT64 NtUserBuildHwndList_callnumber;
					UINT64 NtUserQueryWindow_callnumber;
					UINT64 NtUserFindWindowEx_callnumber;
					UINT64 NtUserGetForegroundWindow_callnumber;
					UINT64 ActiveLinkOffset;
					UINT64 ProcessNameOffset;
					UINT64 DebugportOffset;	
					UINT64 ProcessEvent;
					UINT64 ThreadEvent;
  				} *pinp;

				DbgPrint("IOCTL_CE_INITIALIZE\n");
				pinp=Irp->AssociatedIrp.SystemBuffer;
				ntStatus=STATUS_SUCCESS;

				//referencing event handles to objects

				ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ProcessEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ProcessEvent, NULL); 
				ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ThreadEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ThreadEvent, NULL); 
				
				*(UINT_PTR*)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)0;
				break;
			}
			

		case IOCTL_CE_VMXCONFIG:
			{
#pragma pack(1)
				struct input
				{
					ULONG Virtualization_Enabled;
					QWORD Password1;
					ULONG Password2;
					QWORD Password3;
  				} *pinp;
#pragma pack()
				

				DbgPrint("IOCTL_CE_VMXCONFIG called\n");	
				ntStatus=STATUS_SUCCESS;

				pinp=Irp->AssociatedIrp.SystemBuffer;

				if (pinp->Virtualization_Enabled)
				{
					vmx_password1=pinp->Password1;
					vmx_password2=pinp->Password2;
					vmx_password3=pinp->Password3;

					DbgPrint("new passwords are: %p-%x-%p\n", (void*)vmx_password1, vmx_password2, (void*)vmx_password3);

					__try
					{
						vmx_version=vmx_getversion();
						DbgPrint("Still here, so vmx is loaded. vmx_version=%x\n",vmx_version);	
						vmxusable = 1;
					}
					__except(1)
					{
						DbgPrint("Exception happened. This means no vmx installed, or one of the passwords is wrong\n");
						ntStatus = STATUS_UNSUCCESSFUL;

						vmxusable = 0;
					};
				}
				else
				{
					DbgPrint("Virtualization_Enabled=0\n");
					vmxusable=0;
				}
				
				break;
			}


		case IOCTL_CE_ENABLE_DRM:
			{
#if (NTDDI_VERSION >= NTDDI_VISTA)				
				struct
				{
					QWORD PreferedAltitude;
					QWORD ProtectedProcess;									
				} *inp = Irp->AssociatedIrp.SystemBuffer;

	
				
				DbgPrint("inp->PreferedAltitude=%p", inp->PreferedAltitude);
				DbgPrint("inp->PreferedAltitude=%p", inp->ProtectedProcess);

				
				if (DRMProcess)
				{
					//check if this process has been terminated
					LARGE_INTEGER timeout;

					timeout.QuadPart = -500000;
					ntStatus=KeWaitForSingleObject(DRMProcess, UserRequest, UserMode, FALSE, &timeout);

					if (ntStatus != STATUS_SUCCESS)
						break;					
				}

				DRMProcess = PsGetCurrentProcess();

				if (inp->ProtectedProcess)
				{
					if (DRMProcess != (PEPROCESS)((UINT_PTR)inp->ProtectedProcess))						
						DRMProcess2 = (PEPROCESS)((UINT_PTR)inp->ProtectedProcess);
				}
					
				DbgPrint("DRMProcess=%p", DRMProcess);
				DbgPrint("DRMProcess2=%p", DRMProcess2);

				if (DRMHandle == NULL)
				{
					WCHAR wcAltitude[10];
					UNICODE_STRING usAltitude;
					OB_CALLBACK_REGISTRATION r;
					LARGE_INTEGER tc;
					OB_OPERATION_REGISTRATION obr[2];
					int RandomVal = (int)(inp->PreferedAltitude);
					int trycount = 0;

					if (RandomVal == 0)
					{
						tc.QuadPart = 0;
						KeQueryTickCount(&tc);
						RandomVal = 1000 + (tc.QuadPart % 50000);
					}

					DbgPrint("Activating CE's super advanced DRM"); //yeah right....

					DbgPrint("RandomVal=%d", RandomVal);
					RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);

					DbgPrint("wcAltitude=%S", wcAltitude);
					RtlInitUnicodeString(&usAltitude, wcAltitude);

					r.Version = OB_FLT_REGISTRATION_VERSION;
					r.Altitude = usAltitude;
					r.RegistrationContext = NULL;


					obr[0].ObjectType = PsProcessType;
					obr[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
					obr[0].PreOperation = ProcessPreCallback;
					obr[0].PostOperation = ProcessPostCallback;

					obr[1].ObjectType = PsThreadType;
					obr[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
					obr[1].PreOperation = ThreadPreCallback;
					obr[1].PostOperation = ThreadPostCallback;

					r.OperationRegistration = obr;
					r.OperationRegistrationCount = 2;

					ntStatus = ObRegisterCallbacks(&r, &DRMHandle);

					while ((ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) && (trycount<10))
					{
						RandomVal++;
						RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);
						RtlInitUnicodeString(&usAltitude, wcAltitude);
						r.Altitude = usAltitude;

						trycount++;

						ntStatus = ObRegisterCallbacks(&r, &DRMHandle);
					}

					DbgPrint("ntStatus=%X", ntStatus);
				}
				else
					ntStatus = STATUS_SUCCESS;
#else
				ntStatus = STATUS_NOT_IMPLEMENTED;
#endif				
				break;
			}

		case IOCTL_CE_GET_PEB:
		{
			KAPC_STATE oldstate;
			PEPROCESS ep = *(PEPROCESS *)Irp->AssociatedIrp.SystemBuffer;


			//DbgPrint("IOCTL_CE_GET_PEB");
			KeStackAttachProcess((PKPROCESS)ep, &oldstate);
			__try
			{
				ULONG r;
				PROCESS_BASIC_INFORMATION pbi;
				//DbgPrint("Calling ZwQueryInformationProcess");
				ntStatus = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &r);
				if (ntStatus==STATUS_SUCCESS)
				{
					//DbgPrint("pbi.UniqueProcessId=%x\n", (int)pbi.UniqueProcessId);
					//DbgPrint("pbi.PebBaseAddress=%p\n", (PVOID)pbi.PebBaseAddress);					
					*(QWORD *)Irp->AssociatedIrp.SystemBuffer = (QWORD)(pbi.PebBaseAddress);
				}
				else
					DbgPrint("ZwQueryInformationProcess failed");
			}
			__finally
			{
				KeUnstackDetachProcess(&oldstate);
			}	

			
			break;
		}

		case IOCTL_CE_QUERYINFORMATIONPROCESS:
		{
			struct
			{	
				QWORD processid;
				QWORD ProcessInformationAddress;
				QWORD ProcessInformationClass;
				QWORD ProcessInformationLength;				
			}  *inp = Irp->AssociatedIrp.SystemBuffer;

			struct
			{
				QWORD result;
				QWORD returnLength;
				char data;
			} *outp = Irp->AssociatedIrp.SystemBuffer;

			PEPROCESS selectedprocess;
			DbgPrint("IOCTL_CE_QUERYINFORMATIONPROCESS");

			if (inp->processid == 0)
			{
				DbgPrint("Still works\n");
				ntStatus = STATUS_SUCCESS;
				break;
			}
			__try
			{
				
				if (PsLookupProcessByProcessId((HANDLE)(UINT_PTR)inp->processid, &selectedprocess) == STATUS_SUCCESS)
				{
					KAPC_STATE oldstate;
					KeStackAttachProcess((PKPROCESS)selectedprocess, &oldstate);
					__try
					{
						ULONG returnLength;

						if (inp->ProcessInformationAddress == 0)
						{
							DbgPrint("NULL ProcessInformationAddress");
							outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, NULL, (ULONG)inp->ProcessInformationLength, &returnLength);
						}
						else
							outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, &(outp->data), (ULONG)inp->ProcessInformationLength, &returnLength);

						DbgPrint("outp->result=%x", outp->result);

						outp->returnLength = returnLength;
						DbgPrint("outp->returnLength=%x", outp->returnLength);

						ntStatus = STATUS_SUCCESS;
					}
					__finally
					{
						KeUnstackDetachProcess(&oldstate);
					}

					ObDereferenceObject(selectedprocess);
				}
				else
				{
					DbgPrint("Failed to find pid %x", inp->processid);
					ntStatus = STATUS_EXPIRED_HANDLE;
				}
			}
			__except (1)
			{
				DbgPrint("Exception");
				ntStatus = STATUS_EXPIRED_HANDLE;
			}
			break;
		}

		case IOCTL_CE_NTPROTECTVIRTUALMEMORY:
		{

			
			break;
		}

		case IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM:
		{
			PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
			PMDL mdl;
			QWORD pagecount = *(QWORD*)Irp->AssociatedIrp.SystemBuffer;
			PFN_NUMBER *pfnlist;
			DbgPrint("IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM(%d)\n", pagecount);

			if (!vmxusable)
			{
				DbgPrint("This only works when DBVM is present\n");
				ntStatus = STATUS_INVALID_DEVICE_STATE;
				break;
			}

			LowAddress.QuadPart = 0;
			HighAddress.QuadPart = 0xffffffffffffffffI64;
			SkipBytes.QuadPart = 0;
			mdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, (SIZE_T)pagecount * 4096, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED); //do not free this, EVER
			if (mdl)
			{
				int i;
				PDBVMOffloadMemInfo mi;

				pagecount = MmGetMdlByteCount(mdl) / 4096;
				DbgPrint("Allocated %d pages\n", pagecount);

				pfnlist = MmGetMdlPfnArray(mdl);

				if (pfnlist)
				{
					//convert the pfnlist to a list dbvm understands, and go in blocks of 32
					mi = ExAllocatePool(PagedPool, sizeof(DBVMOffloadMemInfo));
					if (mi)
					{
						mi->List = ExAllocatePool(PagedPool, sizeof(UINT64) * 32);
						if (mi->List)
						{
							mi->Count = 0;
							for (i = 0; i < pagecount; i++)
							{
								mi->List[mi->Count] = pfnlist[i] << 12;
								mi->Count++;

								if (mi->Count == 32)
								{
									int j;
									int r = vmx_add_memory(mi->List, mi->Count);

								
									DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);

									for (j = 0; j < mi->Count; j++)
									{
										DbgPrint("%d : %p\n", j, (void*)((UINT_PTR)mi->List[j]));
									}


									mi->Count = 0;
								}
							}

							if (mi->Count)
							{
								int r = vmx_add_memory(mi->List, mi->Count);
								DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);
							}
							ExFreePool(mi->List);
						}
						else
							DbgPrint("Failure allocating mi->List");
						ExFreePool(mi);
					}
					else
						DbgPrint("Failure allocting mi");

				}
				else
					DbgPrint("Failure getting pfn list");
				ExFreePool(mdl); //only free the mdl, the rest belongs to dbvm now

				ntStatus = STATUS_SUCCESS;
			}
			else
			{
				DbgPrint("Failure allocating MDL");
				ntStatus = STATUS_MEMORY_NOT_ALLOCATED;
			}


			break;
		}

        default:
			DbgPrint("Unhandled IO request: %x\n", IoControlCode);			
            break;
    }

	
    Irp->IoStatus.Status = ntStatus;
    
    // Set # of bytes to copy back to user-mode...
	if (irpStack) //only NULL when loaded by dbvm
	{
		if (ntStatus == STATUS_SUCCESS)
			Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
		else
			Irp->IoStatus.Information = 0;

		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}

    
    return ntStatus;
}


================================================
FILE: src/IOPLDispatcher.h
================================================
#ifndef IOPLDISPACTCHER_H
#define IOPLDISPACTCHER_H

#include "DBKfunc.h"

#define IOCTL_UNKNOWN_BASE					FILE_DEVICE_UNKNOWN

#define IOCTL_CE_READMEMORY						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEMEMORY					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENPROCESS    				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_QUERY_VIRTUAL_MEMORY			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_TEST							CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPEPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0805, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_READPHYSICALMEMORY				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEPHYSICALMEMORY			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0807, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPHYSICALADDRESS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0808, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_PROTECTME						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0809, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR3 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETCR3 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETSDT 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_INITIALIZE     		    	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DONTPROTECTME					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETIDT 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_HOOKINTS 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0810, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DEBUGPROCESS 					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0811, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_RETRIEVEDEBUGDATA				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0812, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STARTPROCESSWATCH				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0813, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCESSEVENTS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0814, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETTHREADEVENTS				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0815, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETVERSION						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0816, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR4 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0817, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENTHREAD	    				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0818, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_MAKEWRITABLE					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0819, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//obsolete: #define IOCTL_CE_DEBUGPROCESS_CHANGEREG			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STOPDEBUGGING					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//obsolete: #define	IOCTL_CE_STOP_DEBUGPROCESS_CHANGEREG	CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define	IOCTL_CE_USEALTERNATEMETHOD				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define	IOCTL_CE_ISUSINGALTERNATEMETHOD			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define	IOCTL_CE_ALLOCATEMEM					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_CREATEAPC						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0820, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPETHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0821, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_SUSPENDTHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0822, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMETHREAD					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0823, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SUSPENDPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0824, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMEPROCESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0825, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ALLOCATEMEM_NONPAGED			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0826, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCADDRESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0827, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_SETSDTADDRESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0828, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETSDTADDRESS					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0829, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_GETGDT 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETCR4 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETTR 							CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_VMXCONFIG						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR0 						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_USERDEFINEDINTERRUPTHOOK		CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETGLOBALDEBUGSTATE			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0830, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_CONTINUEDEBUGEVENT				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0831, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WAITFORDEBUGEVENT				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0832, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETDEBUGGERSTATE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0833, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETDEBUGGERSTATE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0834, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GD_SETBREAKPOINT				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0835, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_TOUCHDEBUGREGISTER				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0836, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_LAUNCHDBVM						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNHOOKALLINTERRUPTS			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_EXECUTE_CODE					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCESSNAMEADDRESS			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETKERNELSTEPABILITY			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_READMSR						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEMSR						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0840, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_SETSTORELBR					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0841, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0842, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_DISABLE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0843, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_WAITFORDATA			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0844, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_CONTINUE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0845, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_FLUSH					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0846, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_GETMEMORYRANGES				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0847, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_STARTACCESMONITOR				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0848, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ENUMACCESSEDMEMORY 			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0849, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETACCESSEDMEMORYLIST			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITESIGNOREWP					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_FREE_NONPAGED					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_MAP_MEMORY						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNMAP_MEMORY					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ULTIMAP2						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DISABLEULTIMAP2				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0850, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_WAITFORDATA			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0851, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_CONTINUE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0852, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_FLUSH					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0853, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_PAUSE					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RESUME				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ULTIMAP2_LOCKFILE				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0856, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RELEASEFILE			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0857, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ULTIMAP_PAUSE  				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0858, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_RESUME  				CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0859, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ULTIMAP2_GETTRACESIZE			CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RESETTRACESIZE		CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_ENABLE_DRM						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GET_PEB						CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_QUERYINFORMATIONPROCESS		CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_NTPROTECTVIRTUALMEMORY 		CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

#define IOCTL_CE_LOCK_MEMORY 					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0860, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNLOCK_MEMORY 					CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0861, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM		CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)


extern PVOID DRMHandle;

#define SYSTEMSERVICE(_function)		KeServiceDescriptorTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]
#define SYSTEMSERVICELINK(_function)	KeServiceDescriptorTable->ServiceTable[*((PUCHAR)(*(PULONG)*((PULONG)((PUCHAR)_function+2)))+1)]


NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned);



#endif

================================================
FILE: src/amd64/dbkfunca.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument

;I should probably start converting to inrinsics

_TEXT SEGMENT 'CODE'
PUBLIC getCS
getCS:
	mov ax,cs
	ret

PUBLIC getSS
getSS:
	mov ax,ss
	ret
	
PUBLIC getDS
getDS:
	mov ax,ds
	ret
	
PUBLIC getES
getES:
	mov ax,es
	ret	
	
PUBLIC getFS
getFS:
	mov ax,fs
	ret
	
PUBLIC getGS
getGS:
	mov ax,gs
	ret	
	
PUBLIC GetTR
GetTR:
	STR AX
	ret	
	
PUBLIC GetLDT
GetLDT:
	SLDT ax
	ret
	
PUBLIC GetGDT
GetGDT:
	SGDT [rcx]
	ret
	
PUBLIC _fxsave
_fxsave:
    fxsave [rcx]
    ret
	
PUBLIC getRSP
getRSP:
	mov rax,rsp
	add rax,8 ;undo the call push
	ret	
	
PUBLIC getRBP
getRBP:
    push rbp
    pop rax	
	ret	
	
PUBLIC getRAX
getRAX:	
	ret							
	
PUBLIC getRBX
getRBX:
	mov rax,rbx
	ret	
	
PUBLIC getRCX
getRCX:
	mov rax,rcx
	ret	
	
PUBLIC getRDX
getRDX:
	mov rax,rdx
	ret		
	
PUBLIC getRSI
getRSI:
	mov rax,rsi
	ret		
	
PUBLIC getRDI
getRDI:
	mov rax,rdi
	ret		
	
PUBLIC getR8
getR8:
	mov rax,r8
	ret		
	
PUBLIC getR9
getR9:
	mov rax,r9
	ret		
	
PUBLIC getR10
getR10:
	mov rax,r10
	ret		
	
PUBLIC getR11
getR11:
	mov rax,r11
	ret		
	
PUBLIC getR12
getR12:
	mov rax,r12
	ret		
	
PUBLIC getR13
getR13:
	mov rax,r13
	ret		
	
PUBLIC getR14
getR14:
	mov rax,r14
	ret		
	
PUBLIC getR15
getR15:
	mov rax,r15
	ret				
	
PUBLIC getAccessRights										
getAccessRights:
  xor rax,rax
  lar rax,rcx
  jnz getAccessRights_invalid
  shr rax,8
  and rax,0f0ffh
  ret
  getAccessRights_invalid:
  mov rax,010000h
  ret


PUBLIC getSegmentLimit										
getSegmentLimit:
  xor rax,rax
  lsl rax,rcx
  ret

_TEXT   ENDS
        END



================================================
FILE: src/amd64/debuggera.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument

CALLBACK        struct
A		 		qword ?
S				qword ?
CALLBACK        ends


ASMENTRY_STACK	struct ;keep this 16 byte aligned
	Scratchspace	qword ?
	Scratchspace2	qword ? 
	Scratchspace3	qword ?
	Scratchspace4	qword ? 	
	Originalmxcsr	qword ?	
	OriginalRAX		qword ?  ;0
	OriginalRBX		qword ?  ;1
	OriginalRCX		qword ?  ;2
	OriginalRDX		qword ?  ;3
	OriginalRSI		qword ?  ;4
	OriginalRDI		qword ?  ;5
	OriginalRBP		qword ?  ;6
	OriginalRSP		qword ?  ;7 not really 'original'
	OriginalR8		qword ?  ;8
	OriginalR9		qword ?  ;9
	OriginalR10		qword ?  ;10
	OriginalR11		qword ?  ;11
	OriginalR12		qword ?  ;12
	OriginalR13		qword ?  ;13
	OriginalR14		qword ?  ;14
	OriginalR15		qword ?  ;15
	OriginalES		qword ?  ;16
	OriginalDS		qword ?	 ;17
	OriginalSS		qword ?	 ;18
	fxsavespace     db 512 dup(?)  ;fpu state

	;errorcode/returnaddress   ;19
	;4096 bytes 
	;eip     ;20
	;cs      ;21
	;eflags
	;esp
	;ss
	
ASMENTRY_STACK	ends


_TEXT SEGMENT 'CODE'

EXTERN interrupt1_centry : proc
EXTERN Int1JumpBackLocation : CALLBACK

PUBLIC interrupt1_asmentry
interrupt1_asmentry:
		;save stack position
		push [Int1JumpBackLocation.A] ;push an errorcode on the stack so the stackindex enum type can stay the same relative to interrupts that do have an errorcode (int 14).  Also helps with variable interrupt handlers
		
		sub rsp,4096  ;functions like setThreadContext adjust the stackframe entry directly. I can't have that messing up my own stack

		cld			

		;stack is aligned at this point
		sub rsp,SIZEOF ASMENTRY_STACK
		
		
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp
		lea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
		
		
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax	
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15

		fxsave (ASMENTRY_STACK PTR [rsp]).fxsavespace

	
		
		
		
		mov ax,ds
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax
		
		mov ax,es
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax
		
		mov ax,ss
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax		
		

		mov ax,2bh 
		mov ds,ax
		mov es,ax
		
		mov ax,18h
		mov ss,ax
		
		
		; rbp= pointer to OriginalRAX
		
		cmp qword ptr [rbp+8*21+512+4096],010h ;check if origin is in kernelmode (check ss)
		je skipswap1 ;if so, skip the swapgs
		
		swapgs ;swap gs with the kernel version
		
skipswap1:
		
		
		
		stmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
		
		mov (ASMENTRY_STACK PTR [rsp]).scratchspace2,1f80h		
		ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace2

		
		mov rcx,rbp
		call interrupt1_centry
		
		ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
		
		cmp qword ptr [rbp+8*21+512+4096],10h ;was it a kernelmode interrupt ?
		je skipswap2 ;if so, skip the swapgs part
				
		swapgs ;swap back
skipswap2:

		cmp al,1


		;restore state
		fxrstor (ASMENTRY_STACK PTR [rsp]).fxsavespace

		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS
		mov ds,ax
		
		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES
		mov es,ax
		
		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS
		mov ss,ax
		
		
		mov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
		mov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX
		mov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX
		mov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX
		mov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI
		mov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI
		mov r8, (ASMENTRY_STACK PTR [rsp]).OriginalR8
		mov r9, (ASMENTRY_STACK PTR [rsp]).OriginalR9
		mov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10
		mov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11
		mov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12
		mov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13
		mov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14
		mov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15

	
		je skip_original_int1
		
		;stack unwind
		mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
		add rsp,SIZEOF ASMENTRY_STACK  
		add rsp,4096

		;at this point [rsp] holds the original int1 handler
		ret ; used to be add rsp,8 ;+8 for the push 0

		;todo: do a jmp [Int1JumpBackLocationCPUNR] and have 256 Int1JumpBackLocationCPUNR's and each cpu goes to it's own interrupt1_asmentry[cpunr]
		
		;jmp [Int1JumpBackLocation.A] ;<-works fine	


skip_original_int1:
		;stack unwind
		mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
		add rsp,SIZEOF ASMENTRY_STACK 	
		add rsp,4096
		add rsp,8  ;+8 for the push	
		
		iretq

	
_TEXT   ENDS
        END	

================================================
FILE: src/amd64/noexceptionsa.asm
================================================
_TEXT SEGMENT 'CODE'

PUBLIC NoException14
NoException14:

;Security cookies sucks, so getjmp/longjmp are not usable
;So, just falling back to an exceptionless Copy command instead
;or disassemble the instruction RIP points at

;rsp=errorcode
;rsp+8=rip
;rsp+10=cs     ;20
;rsp+18=eflags
;rsp+20=rsp
;rsp+28=ss

add rsp,8 ;skip the errorcode
push rax ;push rax -state as above again
mov rax,ExceptionlessCopy_Exception
mov [rsp+8],rax
pop rax
iretq ;go to the designated return address


PUBLIC ExceptionlessCopy_Internal
;rcx=destination
;rdx=source
;r8=size in bytes

ExceptionlessCopy_Internal:
push rbp
mov rbp,rsp

;[rbp] = old rbp value
;[rbp+8] = return address
;[rbp+10h] - [rbp+30h] = scratchspace

mov [rbp+10h],rsi
mov [rbp+18h],rdi

mov rsi,rdx
mov rdi,rcx
mov rcx,r8

rep movsb  ;todo: split this up into movsq, movsd, movsw, movsd, or some of those other string routines

;on exception just exit

ExceptionlessCopy_Exception:
mov rsi,[rbp+10h]
mov rdi,[rbp+18h]
sub r8,rcx ;decrease the number of bytes left from the total amount of bytes to get the total bytes written
mov rax,r8 

pop rbp
ret



_TEXT   ENDS
        END	

================================================
FILE: src/amd64/ultimapa.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument

CALLBACK        struct
A		 		qword ?
S				qword ?
CALLBACK        ends


ASMENTRY_STACK	struct ;keep this 16 byte aligned
	Scratchspace	qword ?   ;0
	Scratchspace2	qword ?   ;8
	Scratchspace3	qword ?   ;0
	Scratchspace4	qword ?   ;8
	Originalmxcsr	qword ?	
	OriginalRAX		qword ?
	OriginalRBX		qword ?
	OriginalRCX		qword ?
	OriginalRDX		qword ?
	OriginalRSI		qword ?
	OriginalRDI		qword ?
	OriginalRBP		qword ?
	OriginalRSP		qword ? ;not really 'original'
	OriginalR8		qword ?
	OriginalR9		qword ?
	OriginalR10		qword ?
	OriginalR11		qword ?
	OriginalR12		qword ?
	OriginalR13		qword ?
	OriginalR14		qword ?
	OriginalR15		qword ?
	OriginalES		qword ?
	OriginalDS		qword ?		
	OriginalSS		qword ?	
	
ASMENTRY_STACK	ends


_TEXT SEGMENT 'CODE'

EXTERN perfmon_interrupt_centry : proc
EXTERN perfmonJumpBackLocation : CALLBACK

PUBLIC perfmon_interrupt



perfmon_interrupt:
		;save stack position
		
		cld			
		push 0 ;push an errorcode on the stack so the stackindex enum type can stay the same relative to interrupts that do have an errorcode (int 14)
		
		;stack is aligned at this point
		sub rsp, 4096
		
		sub rsp,SIZEOF ASMENTRY_STACK
		
		
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp
		lea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX ;make rbp point to the start of the structure
		
		
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax	
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi
		mov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14
		mov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15
	
		
		mov ax,ds
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax
		
		mov ax,es
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax
		
		mov ax,ss
		mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax		
		

		mov ax,2bh 
		mov ds,ax
		mov es,ax
		
		mov ax,18h
		mov ss,ax
		
		
		cmp qword ptr [rbp+8*21+4096],010h ;check if origin is in kernelmode (check ss)
		je skipswap1 ;if so, skip the swapgs
		
		swapgs ;swap gs with the kernel version (not to self fix when called from inside kernel)
		
skipswap1:
		
		
		
		stmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
		
		mov (ASMENTRY_STACK PTR [rsp]).scratchspace,1f80h		
		ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace


		
		;mov rcx,rbp
		call perfmon_interrupt_centry
		
		ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
		
		cmp qword ptr [rbp+8*21+4096],10h ;was it a kernelmode interrupt ?
		je skipswap2 ;if so, skip the swapgs part
				
		swapgs ;swap back
skipswap2:

		cmp al,1


		;restore state
		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS
		mov ds,ax
		
		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES
		mov es,ax
		
		mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS
		mov ss,ax
		
		
		mov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
		mov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX
		mov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX
		mov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX
		mov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI
		mov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI
		mov r8,(ASMENTRY_STACK PTR [rsp]).OriginalR8
		mov r9,(ASMENTRY_STACK PTR [rsp]).OriginalR9
		mov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10
		mov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11
		mov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12
		mov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13
		mov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14
		mov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15

	
		je skip_original_perfmon
		jmp skip_original_perfmon
		
		;stack unwind
		mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
		add rsp,SIZEOF ASMENTRY_STACK  ;+8 for the push 0
		add rsp,8
		
		add rsp,4096
		
		
		jmp [perfmonJumpBackLocation.A] ;<-works fine	


skip_original_perfmon:
		;stack unwind
		mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
		add rsp,SIZEOF ASMENTRY_STACK  ;+8 for the push 0	
		
		add rsp,4096
		add rsp,8

;jump to when the stack has been completly restored to what it was at interrupt time
	    ;push rax
		;push rbx
				
		;unmask the perfmon interrupt
		;mov rax,0fffffffffffe0330h
		;mov rbx,[rax]
		;and rbx,0ffh
		;mov [rax],rbx 
		
		;End of interrupt
	
		;mov rax,0fffffffffffe00b0h
		;xor rbx,rbx
		;mov [rax],rbx ;set EOI to 0		
				
		;pop rbx
		;pop rax
		
		iretq
  
  		

	
_TEXT   ENDS
        END	

================================================
FILE: src/amd64/vmxhelpera.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument


;vmcall:  rdx = password1  info(rax)->password(@offset 4)=password 2

;vmcall(info)

extern vmx_password1 : QWORD
extern vmx_password3 : QWORD

_TEXT SEGMENT 'CODE'
PUBLIC dovmcall_intel
dovmcall_intel:
	mov rax,rcx
	mov rdx,vmx_password1
	mov rcx,vmx_password3
	vmcall
	ret
	
PUBLIC dovmcall_amd
dovmcall_amd:
	mov rax,rcx
	mov rdx,vmx_password1
	mov rcx,vmx_password3
	vmmcall
	ret	
	
_TEXT   ENDS
        END	

================================================
FILE: src/amd64/vmxoffloada.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument

GDTDesc	STRUCT
Limit	WORD	?
Base	QWORD	?
GDTDesc	ENDS

S_ORIGINALSTATE STRUCT
_cpucount		QWORD ?
_originalEFER   QWORD ?
_originalLME	QWORD ?
_idtbase		QWORD ?
_idtlimit		QWORD ?
_gdtbase		QWORD ?
_gdtlimit		QWORD ?
_cr0			QWORD ?
_cr2			QWORD ?
_cr3			QWORD ?
_cr4			QWORD ?
_dr7			QWORD ?
_rip			QWORD ?
_rax			QWORD ?
_rbx			QWORD ?
_rcx			QWORD ?
_rdx			QWORD ?
_rsi			QWORD ?
_rdi			QWORD ?
_rbp			QWORD ?
_rsp			QWORD ?
_r8				QWORD ?
_r9				QWORD ?
_r10			QWORD ?
_r11			QWORD ?
_r12			QWORD ?
_r13			QWORD ?
_r14			QWORD ?
_r15			QWORD ?
_rflags			QWORD ?
_cs				QWORD ?
_ss				QWORD ?
_ds				QWORD ?
_es				QWORD ?
_fs				QWORD ?
_gs				QWORD ?
_tr				QWORD ?
_ldt			QWORD ?	
_cs_AccessRights	QWORD ?	
_ss_AccessRights	QWORD ?	
_ds_AccessRights	QWORD ?	
_es_AccessRights	QWORD ?	
_fs_AccessRights	QWORD ?	
_gs_AccessRights	QWORD ?	
_cs_Limit	QWORD ?	
_ss_Limit	QWORD ?	
_ds_Limit	QWORD ?	
_es_Limit	QWORD ?	
_fs_Limit	QWORD ?	
_gs_Limit	QWORD ?	
_fsbase			QWORD ?
_gsbase			QWORD ?
S_ORIGINALSTATE ENDS
PS_ORIGNALSTATE TYPEDEF PTR S_ORIGINALSTATE


EXTERN NewGDTDescriptor: GDTDesc
EXTERN NewGDTDescriptorVA: QWORD
EXTERN DBVMPML4PA: QWORD
EXTERN TemporaryPagingSetupPA: QWORD
EXTERN enterVMM2PA: QWORD
EXTERN originalstatePA: QWORD
EXTERN enterVMM2: QWORD

EXTERN originalstate: PS_ORIGNALSTATE
EXTERN vmmPA: QWORD

_TEXT SEGMENT 'CODE'

PUBLIC JTAGBP
JTAGBP:
db 0f1h
ret

PUBLIC enterVMM
enterVMM:
begin:
	;switch to identity mapped pagetable

	mov cr3,rdx
	jmp short weee
weee:
	nop
	nop

	
	;now jump to the physical address (identity mapped to the same virtual address)
	mov rax,secondentry
	mov r8,enterVMM
    sub rax,r8
	add rax,rsi ;add the physical address to the offset location	
	
	jmp rax

secondentry:
	;contrary to the 32-bit setup, we don't disable paging to make the switch to 64-bit, we're already there
	;we can just set the CR3 value
	
	
;----------TEST----------
;	waitforready:
;	mov dx,0ec05h
;	in al,dx
;	and al,20h
;	cmp al,20h
;	jne waitforready
;	
;	mov dx,0ec00h
;	mov al,'1'
;	out dx,al
;^^^^^^^^TEST^^^^^^^^
	

	;enable PAE and PSE (just to make sure)
	mov eax,30h
	mov cr4,rax	

	mov cr3,rcx
	nop
	nop
	jmp short weee2
weee2:
    nop
	nop

	mov rbx,0
	mov ds,bx
	mov es,bx
	mov fs,bx
	mov gs,bx
	mov ss,bx
	
	mov rax,cr0
	or eax,10000h
	mov cr0,rax ;enable WP bit
		
	nop
	nop
	nop
	nop
	;db 0f1h  ;jtag
	nop
	nop
	nop	

	
	jmp fword ptr [vmmjump]
	;jmp fword ptr [vmmjump] ;one thing that I don't mind about x64, relative addressing, so no need to change it by me


extrastorage:
	nop
	nop
	nop
	nop
	nop

vmmjump:	
	dd 00400000h
	dw 50h	
	

detectionstring:
	db 0ceh
	db 0ceh
	db 0ceh
	db 0ceh
	db 0ceh
	db 0ceh
	db 0ceh
	
	
PUBLIC enterVMMPrologue
enterVMMPrologue:	
	cli ;goodbye interrupts
	
	push rbx
	mov rbx,originalstate
	mov (S_ORIGINALSTATE PTR [rbx])._rax,rax
	pop rbx
	
	mov rax,originalstate	
	mov (S_ORIGINALSTATE PTR [rax])._rbx,rbx
	mov (S_ORIGINALSTATE PTR [rax])._rcx,rcx
	mov (S_ORIGINALSTATE PTR [rax])._rdx,rdx
	mov (S_ORIGINALSTATE PTR [rax])._rsi,rsi
	mov (S_ORIGINALSTATE PTR [rax])._rdi,rdi	
	mov (S_ORIGINALSTATE PTR [rax])._rbp,rbp
	mov (S_ORIGINALSTATE PTR [rax])._rsp,rsp
	mov (S_ORIGINALSTATE PTR [rax])._r8,r8
	mov (S_ORIGINALSTATE PTR [rax])._r9,r9
	mov (S_ORIGINALSTATE PTR [rax])._r10,r10
	mov (S_ORIGINALSTATE PTR [rax])._r11,r11
	mov (S_ORIGINALSTATE PTR [rax])._r12,r12
	mov (S_ORIGINALSTATE PTR [rax])._r13,r13
	mov (S_ORIGINALSTATE PTR [rax])._r14,r14
	mov (S_ORIGINALSTATE PTR [rax])._r15,r15
	
	mov rbx,enterVMMEpilogue
	mov (S_ORIGINALSTATE PTR [rax])._rip,rbx
	
	;jmp enterVMMEpilogue ;test to see if the loader is bugged
	
	;still here, loader didn't crash, start executing the move to the dbvm environment
	xchg bx,bx ;bochs break
	
	mov rbx,NewGDTDescriptorVA
	lgdt fword ptr [rbx]
	
	mov rcx,DBVMPML4PA
	mov rdx,TemporaryPagingSetupPA 
	mov rsi,enterVMM2PA
	

	jmp [enterVMM2]
			
PUBLIC enterVMMEpilogue
enterVMMEpilogue:
	nop
	nop
	push rax
	push rbx
	push rcx
	push rdx	
	cpuid
	pop rdx
	pop rcx
	pop rbx
	pop rax
	nop						
	nop	
	nop	
	
	
	

	
	mov r8,originalstate	
	
	;mov rbx,(S_ORIGINALSTATE PTR [r8])._tr
	;ltr bx

	mov rbx,(S_ORIGINALSTATE PTR [r8])._ss
	mov ss,bx	
	mov rbx,(S_ORIGINALSTATE PTR [r8])._ds
	mov ds,bx
	mov rbx,(S_ORIGINALSTATE PTR [r8])._es
	mov es,bx
	mov rbx,(S_ORIGINALSTATE PTR [r8])._fs
	mov fs,bx
	mov rbx,(S_ORIGINALSTATE PTR [r8])._gs
	mov gs,bx
	
	
	
	mov rcx,0c0000100h
	mov rax,(S_ORIGINALSTATE PTR [r8])._fsbase
	mov rdx,rax
	shr rdx,32
	wrmsr
	
	mov rcx,0c0000101h
	mov rax,(S_ORIGINALSTATE PTR [r8])._gsbase
	mov rdx,rax
	shr rdx,32
	wrmsr

	

	
		
	mov rax,originalstate	
	mov rbx,(S_ORIGINALSTATE PTR [rax])._rbx
	mov rcx,(S_ORIGINALSTATE PTR [rax])._rcx
	mov rdx,(S_ORIGINALSTATE PTR [rax])._rdx
	mov rsi,(S_ORIGINALSTATE PTR [rax])._rsi
	mov rdi,(S_ORIGINALSTATE PTR [rax])._rdi
	mov rbp,(S_ORIGINALSTATE PTR [rax])._rbp
	mov rsp,(S_ORIGINALSTATE PTR [rax])._rsp
	mov r8,(S_ORIGINALSTATE PTR [rax])._r8
	mov r9,(S_ORIGINALSTATE PTR [rax])._r9
	mov r10,(S_ORIGINALSTATE PTR [rax])._r10
	mov r11,(S_ORIGINALSTATE PTR [rax])._r11
	mov r12,(S_ORIGINALSTATE PTR [rax])._r12
	mov r13,(S_ORIGINALSTATE PTR [rax])._r13
	mov r14,(S_ORIGINALSTATE PTR [rax])._r14
	mov r15,(S_ORIGINALSTATE PTR [rax])._r15
	mov rax,(S_ORIGINALSTATE PTR [rax])._rax
	
	;crashtest
	;mov rax,0deadh
	;mov [rax],rax
	
	;sti
	ret
	nop
	nop
	nop

_TEXT   ENDS
        END

================================================
FILE: src/debugger.c
================================================
/*
debugger.c:
This unit will handle all debugging related code, from hooking, to handling interrupts

todo: this whole thing can be moved to a few simple lines in dbvm...
*/
#pragma warning( disable: 4100 4103 4189)
#include <ntifs.h>
#include <windef.h>

#include "DBKFunc.h"
#include "interruptHook.h"

#include "debugger.h"
#include "vmxhelper.h"

#ifdef AMD64 
extern void interrupt1_asmentry( void ); //declared in debuggera.asm
#else
void interrupt1_asmentry( void );
#endif



volatile struct
{
	BOOL		isDebugging;		//TRUE if a process is currently being debugged
	BOOL		stoppingTheDebugger;
	DWORD		debuggedProcessID;	//The processID that is currently debugger
	struct {
		BOOL		active;
		UINT_PTR	address;		//Up to 4 addresses to break on
		BreakType	breakType;		//What type of breakpoint for each seperate address
		BreakLength breakLength;	//How many bytes does this breakpoint look at
	} breakpoint[4];

	//...
	BOOL globalDebug;			//If set all threads of every process will raise an interrupt on taskswitch

	//while debugging:
	UINT_PTR *LastStackPointer;
	UINT_PTR *LastRealDebugRegisters;
	HANDLE LastThreadID;
	BOOL CausedByDBVM;
	BOOL handledlastevent;
	
	//BOOL storeLBR;
	//int storeLBR_max;
	//UINT_PTR *LastLBRStack;

	volatile struct {		
		UINT_PTR DR0;
		UINT_PTR DR1;
		UINT_PTR DR2;
		UINT_PTR DR3;
		UINT_PTR DR6;
		UINT_PTR DR7;
		UINT_PTR reserved;
		volatile int inEpilogue; //if set the global debug bit does no faking
	} FakedDebugRegisterState[256];

	char b[1];

	//volatile BYTE DECLSPEC_ALIGN(16) fxstate[512];

	BOOL isSteppingTillClear; //when set the user has entered single stepping mode. This is a one thread only thing, so when it's active and another single step happens, discard it

} DebuggerState;


KEVENT debugger_event_WaitForContinue; //event for kernelmode. Waits till it's set by usermode (usermode function: DBK_Continue_Debug_Event sets it)
KEVENT debugger_event_CanBreak; //event for kernelmode. Waits till a break has been handled so a new one can enter
KEVENT debugger_event_WaitForDebugEvent; //event for usermode. Waits till it's set by a debugged event

DebugReg7 debugger_dr7_getValue(void);
void debugger_dr7_setValue(DebugReg7 value);
DebugReg6 debugger_dr6_getValue(void);

JUMPBACK Int1JumpBackLocation;



typedef struct _SavedStack
{
	BOOL inuse;
	QWORD stacksnapshot[600];
} SavedStack, *PSavedStack;

criticalSection StacksCS;
int StackCount;
PSavedStack *Stacks;



void debugger_dr7_setGD(int state)
{

	DebugReg7 _dr7=debugger_dr7_getValue();
	_dr7.GD=state; //usually 1
	debugger_dr7_setValue(_dr7);

	
}

void debugger_dr0_setValue(UINT_PTR value)
{
	__writedr(0,value);
}

UINT_PTR debugger_dr0_getValue(void)
{
	return __readdr(0);
}

void debugger_dr1_setValue(UINT_PTR value)
{
	__writedr(1,value);
}

UINT_PTR debugger_dr1_getValue(void)
{
	return __readdr(1);
}

void debugger_dr2_setValue(UINT_PTR value)
{
	__writedr(2,value);
}

UINT_PTR debugger_dr2_getValue(void)
{
	return __readdr(2);
}

void debugger_dr3_setValue(UINT_PTR value)
{
	__writedr(3,value);
}

UINT_PTR debugger_dr3_getValue(void)
{
	return __readdr(3);
}

void debugger_dr6_setValue(UINT_PTR value)
{
	__writedr(6,value);
}

void debugger_dr7_setValue(DebugReg7 value)
{
	UINT_PTR temp=*(UINT_PTR *)&value;		
	__writedr(7,temp);
}

void debugger_dr7_setValueDword(UINT_PTR value)
{
	__writedr(7,value);	
}

UINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just typecast the DebugReg7 to a dword...
{
	return __readdr(7);
}


DebugReg7 debugger_dr7_getValue(void)
{
	UINT_PTR temp=debugger_dr7_getValueDword();
	return *(DebugReg7 *)&temp;
}

UINT_PTR debugger_dr6_getValueDword(void)
{
	return __readdr(6);
}

DebugReg6 debugger_dr6_getValue(void)
{
	UINT_PTR temp=debugger_dr6_getValueDword();
	return *(DebugReg6 *)&temp;
}



void debugger_touchDebugRegister(UINT_PTR param)
{
	//DbgPrint("Touching debug register. inepilogue=\n", DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue);

	
	debugger_dr0_setValue(debugger_dr0_getValue());
	
}

void debugger_initialize(void)
{
	//DbgPrint("Initializing debugger events\n");

	KeInitializeEvent(&debugger_event_WaitForContinue, SynchronizationEvent, FALSE);	
	KeInitializeEvent(&debugger_event_CanBreak, SynchronizationEvent, TRUE); //true so the first can enter
	KeInitializeEvent(&debugger_event_WaitForDebugEvent, SynchronizationEvent, FALSE);

	//DbgPrint("DebuggerState.fxstate=%p\n",DebuggerState.fxstate);



	StackCount = getCpuCount() * 4;
	Stacks = (PSavedStack*)ExAllocatePool(NonPagedPool, StackCount*sizeof(PSavedStack));


	int i;
	for (i = 0; i < StackCount; i++)
	{
		Stacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
		RtlZeroMemory(Stacks[i], sizeof(SavedStack));
	}
}

void debugger_shutdown(void)
{
	if (Stacks)
	{
		int i;
		for (i = 0; i < StackCount; i++)
		{
			if (Stacks[i])
			{
				ExFreePool(Stacks[i]);
				Stacks[i] = NULL;
			}
		}

		ExFreePool(Stacks);
		Stacks = NULL;
	}
}

void debugger_growstack()
//called in passive mode
{
	if (Stacks)
	{
		KIRQL oldIRQL=KeRaiseIrqlToDpcLevel();

		csEnter(&StacksCS);
		enableInterrupts(); //csEnter disables it, but we need it

		int newStackCount = StackCount * 2;
		int i;
		PSavedStack *newStacks;
		newStacks = (PSavedStack*)ExAllocatePool(NonPagedPool, newStackCount * sizeof(PSavedStack));

		if (newStacks)
		{
			for (i = 0; i < StackCount; i++)
				newStacks[i] = Stacks[i];

			for (i = StackCount; i < newStackCount; i++)
			{
				newStacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
				if (newStacks[i])				
					RtlZeroMemory(newStacks[i], sizeof(SavedStack));				
				else
				{
					ExFreePool(newStacks);
					csLeave(&StacksCS);
					KeLowerIrql(oldIRQL);
					return;
				}
			}

			
			ExFreePool(Stacks);
			Stacks = newStacks;
		}

		csLeave(&StacksCS);
		KeLowerIrql(oldIRQL);

	}
}

void debugger_setInitialFakeState(void)
{	
	//DbgPrint("setInitialFakeState for cpu %d\n",cpunr());
	DebuggerState.FakedDebugRegisterState[cpunr()].DR0=debugger_dr0_getValue();
	DebuggerState.FakedDebugRegisterState[cpunr()].DR1=debugger_dr1_getValue();
	DebuggerState.FakedDebugRegisterState[cpunr()].DR2=debugger_dr2_getValue();
	DebuggerState.FakedDebugRegisterState[cpunr()].DR3=debugger_dr3_getValue();
	DebuggerState.FakedDebugRegisterState[cpunr()].DR6=debugger_dr6_getValueDword();
	DebuggerState.FakedDebugRegisterState[cpunr()].DR7=debugger_dr7_getValueDword();
}

VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2)
{
	debugger_initHookForCurrentCPU();
}

int debugger_removeHookForCurrentCPU(UINT_PTR params)
{
	//DbgPrint("Unhooking int1 for this cpu\n");
    return inthook_UnhookInterrupt(1);	
}

int debugger_initHookForCurrentCPU(void)
/*
Must be called for each cpu
*/
{
	int result=TRUE;
	//DbgPrint("Hooking int1 for cpu %d\n", cpunr());
	
	result=inthook_HookInterrupt(1,getCS() & 0xfff8, (ULONG_PTR)interrupt1_asmentry, &Int1JumpBackLocation);	

#ifdef AMD64
	if (result)
	{
		;//DbgPrint("hooked int1. Int1JumpBackLocation=%x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
	}
	else
	{
		//DbgPrint("Failed hooking interrupt 1\n");
		return result;
	}
#endif

	if (DebuggerState.globalDebug)
	{
		//set the fake state
		//debugger_setInitialFakeState();
		//DbgPrint("Setting GD bit for cpu %d\n",cpunr());

		debugger_dr7_setGD(1); //enable the GD flag		
	}

	/*if (DebuggerState.storeLBR)
	{		
		//DbgPrint("Enabling LBR logging. IA32_DEBUGCTL was %x\n", __readmsr(0x1d9));
		__writemsr(0x1d9, __readmsr(0x1d9) | 1);
		//DbgPrint("Enabling LBR logging. IA32_DEBUGCTL is  %x\n", __readmsr(0x1d9));
	}*/
		
	return result;
}

void debugger_setStoreLBR(BOOL state)
{
	return; //disabled for now
	/*
	//if (state)
	//	DbgPrint("Setting storeLBR to true\n");
	//else
	//	DbgPrint("Setting storeLBR to false\n");

	DebuggerState.storeLBR=state; //it's not THAT crucial to disable/enable it

	DebuggerState.storeLBR_max=0;

	switch (cpu_model)
    {
        case 0x2a:
        case 0x1a:
        case 0x1e:
        case 0x1f:
        case 0x2e:
        case 0x25:
        case 0x2c:
          DebuggerState.storeLBR_max=16;
          break;

        case 0x17:
        case 0x1d:
        case 0x0f:
          DebuggerState.storeLBR_max=4;
          break;

        case 0x1c:
          DebuggerState.storeLBR_max=8;
          break;
    }

	//DbgPrint("Because your cpu_model=%d I think that your storeLBR_max=%d\n", cpu_model, DebuggerState.storeLBR_max);
	*/
	
}


int debugger_setGlobalDebugState(BOOL state)
//call this BEFORE debugging, if already debugging, the user must call this for each cpu
{
	//DbgPrint("debugger_setGlobalDebugState(%d)\n",state);
	if (state)
	  DebuggerState.globalDebug=state; //on enable set this first

	if (inthook_isHooked(1))
	{
		int oldEpilogueState=DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue;

		//DbgPrint("Int 1 is hooked,%ssetting GD\n",(state ? "":"un"));
		//DbgPrint("oldEpilogueState=%d\n",oldEpilogueState);
		//debugger_setInitialFakeState();

		DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=TRUE;
		DebuggerState.globalDebug=state;
		debugger_dr7_setGD(state);
		
		DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=oldEpilogueState;
		

		DebuggerState.FakedDebugRegisterState[cpunr()].DR7=0x400;
		debugger_dr7_setValueDword(0x400);		

	}

	return TRUE;
}



int debugger_startDebugging(DWORD debuggedProcessID)
/*
Call this AFTER the interrupts are hooked
*/
{
	//DbgPrint("debugger_startDebugging. Processid=%x\n",debuggedProcessID);
	Int1JumpBackLocation.eip=inthook_getOriginalEIP(1);
	Int1JumpBackLocation.cs=inthook_getOriginalCS(1);

#ifdef AMD64
	//DbgPrint("Int1 jump back = %x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
#endif

	DebuggerState.isDebugging=TRUE;
	DebuggerState.debuggedProcessID=debuggedProcessID;

	return TRUE;
}

int debugger_stopDebugging(void)
{	
	int i;

	//DbgPrint("Stopping the debugger if it is running\n");

	DebuggerState.stoppingTheDebugger=TRUE;	

	if (DebuggerState.globalDebug)
	{
		//touch the global debug for each debug processor
		//DbgPrint("Touching the debug registers\n");
        forEachCpuPassive(debugger_touchDebugRegister, 0);
	}

	

    DebuggerState.globalDebug=FALSE; //stop when possible, saves speed
	DebuggerState.isDebugging=FALSE;	

	for (i=0; i<4; i++)
		DebuggerState.breakpoint[i].active=FALSE;

	//unhook all processors

	forEachCpuPassive(debugger_removeHookForCurrentCPU, 0);


	return TRUE;
}

int debugger_unsetGDBreakpoint(int breakpointnr)
{
	int result=DebuggerState.breakpoint[breakpointnr].active;
	DebuggerState.breakpoint[breakpointnr].active=FALSE;
	return result; //returns true if it was active
}

int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl)
/*
Will register a specific breakpoint. If global debug is used it'll set this debug register accordingly
*/
{
	//DbgPrint("debugger_setGDBreakpoint(%d, %x, %d, %d)\n", breakpointnr, Address, bt, bl);
	DebuggerState.breakpoint[breakpointnr].active=TRUE;
	DebuggerState.breakpoint[breakpointnr].address=Address;
	DebuggerState.breakpoint[breakpointnr].breakType=bt;
	DebuggerState.breakpoint[breakpointnr].breakLength=bl;
	return TRUE;
}

NTSTATUS debugger_waitForDebugEvent(ULONG timeout)
{
	NTSTATUS r;
	LARGE_INTEGER wait;

	//DbgPrint("debugger_waitForDebugEvent with timeout of %d\n",timeout);

	//-10000000LL=1 second
	//-10000LL should be 1 millisecond
	//-10000LL
	wait.QuadPart=-10000LL * timeout;

	if (timeout==0xffffffff) //infinite wait
	  r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, NULL);
	else
	  r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, &wait);

	if (r==STATUS_SUCCESS)
		return r;
	else
		return STATUS_UNSUCCESSFUL;	
}

NTSTATUS debugger_continueDebugEvent(BOOL handled)
/*
Only call this by one thread only, and only when there's actually a debug eevnt in progress
*/
{
	//DbgPrint("debugger_continueDebugEvent\n");
	
	DebuggerState.handledlastevent=handled;
	KeSetEvent(&debugger_event_WaitForContinue, 0,FALSE);

	return STATUS_SUCCESS;
}

UINT_PTR *debugger_getLastStackPointer(void)
{
	
	return DebuggerState.LastStackPointer;
}


NTSTATUS debugger_getDebuggerState(PDebugStackState state)
{
	//DbgPrint("debugger_getDebuggerState\n");
	state->threadid=(UINT64)DebuggerState.LastThreadID;
	state->causedbydbvm = (UINT64)DebuggerState.CausedByDBVM;
	if (DebuggerState.LastStackPointer)
	{
		state->rflags=(UINT_PTR)DebuggerState.LastStackPointer[si_eflags];
		state->rax=DebuggerState.LastStackPointer[si_eax];
		state->rbx=DebuggerState.LastStackPointer[si_ebx];
		state->rcx=DebuggerState.LastStackPointer[si_ecx];
		state->rdx=DebuggerState.LastStackPointer[si_edx];
		state->rsi=DebuggerState.LastStackPointer[si_esi];
		state->rdi=DebuggerState.LastStackPointer[si_edi];
		state->rbp=DebuggerState.LastStackPointer[si_ebp];

		

	#ifdef AMD64
		//fill in the extra registers
		state->r8=DebuggerState.LastStackPointer[si_r8];
		state->r9=DebuggerState.LastStackPointer[si_r9];
		state->r10=DebuggerState.LastStackPointer[si_r10];
		state->r11=DebuggerState.LastStackPointer[si_r11];
		state->r12=DebuggerState.LastStackPointer[si_r12];
		state->r13=DebuggerState.LastStackPointer[si_r13];
		state->r14=DebuggerState.LastStackPointer[si_r14];
		state->r15=DebuggerState.LastStackPointer[si_r15];	
		memcpy(state->fxstate, (void *)&DebuggerState.LastStackPointer[si_xmm], 512);
	#endif		
		
		


		//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
		if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
		{
			//priv level change, so the stack info was pushed as well
			state->rsp=DebuggerState.LastStackPointer[si_esp]; 
			state->ss=DebuggerState.LastStackPointer[si_ss];
		}
		else
		{
			//kernelmode stack, yeah, it's really useless here since changing it here only means certain doom, but hey...
			state->rsp=(UINT_PTR)(DebuggerState.LastStackPointer)-4;
			state->ss=getSS();; //unchangeble by the user
		}

		
		state->rip=DebuggerState.LastStackPointer[si_eip];
		state->cs=DebuggerState.LastStackPointer[si_cs];
		state->ds=DebuggerState.LastStackPointer[si_ds];
		state->es=DebuggerState.LastStackPointer[si_es];
	#ifdef AMD64
		state->fs=0;
		state->gs=0;
	#else
		state->fs=DebuggerState.LastStackPointer[si_fs];
		state->gs=DebuggerState.LastStackPointer[si_gs];
	#endif

		state->dr0=DebuggerState.LastRealDebugRegisters[0];
		state->dr1=DebuggerState.LastRealDebugRegisters[1];
		state->dr2=DebuggerState.LastRealDebugRegisters[2];
		state->dr3=DebuggerState.LastRealDebugRegisters[3];
		state->dr6=DebuggerState.LastRealDebugRegisters[4];
		state->dr7=DebuggerState.LastRealDebugRegisters[5];

		 /*if (DebuggerState.storeLBR)
		{
			//DbgPrint("Copying the LBR stack to usermode\n");
			//DbgPrint("storeLBR_max=%d\n", DebuggerState.storeLBR_max);

		
			for (state->LBR_Count=0; state->LBR_Count<DebuggerState.storeLBR_max; state->LBR_Count++ )
			{
				//DbgPrint("DebuggerState.LastLBRStack[%d]=%x\n", state->LBR_Count, DebuggerState.LastLBRStack[state->LBR_Count]);
				state->LBR[state->LBR_Count]=DebuggerState.LastLBRStack[state->LBR_Count];
				if (state->LBR[state->LBR_Count]==0) //no need to copy once a 0 has been reached
					break;				
			}
		}
		else*/
			state->LBR_Count=0;


		return STATUS_SUCCESS;
	}
	else
	{
		//DbgPrint("debugger_getDebuggerState was called while DebuggerState.LastStackPointer was still NULL");
		return STATUS_UNSUCCESSFUL;
	}
}

NTSTATUS debugger_setDebuggerState(PDebugStackState state)
{
	if (DebuggerState.LastStackPointer)
	{
		DebuggerState.LastStackPointer[si_eflags]=(UINT_PTR)state->rflags;

		//DbgPrint("have set eflags to %x\n",DebuggerState.LastStackPointer[si_eflags]);


		DebuggerState.LastStackPointer[si_eax]=(UINT_PTR)state->rax;
		DebuggerState.LastStackPointer[si_ebx]=(UINT_PTR)state->rbx;
		DebuggerState.LastStackPointer[si_ecx]=(UINT_PTR)state->rcx;
		DebuggerState.LastStackPointer[si_edx]=(UINT_PTR)state->rdx;
		
		DebuggerState.LastStackPointer[si_esi]=(UINT_PTR)state->rsi;
		DebuggerState.LastStackPointer[si_edi]=(UINT_PTR)state->rdi;
		
		DebuggerState.LastStackPointer[si_ebp]=(UINT_PTR)state->rbp;

		//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
		if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
		{
			//priv level change, so the stack info was pushed as well
			DebuggerState.LastStackPointer[si_esp]=(UINT_PTR)state->rsp;
			//don't mess with ss
		}
		else
		{
			//no change in kernelmode allowed		
		}

		
		DebuggerState.LastStackPointer[si_eip]=(UINT_PTR)state->rip;
		DebuggerState.LastStackPointer[si_cs]=(UINT_PTR)state->cs;
		DebuggerState.LastStackPointer[si_ds]=(UINT_PTR)state->ds;
		DebuggerState.LastStackPointer[si_es]=(UINT_PTR)state->es;
	#ifndef AMD64
		DebuggerState.LastStackPointer[si_fs]=(UINT_PTR)state->fs;
		DebuggerState.LastStackPointer[si_gs]=(UINT_PTR)state->gs;
	#else //don't touch fs or gs in 64-bit
		DebuggerState.LastStackPointer[si_r8]=(UINT_PTR)state->r8;
		DebuggerState.LastStackPointer[si_r9]=(UINT_PTR)state->r9;
		DebuggerState.LastStackPointer[si_r10]=(UINT_PTR)state->r10;
		DebuggerState.LastStackPointer[si_r11]=(UINT_PTR)state->r11;
		DebuggerState.LastStackPointer[si_r12]=(UINT_PTR)state->r12;
		DebuggerState.LastStackPointer[si_r13]=(UINT_PTR)state->r13;
		DebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14;
		DebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15;
		memcpy((void *)&DebuggerState.LastStackPointer[si_xmm], state->fxstate, 512);
	#endif
		


		if (!DebuggerState.globalDebug)
		{
			//no idea why someone would want to use this method, but it's in (for NON globaldebug only)

			//updating this array too just so the user can see it got executed. (it eases their state of mind...)
			DebuggerState.LastRealDebugRegisters[0]=(UINT_PTR)state->dr0; 
			DebuggerState.LastRealDebugRegisters[1]=(UINT_PTR)state->dr1;
			DebuggerState.LastRealDebugRegisters[2]=(UINT_PTR)state->dr2;
			DebuggerState.LastRealDebugRegisters[3]=(UINT_PTR)state->dr3;
			DebuggerState.LastRealDebugRegisters[4]=(UINT_PTR)state->dr6;
			DebuggerState.LastRealDebugRegisters[5]=(UINT_PTR)state->dr7;

			//no setting of the DebugRegs here

		}
	}
	else
	{
		//DbgPrint("debugger_setDebuggerState was called while DebuggerState.LastStackPointer was still NULL");
		return STATUS_UNSUCCESSFUL;
	}

	return STATUS_SUCCESS;
}

int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs, UINT_PTR *LBR_Stack, int causedbyDBVM)
//Notice: This routine is called when interrupts are enabled and the GD bit has been set if globaL DEBUGGING HAS BEEN USED
//Interrupts are enabled and should be at passive level, so taskswitching is possible
{
	NTSTATUS r=STATUS_UNSUCCESSFUL;
	int handled=0; //0 means let the OS handle it
	LARGE_INTEGER timeout;
	timeout.QuadPart=-100000;
	
	
	
	//DbgPrint("breakpointHandler for kernel breakpoints\n");

#ifdef AMD64
	//DbgPrint("cs=%x ss=%x ds=%x es=%x fs=%x gs=%x\n",getCS(), getSS(), getDS(), getES(), getFS(), getGS());

	//DbgPrint("fsbase=%llx gsbase=%llx gskernel=%llx\n", readMSR(0xc0000100), readMSR(0xc0000101), readMSR(0xc0000102));

	//DbgPrint("rbp=%llx\n", getRBP());

	//DbgPrint("gs:188=%llx\n", __readgsqword(0x188));
	//DbgPrint("causedbyDBVM=%d\n", causedbyDBVM);
#endif
	
	if (KeGetCurrentIrql()==0)
	{
		//crititical section here
		if ((stackpointer[si_cs] & 3)==0)
		{
			//DbgPrint("Going to wait in a kernelmode routine\n");
		}

	
		//block other threads from breaking until this one has been handled
		while (r != STATUS_SUCCESS)
		{
			r=KeWaitForSingleObject(&debugger_event_CanBreak,Executive, KernelMode, FALSE, NULL);
			//check r and handle specific events

			//DbgPrint("Woke up. r=%x\n",r);
				
		}

		if ((stackpointer[si_cs] & 3)==0)
		{
			//DbgPrint("Woke up in a kernelmode routine\n");
		}
		

		//We're here, let's notify the usermode debugger of our situation
		//first store the stackpointer so it can be manipulated externally
		DebuggerState.LastStackPointer=stackpointer;
		DebuggerState.LastRealDebugRegisters=currentdebugregs;		
		/*DebuggerState.LastLBRStack=LBR_Stack;*/
		DebuggerState.LastThreadID=PsGetCurrentThreadId();
		DebuggerState.CausedByDBVM = causedbyDBVM;
		


 


		//notify usermode app that this thread has halted due to a debug event
		
		KeSetEvent(&debugger_event_WaitForDebugEvent,0,FALSE);


		//wait for event from usermode that debgu event has been handled
		//KeWaitForSingleObject();
		//continue with state

		while (1)
		{


			//LARGE_INTEGER wt;
			NTSTATUS s=STATUS_UNSUCCESSFUL;
			
			//wt.QuadPart=-10000000LL; 
			//s=KeDelayExecutionThread(KernelMode, FALSE, &wt);

			//DbgPrint("Waiting...\n");


			while (s != STATUS_SUCCESS)
			{
				s=KeWaitForSingleObject(&debugger_event_WaitForContinue, Executive, KernelMode, FALSE, NULL);
				//DbgPrint("KeWaitForSingleObject=%x\n",s);		
			}

			

			if (s==STATUS_SUCCESS)
			{
				if (DebuggerState.handledlastevent)
				{
					//DbgPrint("handledlastevent=TRUE");
					handled=1;
				}
				else
					handled=0;

				break;
			}
				
		}


		DebuggerState.LastStackPointer=NULL; //NULL the stackpointer so routines know it should not be called

		//i'm done, let other threads catch it
		KeSetEvent(&debugger_event_CanBreak, 0, FALSE);

		//DbgPrint("Returning after a wait. handled=%d and eflags=%x\n",handled, stackpointer[si_eflags]);
		if ((stackpointer[si_cs] & 3)==0) //check rpl of cs
		{
			//DbgPrint("and in kernelmode\n");
		}

		return handled;
	}
	else
	{
		//DbgPrint("Breakpoint wasn't at passive level. Screw this, i'm not going to break here\n");
		
		return 1;
	}

}

int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
{
	HANDLE CurrentProcessID=PsGetCurrentProcessId();	
	UINT_PTR originaldr6=currentdebugregs[4];
	DebugReg6 _dr6=*(DebugReg6 *)&currentdebugregs[4];

	UINT_PTR LBR_Stack[16]; //max 16
//	DebugReg7 _dr7=*(DebugReg7 *)&currentdebugregs[5];

	int causedbyDBVM = vmxusable && vmx_causedCurrentDebugBreak();

	/*
	if (cpu_familyID==0x6)
	{
		if (DebuggerState.storeLBR)
		{
			//fetch the lbr stack
			int MSR_LASTBRANCH_TOS=0x1c9;
			int MSR_LASTBRANCH_0=0x40;

			int i;
			int count;

			

			i=(int)__readmsr(MSR_LASTBRANCH_TOS);
			count=0;
			while (count<DebuggerState.storeLBR_max)
			{
				UINT64 x;
				x=__readmsr(MSR_LASTBRANCH_0+i);
				LBR_Stack[count]=(UINT_PTR)x;
				__writemsr(MSR_LASTBRANCH_0+i,0); //it has been read out, so can be erased now

				count++;
				i++;
				i=i % DebuggerState.storeLBR_max;				
			}
		}
	}
	*/
	

	//DbgPrint("interrupt1_handler(%p). DR6=%x (%x) DR7=%x %x:%p\n", interrupt1_handler, originaldr6, debugger_dr6_getValueDword(), debugger_dr7_getValueDword(), stackpointer[si_cs], (void*)(stackpointer[si_eip]));
	
	//check if this break should be handled or not
	
	if (DebuggerState.globalDebug)
	{
		//DbgPrint("DebuggerState.globalDebug=TRUE\n");
		//global debugging is being used
		if (_dr6.BD)
		{
			_dr6.BD = 0;
			debugger_dr6_setValue(*(UINT_PTR *)&_dr6);

		    //The debug registers are being accessed, emulate it with DebuggerState.FakedDebugRegisterState[cpunr()].DRx

			if ((stackpointer[si_cs] & 3)==0)
			{
				int instructionPointer;
	#ifdef AMD64
				int prefixpointer;
	#endif
				int currentcpunr = cpunr();
				int debugregister;
				int generalpurposeregister;
				unsigned char *instruction = (unsigned char *)stackpointer[si_eip];

				//unset this flag in DR6
				_dr6.BD = 0;
				debugger_dr6_setValue(*(UINT_PTR *)&_dr6);

				if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
				{
					((EFLAGS *)&stackpointer[si_eflags])->RF = 1; //repeat this instruction and don't break
					return 2;
				}


				//DbgPrint("handler: Setting fake dr6 to %x\n",*(UINT_PTR *)&_dr6);

				DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = *(UINT_PTR *)&_dr6;

				for (instructionPointer = 0; instruction[instructionPointer] != 0x0f; instructionPointer++); //find the start of the instruction, skipping prefixes etc...

				//we now have the start of the instruction.
				//Find out which instruction it is, and which register is used
				debugregister = (instruction[instructionPointer + 2] >> 3) & 7;
				generalpurposeregister = instruction[instructionPointer + 2] & 7;

	#ifdef AMD64
				for (prefixpointer = 0; prefixpointer < instructionPointer; prefixpointer++)
				{
					//check for a REX.B prefix  (0x40  + 0x1 : 0x41)
					if ((instruction[prefixpointer] & 0x41) == 0x41)
					{
						//rex.b prefix is used, r8 to r15 are being accessed
						generalpurposeregister += 8;
					}
				}

	#endif

				//DbgPrint("debugregister=%d, generalpurposeregister=%d\n",debugregister,generalpurposeregister); 

				if (instruction[instructionPointer + 1] == 0x21)
				{
					UINT_PTR drvalue = 0;
					//DbgPrint("read opperation\n");
					//21=read
					switch (debugregister)
					{
					case 0:

						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
						//DbgPrint("Reading DR0 (returning %x real %x)\n", drvalue, currentdebugregs[0]); 
						break;

					case 1:
						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
						break;

					case 2:
						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
						break;

					case 3:
						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
						break;

					case 4:
					case 6:
						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
						//DbgPrint("reading dr6 value:%x\n",drvalue);
						break;

					case 5:
					case 7:
						drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
						break;

					default:
						//DbgPrint("Invalid debugregister\n");
						drvalue = 0;
						break;
					}

					switch (generalpurposeregister)
					{
					case 0:
						stackpointer[si_eax] = drvalue;
						break;

					case 1:
						stackpointer[si_ecx] = drvalue;
						break;

					case 2:
						stackpointer[si_edx] = drvalue;
						break;

					case 3:
						stackpointer[si_ebx] = drvalue;
						break;

					case 4:
						if ((stackpointer[si_cs] & 3) == 3)  //usermode dr access ?
							stackpointer[si_esp] = drvalue;
						else
							stackpointer[si_stack_esp] = drvalue;

						break;

					case 5:
						stackpointer[si_ebp] = drvalue;
						break;

					case 6:
						stackpointer[si_esi] = drvalue;
						break;

					case 7:
						stackpointer[si_edi] = drvalue;
						break;

	#ifdef AMD64
					case 8:
						stackpointer[si_r8] = drvalue;
						break;

					case 9:
						stackpointer[si_r9] = drvalue;
						break;

					case 10:
						stackpointer[si_r10] = drvalue;
						break;

					case 11:
						stackpointer[si_r11] = drvalue;
						break;

					case 12:
						stackpointer[si_r12] = drvalue;
						break;

					case 13:
						stackpointer[si_r13] = drvalue;
						break;

					case 14:
						stackpointer[si_r14] = drvalue;
						break;

					case 15:
						stackpointer[si_r15] = drvalue;
						break;


	#endif
					}

				}
				else
					if (instruction[instructionPointer + 1] == 0x23)
					{
						//23=write
						UINT_PTR gpvalue = 0;
						//DbgPrint("Write operation\n");
						switch (generalpurposeregister)
						{
						case 0:
							gpvalue = stackpointer[si_eax];
							break;

						case 1:
							gpvalue = stackpointer[si_ecx];
							break;

						case 2:
							gpvalue = stackpointer[si_edx];
							break;

						case 3:
							gpvalue = stackpointer[si_ebx];
							break;

						case 4:
							if ((stackpointer[si_cs] & 3) == 3)
								gpvalue = stackpointer[si_esp];

							break;

						case 5:
							gpvalue = stackpointer[si_ebp];
							break;

						case 6:
							gpvalue = stackpointer[si_esi];
							break;

						case 7:
							gpvalue = stackpointer[si_edi];
							break;
	#ifdef AMD64
						case 8:
							gpvalue = stackpointer[si_r8];
							break;

						case 9:
							gpvalue = stackpointer[si_r9];
							break;

						case 10:
							gpvalue = stackpointer[si_r10];
							break;

						case 11:
							gpvalue = stackpointer[si_r11];
							break;

						case 12:
							gpvalue = stackpointer[si_r12];
							break;

						case 13:
							gpvalue = stackpointer[si_r13];
							break;

						case 14:
							gpvalue = stackpointer[si_r14];
							break;

						case 15:
							gpvalue = stackpointer[si_r15];
							break;

						default:
							//DbgPrint("Invalid register value\n");
							break;
	#endif
						}

						//gpvalue now contains the value to set the debug register
						switch (debugregister)
						{
						case 0:
							//DbgPrint("Writing DR0. Original value=%x new value=%x\n", currentdebugregs[0], gpvalue);
							debugger_dr0_setValue(gpvalue);
							DebuggerState.FakedDebugRegisterState[cpunr()].DR0 = debugger_dr0_getValue();
							break;

						case 1:
							debugger_dr1_setValue(gpvalue);
							DebuggerState.FakedDebugRegisterState[cpunr()].DR1 = debugger_dr1_getValue();
							break;

						case 2:
							debugger_dr2_setValue(gpvalue);
							DebuggerState.FakedDebugRegisterState[cpunr()].DR2 = debugger_dr2_getValue();
							break;

						case 3:
							debugger_dr3_setValue(gpvalue);
							DebuggerState.FakedDebugRegisterState[cpunr()].DR3 = debugger_dr3_getValue();
							break;

						case 4:
						case 6:
							//DbgPrint("Setting dr6 to %x (was %x)\n", gpvalue, DebuggerState.FakedDebugRegisterState[cpunr()].DR6);							
							_dr6 = *(DebugReg6 *)&gpvalue;

							//if (_dr6.BD) DbgPrint("Some code wants to set the BD flag to 1\n");
							



							debugger_dr6_setValue(gpvalue);
							DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();

							if (_dr6.BD)
							{
								_dr6.BD = 0;
								debugger_dr6_setValue(gpvalue);
							}

							break;

						case 5:
						case 7:
							//make sure it doesn't set the GD flag here
							//DbgPrint("DR7 write\n");

							//if (generalpurposeregister == 15)
							//{
							//	while (1); //patchguard
							//}

							//if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
							//{
								//	DbgPrint("Was in epilogue\n");
							//}

							//check for invalid bits and raise a GPF if invalid


							gpvalue = (gpvalue | 0x400) & (~(1 << 13)); //unset the GD value

							//gpvalue=0xf0401;
							debugger_dr7_setValueDword(gpvalue);

							DebuggerState.FakedDebugRegisterState[cpunr()].DR7 = debugger_dr7_getValueDword();

							break;
						}



					}
					else
					{
						//DbgPrint("Some unknown instruction accessed the debug registers?\n");
						//if (CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
						//	DbgPrint("Happened inside the target process\n");

						//DbgPrint("interrupt1_handler dr6=%x (original=%x) dr7=%d\n",_dr6, originaldr6, _dr7);
						//DbgPrint("eip=%x\n",stackpointer[si_eip]);
					}

				//adjust eip to after this instruction
				stackpointer[si_eip] += instructionPointer + 3; //0f xx /r

				return 1; //don't tell windows about it
			}
			else
			{
				//DbgPrint("DR6.BD == 1 in USERMODE! WTF\n");
				_dr6.BD = 0;
				debugger_dr6_setValue(*(UINT_PTR *)&_dr6);
				DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();
			}
		}
	}



	if (DebuggerState.isSteppingTillClear) //this doesn't really work because when the state comes back to interruptable the system has a critical section lock on the GUI, so yeah... I really need a DBVM display driver for this
	{
	
		if ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))
		{
			((PEFLAGS)&stackpointer[si_eflags])->TF = 1;
			((PEFLAGS)&stackpointer[si_eflags])->RF = 1;
			debugger_dr6_setValue(0xffff0ff0);
			return 1;
		}

		DebuggerState.isSteppingTillClear = FALSE;	
	}

	
	if (DebuggerState.isDebugging)
	{
		//DbgPrint("DebuggerState.isDebugging\n");
		//check if this should break
		if (CurrentProcessID == (HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
		{
			UINT_PTR originaldebugregs[6];
			UINT64 oldDR7 = getDR7();


			if ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))
			{
				//There's no way to display the state to the usermode part of CE
				//DbgPrint("int1 at unstoppable location");
				if (!KernelCodeStepping)
				{
					((PEFLAGS)&stackpointer[si_eflags])->TF = 0; //just give up stepping
				//	DbgPrint("Quitting this");
				}
				else
				{
					//	DbgPrint("Stepping until valid\n");
					((PEFLAGS)&stackpointer[si_eflags])->TF = 1; //keep going until a valid state
					DebuggerState.isSteppingTillClear = TRUE; //Just in case a taskswitch happens right after enabling passive level with interrupts
				}

				((PEFLAGS)&stackpointer[si_eflags])->RF = 1;
				debugger_dr6_setValue(0xffff0ff0);
				return 1;
			}

			DebuggerState.isSteppingTillClear = FALSE;



			//DbgPrint("CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID\n");

			if (DebuggerState.globalDebug)
			{
				originaldebugregs[0] = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
				originaldebugregs[1] = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
				originaldebugregs[2] = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
				originaldebugregs[3] = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
				originaldebugregs[4] = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
				originaldebugregs[5] = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
			}

			//DbgPrint("BP in target process\n");

			//no extra checks if it's caused by the debugger or not. That is now done in the usermode part
			//if (*(PEFLAGS)(&stackpointer[si_eflags]).IF)	
/*
			if (((PEFLAGS)&stackpointer[si_eflags])->IF==0)
			{
				//DbgPrint("Breakpoint while interrupts are disabled: %x\n",stackpointer[si_eip]);
				//An breakpoint happened while IF was 0. Step through the code untill IF is 1
				((PEFLAGS)&stackpointer[si_eflags])->RF=1;
				((PEFLAGS)&stackpointer[si_eflags])->TF=1; //keep going until IF=1
				DbgPrint("IF==0\n");
				return 1; //don't handle it but also don't tell windows
			}*/

			//set the real debug registers to what it is according to the guest (so taskswitches take over these values) .... shouldn't be needed as global debug is on which fakes that read...



			if (DebuggerState.globalDebug)
			{
				//enable the GD flag for taskswitches that will occur as soon as interrupts are enabled
				//this also means: DO NOT EDIT THE DEBUG REGISTERS IN GLOBAL DEBUG MODE at this point. Only in the epilogue

				if (!DebuggerState.stoppingTheDebugger) //This is set when the driver is unloading. So do NOT set it back then
					debugger_dr7_setGD(DebuggerState.globalDebug);
			}
			else
			{
				//unset ALL debug registers before enabling taskswitching. Just re-enable it when back when interrupts are disabled again
				debugger_dr7_setValueDword(0x400);
				debugger_dr0_setValue(0);
				debugger_dr1_setValue(0);
				debugger_dr2_setValue(0);
				debugger_dr3_setValue(0);
				debugger_dr6_setValue(0xffff0ff0);
			}

			//start the windows taskswitching mode

			//if (1) return 1;

			//save the state of the thread to a place that won't get overwritten

			//todo: breaks 32-bit
			//int i;
			BOOL NeedsToGrowStackList = FALSE;
			PSavedStack SelectedStackEntry = NULL;
			/*
			csEnter(&StacksCS);
			for (i = 0; i < StackCount; i++)
			{
				if (Stacks[i]->inuse == FALSE)
				{
					SelectedStackEntry = Stacks[i];
					SelectedStackEntry->inuse = TRUE;
					RtlCopyMemory(SelectedStackEntry->stacksnapshot, stackpointer, 600 * 8);

					if (i > StackCount / 2)
						NeedsToGrowStackList = TRUE;

					break;
				}
			}
			csLeave(&StacksCS);

			enableInterrupts();

			//grow stack if needed

			if (NeedsToGrowStackList)
				debugger_growstack();
		*/

			{
				int rs=1;	

				//DbgPrint("calling breakpointHandler_kernel\n");

				if (SelectedStackEntry == NULL) //fuck
					rs = breakpointHandler_kernel(stackpointer, currentdebugregs, LBR_Stack, causedbyDBVM);
				else
					rs = breakpointHandler_kernel((UINT_PTR *)(SelectedStackEntry->stacksnapshot), currentdebugregs, LBR_Stack, causedbyDBVM);

				
				
				//DbgPrint("After handler\n");
/*
				if (SelectedStackEntry)  //restore the stack
				{
					RtlCopyMemory(stackpointer, SelectedStackEntry->stacksnapshot, 600 * 8);
					SelectedStackEntry->inuse = FALSE;
				}
				*/
				
				//DbgPrint("rs=%d\n",rs);


				disableInterrupts();

				//restore the 


				//we might be on a different CPU now
				if (DebuggerState.globalDebug)
				{
					DebuggerState.FakedDebugRegisterState[cpunr()].DR0=originaldebugregs[0];
					DebuggerState.FakedDebugRegisterState[cpunr()].DR1=originaldebugregs[1];
					DebuggerState.FakedDebugRegisterState[cpunr()].DR2=originaldebugregs[2];
					DebuggerState.FakedDebugRegisterState[cpunr()].DR3=originaldebugregs[3];
					DebuggerState.FakedDebugRegisterState[cpunr()].DR6=originaldebugregs[4];
					DebuggerState.FakedDebugRegisterState[cpunr()].DR7=originaldebugregs[5];
				}
				else
				{
					
					/*if (getDR7() != oldDR7)
					{
						DbgPrint("Something changed DR7. old=%llx new=%llx\n",oldDR7, getDR7());
					}*/

					
					//set the debugregisters to what they where set to before taskswitching was enable
					//with global debug this is done elsewhere
					debugger_dr0_setValue(currentdebugregs[0]);
					debugger_dr1_setValue(currentdebugregs[1]);
					debugger_dr2_setValue(currentdebugregs[2]);
					debugger_dr3_setValue(currentdebugregs[3]);
					debugger_dr6_setValue(currentdebugregs[4]);

					if ((currentdebugregs[5] >> 13) & 1)
					{
					//	DbgPrint("WTF? GD is 1 in currentdebugregs[5]: %llx\n", currentdebugregs[5]);
					}
					else
						debugger_dr7_setValue(*(DebugReg7 *)&currentdebugregs[5]);	
						
				}
				
				return rs;
			}
		}
		else 
		{
			//DbgPrint("Not the debugged process (%x != %x)\n",CurrentProcessID,DebuggerState.debuggedProcessID );
			//check if this break is due to a breakpoint ce has set. (during global debug threadsurfing))
			//do that by checking if the breakpoint condition exists in the FAKE dr7 registers
			//if so, let windows handle it, if not, it is caused by ce, which then means, skip (so execute normally)

			if (DebuggerState.globalDebug)
			{			
				DebugReg6 dr6=debugger_dr6_getValue();
				DebugReg7 dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;

				//real dr6		//fake dr7
				if ((dr6.B0) && (!(dr7.L0 || dr7.G0))) { /*DbgPrint("setting RF because of B0\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //break caused by DR0 and not expected by the current process, ignore this bp and continue
				if ((dr6.B1) && (!(dr7.L1 || dr7.G1))) { /*DbgPrint("setting RF because of B1\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //		...		DR1		...
				if ((dr6.B2) && (!(dr7.L2 || dr7.G2))) { /*DbgPrint("setting RF because of B2\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //		...		DR2		...
				if ((dr6.B3) && (!(dr7.L3 || dr7.G3))) { /*DbgPrint("setting RF because of B3\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //		...		DR3		...
			}

			if (causedbyDBVM)
				return 1; //correct PA, bad PID, ignore BP

			if (DebuggerState.isSteppingTillClear) //shouldn't happen often
			{
				//DbgPrint("That thing that shouldn\'t happen often happened\n");
				((PEFLAGS)&stackpointer[si_eflags])->TF = 0;

				DebuggerState.isSteppingTillClear = 0;
				return 1; //ignore
			}

			//DbgPrint("Returning unhandled. DR6=%x", debugger_dr6_getValueDword());
			
			return 0; //still here, so let windows handle it

		}
	}
	else
		return 0; //Let windows handle it

	//get the current processid
	//is it being debugged
	//if yes, check if the breakpoint is something done by me
	//if no, exit
	
}

int interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-bit stackpointer
{
	UINT_PTR before;//,after;
	UINT_PTR currentdebugregs[6]; //used for determining if the current bp is caused by the debugger or not
	int handled=0; //if 0 at return, the interupt will be passed down to the operating system
	QWORD naddress;
	//DbgPrint("interrupt1_centry cpunr=%d esp=%x\n",cpunr(), getRSP());

	//bsod crashfix, but also disables kernelmode stepping
	IDT idt;
	GetIDT(&idt);

	naddress = idt.vector[1].wLowOffset + (idt.vector[1].wHighOffset << 16);
#ifdef AMD64
	naddress += ((UINT64)idt.vector[1].TopOffset << 32);
#endif
	stackpointer[si_errorcode] = (UINT_PTR)naddress; //the errorcode is used as address to call the original function if needed
		


	/*
	if (Int1JumpBackLocation.eip != naddress) //no, just fucking no (patchguard will replace all inthandlers with invalid ones and then touch dr7)	
	{
		//todo: the usual, but make sure not to use dbgprint or anything that could trigger a software int
		if (DebuggerState.globalDebug)
		{
			debugger_dr7_setGD(DebuggerState.globalDebug);
			stackpointer[si_eip] += 4;
			return 1;
		}
	}
	*/






	before=getRSP();

	//Fetch current debug registers
	currentdebugregs[0]=debugger_dr0_getValue();
	currentdebugregs[1]=debugger_dr1_getValue();
	currentdebugregs[2]=debugger_dr2_getValue();
	currentdebugregs[3]=debugger_dr3_getValue();
	currentdebugregs[4]=debugger_dr6_getValueDword();
	currentdebugregs[5]=debugger_dr7_getValueDword();


	handled=interrupt1_handler(stackpointer, currentdebugregs);

	//epilogue:
	//At the end when returning:
	
	

	//
	//--------------------------------------------------------------------------
	//--------------EPILOGUE (AFTER HAVING HANDLED THE BREAKPOINT)--------------
	//--------------------------------------------------------------------------
	//
	
	
	disableInterrupts(); //just making sure..	


	DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
	debugger_dr7_setGD(0); //make sure the GD bit is disabled (int1 within int1, oooh the fun..., and yes, THIS itself will cause one too)
	DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1; //just be sure...


	//if (inthook_isDBVMHook(1))
	//{
		//update the int1 return address, could have been changed
		

		

		//DbgPrint("This was a dbvm hook. Changing if the interrupt return address is still valid\n");

	//	Int1JumpBackLocation.cs=idt.vector[1].wSelector;
	//	naddress=idt.vector[1].wLowOffset+(idt.vector[1].wHighOffset << 16);
#ifdef AMD64
	//	naddress+=((UINT64)idt.vector[1].TopOffset << 32);		
#endif
	   


	//}
	

	if (DebuggerState.globalDebug) //DR's are only accesses when there are DR's(no idea how it handles breakpoints in a different process...), so set them in each thread even those that don't belong original: && (PsGetCurrentProcessId()==(HANDLE)DebuggerState.debuggedProcessID))
	{
		//set the breakpoint in this thread. 		
        DebugReg6 dr6=debugger_dr6_getValue();
		//DebugReg7 dr7=debugger_dr7_getValue();

		DebugReg6 _dr6=*(DebugReg6 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
        DebugReg7 _dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
		int debugregister=0, breakpoint=0;
		


        //first clear the DR6 bits caused by the debugger

		if (!handled)
		{
			//it's going to get sent to windows
			if (dr6.BD && _dr7.GD) _dr6.BD=1; //should already have been done, but what the heck...
			if (dr6.B0 && (_dr7.L0 || _dr7.G0)) _dr6.B0=1;
			if (dr6.B1 && (_dr7.L1 || _dr7.G1)) _dr6.B1=1;
			if (dr6.B2 && (_dr7.L2 || _dr7.G2)) _dr6.B2=1;
			if (dr6.B3 && (_dr7.L3 || _dr7.G3)) _dr6.B3=1;

			_dr6.BS=dr6.BS;
			_dr6.BT=dr6.BT;
			//DbgPrint("epilogue: Setting fake dr6 to %x (fake=%x)\n",*(DWORD *)&dr6, *(DWORD *)&_dr6);
		}
		

		debugger_dr6_setValue(0xffff0ff0);

		
		//set the debug registers of active breakpoints. Doesn't have to be in the specified order. Just find an unused debug registers
		//check DebuggerState.FakedDebugRegisterState[cpunumber].DR7 for unused breakpoints

		//set state to what the guest thinks it is
		debugger_dr0_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR0);
		debugger_dr1_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR1);
		debugger_dr2_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR2);
		debugger_dr3_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR3);
		debugger_dr6_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR6);

		
		
		for (breakpoint=0; breakpoint<4; breakpoint++)
		{
			
			if (DebuggerState.breakpoint[breakpoint].active)
			{
				
				int foundone=0;
			//	DbgPrint("Want to set breakpoint %d\n",breakpoint);
			
				

				//find a usable debugregister
				while ((debugregister<4) && (foundone==0))				
				{
				
					if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue==0)
					{
						DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
					}
					

					//check if this debugregister is usable
					if (((DebuggerState.FakedDebugRegisterState[cpunr()].DR7 >> (debugregister*2)) & 3)==0)  //DR7.Gx and DR7.Lx are 0
					{
					  //  DbgPrint("debugregister %d is free to be used\n",debugregister);
						foundone=1;
						
						//set address
						switch (debugregister)
						{
							case 0:	
								debugger_dr0_setValue(DebuggerState.breakpoint[breakpoint].address);
								_dr7.L0=1;
								_dr7.LEN0=DebuggerState.breakpoint[breakpoint].breakLength;
								_dr7.RW0=DebuggerState.breakpoint[breakpoint].breakType;
								break;

							case 1:
								debugger_dr1_setValue(DebuggerState.breakpoint[breakpoint].address);
								_dr7.L1=1;
								_dr7.LEN1=DebuggerState.breakpoint[breakpoint].breakLength;
								_dr7.RW1=DebuggerState.breakpoint[breakpoint].breakType;
								break;

							case 2:
								debugger_dr2_setValue(DebuggerState.breakpoint[breakpoint].address);
								_dr7.L2=1;
								_dr7.LEN2=DebuggerState.breakpoint[breakpoint].breakLength;
								_dr7.RW2=DebuggerState.breakpoint[breakpoint].breakType;
								break;

							case 3:
								debugger_dr3_setValue(DebuggerState.breakpoint[breakpoint].address);
								_dr7.L3=1;
								_dr7.LEN3=DebuggerState.breakpoint[breakpoint].breakLength;
								_dr7.RW3=DebuggerState.breakpoint[breakpoint].breakType;
								break;
						}
						

					}

					debugregister++;

				}
				
				
			}
			
			
		}
		

		debugger_dr7_setValue(_dr7);

		//DbgPrint("after:\n");

		//DbgPrint("after fake DR0=%x real DR0=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR0, debugger_dr0_getValue());
		//DbgPrint("after fake DR1=%x real DR1=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR1, debugger_dr1_getValue());
		//DbgPrint("after fake DR2=%x real DR2=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR2, debugger_dr2_getValue());
		//DbgPrint("after fake DR3=%x real DR3=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR3, debugger_dr3_getValue());
		//DbgPrint("after fake DR6=%x real DR6=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR6, debugger_dr6_getValueDword());
		//DbgPrint("after fake DR7=%x real DR7=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR7, debugger_dr7_getValueDword());

	}
	else
	{
		//not global debug, just clear all flags and be done with it
		if (handled)
			debugger_dr6_setValue(0xffff0ff0);
	
	}

	disableInterrupts();


	if (handled == 2)
	{
		//DbgPrint("handled==2\n");		
		handled = 1; //epilogue = 1 Dr handler
	}
	else
	{		
		//not handled by the epilogue set DR0, so the actual epilogue
		//DbgPrint("handled==1\n");
		
		if (DebuggerState.globalDebug)
		{
			DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=0;

			if (!DebuggerState.stoppingTheDebugger)
				debugger_dr7_setGD(DebuggerState.globalDebug); //set it back to 1, if not unloading
		}
	}
	//after=getRSP();

	//DbgPrint("before=%llx after=%llx\n",before,after);

	//DbgPrint("end of interrupt1_centry. eflags=%x", stackpointer[si_eflags]);

	//if branch tracing set lbr back on (get's disabled on debug interrupts)	
	/*
	  if (DebuggerState.storeLBR)
	    __writemsr(0x1d9, __readmsr(0x1d9) | 1);
    */
		



	return handled;
}

#ifndef AMD64
_declspec( naked ) void interrupt1_asmentry( void )
//This routine is called upon an interrupt 1, even before windows gets it
{
	__asm{
		//change the start of the stack so that instructions like setthreadcontext do not affect the stack it when it's frozen and waiting for input
		//meaning the setting of debug registers will have to be done with the changestate call

		//sub esp,4096
		//push [esp+4096+0+16] //optional ss
		//push [esp+4096+4+12] //optional esp
		//push [esp+4096+8+8] //eflags
		//push [esp+4096+12+4] //cs
		//push [esp+4096+16+0] //eip

		cld //reset the direction flag
		
		
		
		



		//save stack position
		push 0 //push an errorcode on the stack so the stackindex can stay the same
		push ebp
		mov ebp,esp

		//save state
		pushad
		xor eax,eax
		mov ax,ds
		push eax

		mov ax,es
		push eax

		mov ax,fs
		push eax

		mov ax,gs
		push eax

		//save fpu state
		//save sse state
		
		mov ax,0x23 //0x10 should work too, but even windows itself is using 0x23
		mov ds,ax
		mov es,ax
		mov gs,ax
		mov ax,0x30
		mov fs,ax

		
		

		push ebp
		call interrupt1_centry

		cmp eax,1	//set flag

		//restore state
		pop gs
		pop fs
		pop es
		pop ds
		popad

		pop ebp		

		je skip_original_int1
		
		add esp,4 //undo errorcode push (add effects eflags, so set it at both locations)

		jmp far [Int1JumpBackLocation]

skip_original_int1:
		add esp,4 //undo errorcode push
		iretd
	}
}
#endif


================================================
FILE: src/debugger.h
================================================
#ifndef DEBUGGER_H
#define DEBUGGER_H

#include <ntifs.h>
#include <windef.h>

#pragma pack(4)
typedef struct {
	UINT64 threadid;  //
	UINT64 causedbydbvm;
	UINT64 rflags;
	UINT64 rax;//
	UINT64 rbx;
	UINT64 rcx;//
	UINT64 rdx;
	UINT64 rsi;//
	UINT64 rdi;
	UINT64 rbp;//
	UINT64 rsp;
	UINT64 rip;//
	UINT64 r8;
	UINT64 r9;//
	UINT64 r10;
	UINT64 r11;//
	UINT64 r12;
	UINT64 r13;//
	UINT64 r14;
	UINT64 r15;//
	UINT64 cs;
	UINT64 ds;//
	UINT64 es;
	UINT64 fs;//
	UINT64 gs;
	UINT64 ss;//
	UINT64 dr0;
	UINT64 dr1;//
	UINT64 dr2;
	UINT64 dr3;//
	UINT64 dr6;
	UINT64 dr7;//
	BYTE fxstate[512];

	UINT64 LBR_Count;
	UINT64 LBR[16];
} DebugStackState, *PDebugStackState;
#pragma pack()

//stack index

typedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnReadsAndWrites=3} BreakType;
typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/, bl_4byte=3} BreakLength;

void debugger_initialize(void);
void debugger_shutdown(void);
int debugger_initHookForCurrentCPU(void);
int debugger_setGlobalDebugState(BOOL state);
void debugger_setStoreLBR(BOOL state);

int debugger_startDebugging(DWORD debuggedProcessID);
int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl);
int debugger_unsetGDBreakpoint(int breakpointnr);
void debugger_touchDebugRegister(UINT_PTR param);
int debugger_stopDebugging(void);
NTSTATUS debugger_waitForDebugEvent(ULONG timeout);
NTSTATUS debugger_continueDebugEvent(BOOL handled);
UINT_PTR *debugger_getLastStackPointer(void);
NTSTATUS debugger_getDebuggerState(PDebugStackState state);
NTSTATUS debugger_setDebuggerState(PDebugStackState state);

void GetDebuggerInfo(void);
VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2);

#endif

================================================
FILE: src/deepkernel.c
================================================
#pragma warning( disable: 4100 4103)

#include "deepkernel.h"
#include "DBKFunc.h"
#include <windef.h>

#include "vmxhelper.h"


BOOLEAN MakeWritableKM(PVOID StartAddress,UINT_PTR size)
{
#ifndef AMD64
	UINT_PTR PTE,PDE;
	struct PTEStruct *x;
	UINT_PTR CurrentAddress=(UINT_PTR)StartAddress;	

	while (CurrentAddress<((UINT_PTR)StartAddress+size))
	{
		//find the PTE or PDE of the selected address
		PTE=(UINT_PTR)CurrentAddress;
		PTE=PTE/0x1000*PTESize+0xc0000000;

		PTE=(UINT_PTR)StartAddress;
		PTE=PTE/0x1000*PTESize+0xc0000000;

    	//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)
	    PDE=PTE/0x1000*PTESize+0xc0000000; //same formula

		x=(PVOID)PDE;
		if ((x->P==0) && (x->A2==0))
		{
			CurrentAddress+=PAGE_SIZE_LARGE;
			continue;
		}

		if (x->PS==1)
		{
			//big page, no pte
			x->RW=1;
			CurrentAddress+=PAGE_SIZE_LARGE;
			continue;
		}

		CurrentAddress+=0x1000;
		x=(PVOID)PTE;
		if ((x->P==0) && (x->A2==0))
			continue; //see for explenation the part of the PDE

		x->RW=1;
	}

	return TRUE;
#else
	return FALSE;
Download .txt
gitextract_ndahrtj5/

├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── scripts/
│   ├── builder.js
│   ├── context.js
│   ├── multibuilder.js
│   ├── paths.js
│   └── utils.js
├── src/
│   ├── DBKDrvr.c
│   ├── DBKDrvr.h
│   ├── DBKFunc.c
│   ├── DBKFunc.h
│   ├── IOPLDispatcher.c
│   ├── IOPLDispatcher.h
│   ├── amd64/
│   │   ├── dbkfunca.asm
│   │   ├── debuggera.asm
│   │   ├── noexceptionsa.asm
│   │   ├── ultimapa.asm
│   │   ├── vmxhelpera.asm
│   │   └── vmxoffloada.asm
│   ├── debugger.c
│   ├── debugger.h
│   ├── deepkernel.c
│   ├── deepkernel.h
│   ├── extradefines.h
│   ├── extraimports.h
│   ├── interruptHook.c
│   ├── interruptHook.h
│   ├── memscan.c
│   ├── memscan.h
│   ├── noexceptions.c
│   ├── noexceptions.h
│   ├── processlist.c
│   ├── processlist.h
│   ├── segmentinfo.asm
│   ├── threads.c
│   ├── threads.h
│   ├── ultimap.c
│   ├── ultimap.h
│   ├── ultimap2/
│   │   ├── apic.c
│   │   └── apic.h
│   ├── ultimap2.c
│   ├── ultimap2.h
│   ├── vmxhelper.c
│   ├── vmxhelper.h
│   ├── vmxoffload.c
│   └── vmxoffload.h
├── templates/
│   ├── CMakeLists.txt.tpl
│   ├── chamd.inf.tpl
│   ├── driver64.dat.tpl
│   └── makecat.cdf.tpl
└── wdk/
    └── FindWDK.cmake
Download .txt
SYMBOL INDEX (314 symbols across 28 files)

FILE: scripts/context.js
  class Context (line 7) | class Context {
    method constructor (line 22) | constructor(driverName, distDir) {
    method all (line 42) | async all() {
    method purge (line 57) | async purge() {
    method purgeDir (line 67) | static async purgeDir(dir) {
    method generateCmakeFile (line 76) | async generateCmakeFile() {
    method templateToFile (line 86) | async templateToFile(src, dist, vars) {
    method compile (line 94) | async compile() {
    method createMakeCatFile (line 108) | async createMakeCatFile() {
    method makeCatFile (line 118) | async makeCatFile() {
    method signDriver (line 124) | async signDriver() {
    method execute (line 137) | async execute(cmd, cwd, params = []) {
    method createDriverDatFile (line 157) | async createDriverDatFile() {
    method install (line 167) | async install() {
    method clearBuildDir (line 190) | async clearBuildDir() {

FILE: scripts/multibuilder.js
  function getRandomWord (line 11) | async function getRandomWord() {

FILE: src/DBKDrvr.c
  type ULONG (line 45) | typedef ULONG (NTUSERSETWINDOWSHOOKEX)(
  type NTSTATUS (line 58) | typedef NTSTATUS (*ZWSUSPENDPROCESS)
  type NTSTATUS (line 81) | typedef NTSTATUS(*PSRCTNR)(__in PCREATE_THREAD_NOTIFY_ROUTINE NotifyRout...
  type NTSTATUS (line 84) | typedef NTSTATUS(*PSRLINR)(__in PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);
  function hideme (line 92) | void hideme(PDRIVER_OBJECT DriverObject)
  function testfunction (line 118) | int testfunction(int p1,int p2)
  function VOID (line 133) | VOID TestPassive(UINT_PTR param)
  function VOID (line 139) | VOID TestDPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  ...
  function NTSTATUS (line 148) | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
  function NTSTATUS (line 540) | NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,
  function NTSTATUS (line 581) | NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,
  function UnloadDriver (line 595) | void UnloadDriver(PDRIVER_OBJECT DriverObject)

FILE: src/DBKFunc.c
  function _enable (line 14) | void _enable() {}
  function _disable (line 15) | void _disable() {}
  function forEachCpuPassive (line 19) | void forEachCpuPassive(PF f, UINT_PTR param)
  function forOneCpu (line 95) | void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID Deferr...
  function forEachCpu (line 112) | void forEachCpu(PKDEFERRED_ROUTINE dpcfunction,  PVOID DeferredContext, ...
  function forEachCpuAsync (line 171) | void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredConte...
  function spinlock (line 231) | void spinlock(volatile LONG *lockvar)
  function csEnter (line 247) | void csEnter(PcriticalSection CS)
  function csLeave (line 268) | void csLeave(PcriticalSection CS)
  function getCpuCount (line 287) | int getCpuCount(void)
  function isPrefix (line 301) | int isPrefix(unsigned char b)
  function UINT64 (line 325) | UINT64 getDR7(void)
  function cpunr (line 331) | int cpunr(void)
  function EFLAGS (line 340) | EFLAGS getEflags(void)
  function UINT64 (line 347) | UINT64 readMSR(DWORD msr)
  function setCR0 (line 352) | void setCR0(UINT64 newcr0)
  function UINT64 (line 357) | UINT64 getCR0(void)
  function UINT64 (line 362) | UINT64 getCR2(void)
  function setCR3 (line 369) | void setCR3(UINT64 newCR3)
  function UINT64 (line 374) | UINT64 getCR3(void)
  function setCR4 (line 381) | void setCR4(UINT64 newcr4)
  function UINT64 (line 386) | UINT64 getCR4(void)
  function GetIDT (line 391) | void GetIDT(PIDT pIdt)
  function UINT64 (line 414) | UINT64 getTSC(void)

FILE: src/DBKFunc.h
  type VOID (line 20) | typedef VOID F(UINT_PTR param);
  type F (line 21) | typedef F *PF;
  type VOID (line 23) | typedef VOID PREDPC_CALLBACK(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID ...
  type PREDPC_CALLBACK (line 25) | typedef PREDPC_CALLBACK *PPREDPC_CALLBACK;
  type criticalSection (line 28) | typedef struct _criticalSection
  type KNORMAL_ROUTINE (line 51) | typedef KNORMAL_ROUTINE *PKNORMAL_ROUTINE;
  type KKERNEL_ROUTINE (line 67) | typedef KKERNEL_ROUTINE *PKKERNEL_ROUTINE;
  type KRUNDOWN_ROUTINE (line 80) | typedef KRUNDOWN_ROUTINE *PKRUNDOWN_ROUTINE;
  type _IRQL_requires_same_ (line 83) | typedef
  type KENUM_ROUTINE (line 93) | typedef KENUM_ROUTINE *PKENUM_ROUTINE;
  type KAPC_ENVIRONMENT (line 95) | typedef enum _KAPC_ENVIRONMENT {
  type PTEStruct (line 162) | struct PTEStruct
  type PTEStruct64 (line 183) | struct PTEStruct64
  type Debugregs (line 205) | typedef struct tagDebugregs
  type EFLAGS (line 218) | typedef struct
  type DebugReg7 (line 250) | typedef struct tagDebugReg7
  type DebugReg6 (line 283) | typedef struct DebugReg6
  type GDT (line 307) | typedef struct tagGDT

FILE: src/IOPLDispatcher.c
  type PCHAR (line 34) | typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
  function mykapc2 (line 60) | void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalCont...
  function nothing2 (line 81) | void nothing2(PVOID arg1, PVOID arg2, PVOID arg3)
  function mykapc (line 87) | void mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalConte...
  function nothing (line 126) | void nothing(PVOID arg1, PVOID arg2, PVOID arg3)
  function CreateRemoteAPC (line 132) | void CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)
  function OB_PREOP_CALLBACK_STATUS (line 174) | OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, PO...
  function VOID (line 216) | VOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_IN...
  function OB_PREOP_CALLBACK_STATUS (line 222) | OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, P...
  function VOID (line 270) | VOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_I...
  function BOOL (line 277) | BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCo...
  function NTSTATUS (line 306) | NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

FILE: src/debugger.c
  type SavedStack (line 83) | typedef struct _SavedStack
  function debugger_dr7_setGD (line 95) | void debugger_dr7_setGD(int state)
  function debugger_dr0_setValue (line 105) | void debugger_dr0_setValue(UINT_PTR value)
  function UINT_PTR (line 110) | UINT_PTR debugger_dr0_getValue(void)
  function debugger_dr1_setValue (line 115) | void debugger_dr1_setValue(UINT_PTR value)
  function UINT_PTR (line 120) | UINT_PTR debugger_dr1_getValue(void)
  function debugger_dr2_setValue (line 125) | void debugger_dr2_setValue(UINT_PTR value)
  function UINT_PTR (line 130) | UINT_PTR debugger_dr2_getValue(void)
  function debugger_dr3_setValue (line 135) | void debugger_dr3_setValue(UINT_PTR value)
  function UINT_PTR (line 140) | UINT_PTR debugger_dr3_getValue(void)
  function debugger_dr6_setValue (line 145) | void debugger_dr6_setValue(UINT_PTR value)
  function debugger_dr7_setValue (line 150) | void debugger_dr7_setValue(DebugReg7 value)
  function debugger_dr7_setValueDword (line 156) | void debugger_dr7_setValueDword(UINT_PTR value)
  function UINT_PTR (line 161) | UINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just...
  function DebugReg7 (line 167) | DebugReg7 debugger_dr7_getValue(void)
  function UINT_PTR (line 173) | UINT_PTR debugger_dr6_getValueDword(void)
  function DebugReg6 (line 178) | DebugReg6 debugger_dr6_getValue(void)
  function debugger_touchDebugRegister (line 186) | void debugger_touchDebugRegister(UINT_PTR param)
  function debugger_initialize (line 195) | void debugger_initialize(void)
  function debugger_shutdown (line 219) | void debugger_shutdown(void)
  function debugger_growstack (line 238) | void debugger_growstack()
  function debugger_setInitialFakeState (line 283) | void debugger_setInitialFakeState(void)
  function VOID (line 294) | VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID  ...
  function debugger_removeHookForCurrentCPU (line 299) | int debugger_removeHookForCurrentCPU(UINT_PTR params)
  function debugger_initHookForCurrentCPU (line 305) | int debugger_initHookForCurrentCPU(void)
  function debugger_setStoreLBR (line 346) | void debugger_setStoreLBR(BOOL state)
  function debugger_setGlobalDebugState (line 388) | int debugger_setGlobalDebugState(BOOL state)
  function debugger_startDebugging (line 420) | int debugger_startDebugging(DWORD debuggedProcessID)
  function debugger_stopDebugging (line 439) | int debugger_stopDebugging(void)
  function debugger_unsetGDBreakpoint (line 470) | int debugger_unsetGDBreakpoint(int breakpointnr)
  function debugger_setGDBreakpoint (line 477) | int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakT...
  function NTSTATUS (line 490) | NTSTATUS debugger_waitForDebugEvent(ULONG timeout)
  function NTSTATUS (line 513) | NTSTATUS debugger_continueDebugEvent(BOOL handled)
  function UINT_PTR (line 526) | UINT_PTR *debugger_getLastStackPointer(void)
  function NTSTATUS (line 533) | NTSTATUS debugger_getDebuggerState(PDebugStackState state)
  function NTSTATUS (line 628) | NTSTATUS debugger_setDebuggerState(PDebugStackState state)
  function breakpointHandler_kernel (line 706) | int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentde...
  function interrupt1_handler (line 836) | int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
  function interrupt1_centry (line 1494) | int interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-...
  function interrupt1_asmentry (line 1762) | _declspec( naked ) void interrupt1_asmentry( void )

FILE: src/debugger.h
  type DebugStackState (line 8) | typedef struct {
  type BreakType (line 50) | typedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnRe...
  type BreakLength (line 51) | typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/,...

FILE: src/deepkernel.c
  function BOOLEAN (line 10) | BOOLEAN MakeWritableKM(PVOID StartAddress,UINT_PTR size)
  function BOOLEAN (line 58) | BOOLEAN MakeWritable(PVOID StartAddress,UINT_PTR size,BOOLEAN usecopyonw...
  function BOOLEAN (line 102) | BOOLEAN CheckImageName(IN PUNICODE_STRING FullImageName, IN char* List,i...
  function VOID (line 161) | VOID LoadImageNotifyRoutine(IN PUNICODE_STRING  FullImageName, IN HANDLE...

FILE: src/interruptHook.c
  function WORD (line 21) | WORD inthook_getOriginalCS(unsigned char intnr)
  function ULONG_PTR (line 26) | ULONG_PTR inthook_getOriginalEIP(unsigned char intnr)
  function inthook_isHooked (line 31) | int inthook_isHooked(unsigned char intnr)
  function inthook_isDBVMHook (line 40) | int inthook_isDBVMHook(unsigned char intnr)
  function inthook_UnhookInterrupt (line 45) | int inthook_UnhookInterrupt(unsigned char intnr)
  function inthook_HookInterrupt (line 105) | int inthook_HookInterrupt(unsigned char intnr, int newCS, ULONG_PTR newE...

FILE: src/interruptHook.h
  type stackindex (line 8) | typedef enum {si_eax=0, si_ebx=1, si_ecx=2, si_edx=3, si_esi=4, si_edi=5...
  type stackindex (line 10) | typedef enum {si_gs=-12, si_fs=-11, si_es=-10, si_ds=-9, si_edi=-8, si_e...
  type INT_VECTOR (line 16) | typedef struct tagINT_VECTOR
  type IDT (line 39) | typedef struct tagIDT

FILE: src/memscan.c
  function VirtualAddressToIndexes (line 20) | void VirtualAddressToIndexes(QWORD address, int *pml4index, int *pagedir...
  function QWORD (line 41) | QWORD IndexesToVirtualAddress(int pml4index, int pagedirptrindex, int pa...
  function VirtualAddressToPageEntries32 (line 74) | void VirtualAddressToPageEntries32(DWORD address, PPDE *pagedirentry, PP...
  function VirtualAddressToPageEntries64 (line 92) | void VirtualAddressToPageEntries64(QWORD address, PPDPTE_PAE *pml4entry,...
  function BOOLEAN (line 136) | BOOLEAN IsAddressSafe(UINT_PTR StartAddress)
  function UINT_PTR (line 250) | UINT_PTR getPEThread(UINT_PTR threadid)
  function BOOLEAN (line 267) | BOOLEAN WriteProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,D...
  function BOOLEAN (line 381) | BOOLEAN ReadProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DW...
  function UINT64 (line 476) | UINT64 getMaxPhysAddress(void)
  function NTSTATUS (line 496) | NTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, vo...
  function UINT_PTR (line 608) | UINT_PTR SignExtend(UINT_PTR a)
  function UINT_PTR (line 621) | UINT_PTR getPageTableBase()
  type PTEStruct (line 661) | struct PTEStruct
  function BOOL (line 662) | BOOL walkPagingLayout(PEPROCESS PEProcess, UINT_PTR MaxAddress, PRESENTP...
  function CleanAccessedList (line 785) | void CleanAccessedList()
  function StoreAccessedRanges (line 803) | void StoreAccessedRanges(UINT_PTR StartAddress, UINT_PTR EndAddress, str...
  function enumAllAccessedPages (line 827) | int enumAllAccessedPages(PEPROCESS PEProcess)
  function getAccessedPageList (line 846) | int getAccessedPageList(PPRANGE List, int ListSizeInBytes)
  function MarkPageAsNotAccessed (line 875) | void MarkPageAsNotAccessed(UINT_PTR StartAddress, UINT_PTR EndAddress, s...
  function NTSTATUS (line 880) | NTSTATUS markAllPagesAsNeverAccessed(PEPROCESS PEProcess)
  function BOOLEAN (line 1280) | BOOLEAN GetMemoryRegionData(DWORD PID,PEPROCESS PEProcess, PVOID mempoin...

FILE: src/memscan.h
  type ADDRESSENTRY (line 10) | typedef struct _ADDRESSENTRY {
  type MEMREGION (line 17) | typedef struct _MEMREGION //only holds regions that are allowed
  type MEMSCANOPTIONS (line 24) | typedef struct _MEMSCANOPTIONS
  type SCANDATA (line 38) | typedef struct _SCANDATA {
  type PRANGE (line 53) | typedef struct
  type PENTRY (line 59) | typedef struct

FILE: src/noexceptions.c
  function KeQueryActiveProcessorCount (line 17) | int KeQueryActiveProcessorCount(PVOID x)
  function BOOL (line 34) | BOOL NoExceptions_Enter()
  function NoExceptions_CopyMemory (line 158) | int NoExceptions_CopyMemory(PVOID Destination, PVOID Source, int size)
  function NoExceptions_Leave (line 185) | void NoExceptions_Leave()
  function NoExceptions_Cleanup (line 202) | void NoExceptions_Cleanup()

FILE: src/noexceptions.h
  type CPUSTATE (line 15) | typedef struct

FILE: src/processlist.c
  function RTL_GENERIC_COMPARE_RESULTS (line 17) | RTL_GENERIC_COMPARE_RESULTS NTAPI ProcessListCompare(__in struct _RTL_GE...
  function PVOID (line 32) | PVOID NTAPI ProcessListAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in...
  function VOID (line 41) | VOID NTAPI ProcessListDealloc(__in struct _RTL_GENERIC_TABLE *Table, __i...
  function VOID (line 48) | VOID GetThreadData(IN PDEVICE_OBJECT  DeviceObject, IN PVOID  Context)
  function VOID (line 94) | VOID CreateThreadNotifyRoutine(IN HANDLE  ProcessId,IN HANDLE  ThreadId,...
  function VOID (line 127) | VOID CreateProcessNotifyRoutine(IN HANDLE  ParentId, IN HANDLE  ProcessI...
  function VOID (line 372) | VOID CreateProcessNotifyRoutineEx(IN HANDLE  ParentId, IN HANDLE  Proces...
  function HANDLE (line 378) | HANDLE GetHandleForProcessID(IN HANDLE ProcessID)
  function VOID (line 396) | VOID CleanProcessList()

FILE: src/processlist.h
  type ThreadData (line 9) | struct ThreadData
  type ProcessListData (line 20) | typedef struct
  type ProcessData (line 29) | struct ProcessData
  type ProcessEventdta (line 38) | typedef struct tagProcessEventData
  type ThreadEventDta (line 54) | typedef struct tagThreadEventData

FILE: src/threads.c
  type ThreadData (line 16) | struct ThreadData
  type ProcessData (line 18) | struct ProcessData
  type ThreadData (line 19) | struct ThreadData
  function Ignore (line 40) | void Ignore(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalConte...
  function SuspendThreadAPCRoutine (line 46) | void SuspendThreadAPCRoutine(PVOID arg1, PVOID arg2, PVOID arg3)
  function DBKSuspendThread (line 65) | void DBKSuspendThread(ULONG ThreadID)
  function DBKResumeThread (line 111) | void DBKResumeThread(ULONG ThreadID)
  function DBKSuspendProcess (line 142) | void DBKSuspendProcess(ULONG ProcessID)
  function DBKResumeProcess (line 206) | void DBKResumeProcess(ULONG ProcessID)

FILE: src/ultimap.c
  type _DataBlock (line 37) | typedef struct
  function ultimap_flushBuffers_all (line 77) | void ultimap_flushBuffers_all(UINT_PTR param)
  function ultimap_flushBuffers (line 87) | void ultimap_flushBuffers(void)
  function NTSTATUS (line 115) | NTSTATUS ultimap_continue(PULTIMAPDATAEVENT data)
  function NTSTATUS (line 136) | NTSTATUS ultimap_waitForData(ULONG timeout, PULTIMAPDATAEVENT data)
  function ultimap_cleanstate (line 218) | void ultimap_cleanstate()
  function perfmon_interrupt_centry (line 223) | int perfmon_interrupt_centry(void)
  function ultimap_pause (line 417) | void ultimap_pause(void)
  function VOID (line 422) | VOID ultimap_resume_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, ...
  function ultimap_resume (line 427) | void ultimap_resume(void)
  function VOID (line 432) | VOID ultimap_disable_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext,...
  function ultimap_disable (line 451) | void ultimap_disable(void)
  function VOID (line 493) | VOID ultimap_setup_dpc(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, ...
  function ultimapapc (line 585) | void ultimapapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalC...
  function ultimapapcnormal (line 594) | void ultimapapcnormal(PVOID arg1, PVOID arg2, PVOID arg3)
  function perfmon_hook (line 608) | void perfmon_hook(__in struct _KINTERRUPT *Interrupt, __in PVOID Service...
  function NTSTATUS (line 653) | NTSTATUS ultimap(UINT64 cr3, UINT64 dbgctl_msr, int _DS_AREA_SIZE, BOOL ...

FILE: src/ultimap.h
  type UINT64 (line 7) | typedef UINT64 QWORD;
  type DS_AREA_MANAGEMENT64 (line 28) | typedef struct
  type BTS (line 44) | typedef struct
  type DS_AREA_MANAGEMENT64 (line 54) | typedef DS_AREA_MANAGEMENT64 DS_AREA_MANAGEMENT;
  type PDS_AREA_MANAGEMENT64 (line 55) | typedef PDS_AREA_MANAGEMENT64 PDS_AREA_MANAGEMENT;
  type ULTIMAPEVENT (line 61) | typedef struct
  type ULTIMAPDATAEVENT (line 67) | typedef struct

FILE: src/ultimap2.c
  function KeQueryMaximumProcessorCount (line 42) | unsigned int KeQueryMaximumProcessorCount()
  type ProcessorInfo (line 63) | typedef struct
  function suspendThread (line 115) | void suspendThread(PVOID StartContext)
  function NTSTATUS (line 147) | NTSTATUS ultimap2_continue(int cpunr)
  function NTSTATUS (line 179) | NTSTATUS ultimap2_waitForData(ULONG timeout, PULTIMAP2DATAEVENT data)
  function createUltimap2OutputFile (line 263) | void createUltimap2OutputFile(int cpunr)
  function WriteThreadForSpecificCPU (line 297) | void WriteThreadForSpecificCPU(PVOID StartContext)
  function ultimap2_LockFile (line 408) | void ultimap2_LockFile(int cpunr)
  function ultimap2_ReleaseFile (line 432) | void ultimap2_ReleaseFile(int cpunr)
  function UINT64 (line 445) | UINT64 ultimap2_GetTraceFileSize()
  function ultimap2_ResetTraceFileSize (line 460) | void ultimap2_ResetTraceFileSize()
  function SwitchToPABuffer (line 471) | void SwitchToPABuffer(struct _KDPC *Dpc, PVOID DeferredContext, PVOID Sy...
  function WaitForWriteToFinishAndSwapWriteBuffers (line 586) | void WaitForWriteToFinishAndSwapWriteBuffers(BOOL interruptedOnly)
  function bufferWriterThread (line 607) | void bufferWriterThread(PVOID StartContext)
  function NTSTATUS (line 713) | NTSTATUS ultimap2_flushBuffers()
  function RTIT_DPC_Handler (line 758) | void RTIT_DPC_Handler(__in struct _KDPC *Dpc, __in_opt PVOID DeferredCon...
  function PMI (line 766) | void PMI(__in struct _KINTERRUPT *Interrupt, __in PVOID ServiceContext)
  function ultimap2_disable_dpc (line 816) | void ultimap2_disable_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOI...
  function ultimap2_setup_dpc (line 848) | void ultimap2_setup_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOID ...
  function getToPAHeaderCount (line 974) | int getToPAHeaderCount(ULONG _BufferSize)
  function getToPAHeaderSize (line 979) | int getToPAHeaderSize(ULONG _BufferSize)
  function RTL_GENERIC_COMPARE_RESULTS (line 986) | RTL_GENERIC_COMPARE_RESULTS NTAPI ToPACompare(__in struct _RTL_GENERIC_T...
  function PVOID (line 1001) | PVOID NTAPI ToPAAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in CLONG ...
  function VOID (line 1006) | VOID NTAPI ToPADealloc(__in struct _RTL_GENERIC_TABLE *Table, __in __drv...
  function NTSTATUS (line 1297) | NTSTATUS ultimap2_pause()
  function NTSTATUS (line 1314) | NTSTATUS ultimap2_resume()
  function SetupUltimap2 (line 1326) | void SetupUltimap2(UINT32 PID, UINT32 BufferSize, WCHAR *Path, int range...
  function UnregisterUltimapPMI (line 1533) | void UnregisterUltimapPMI()
  function DisableUltimap2 (line 1562) | void DisableUltimap2(void)

FILE: src/ultimap2.h
  type URANGE (line 26) | typedef struct
  type RTIT_CTL (line 35) | typedef union {
  type RTIT_STATUS (line 67) | typedef union {
  type ToPA_ENTRY (line 80) | typedef union {
  type ToPA_LOOKUP (line 95) | typedef struct{
  type ULTIMAP2DATAEVENT (line 100) | typedef struct
  type NTSTATUS (line 125) | typedef NTSTATUS(*PSSUSPENDPROCESS)(PEPROCESS p);

FILE: src/ultimap2/apic.c
  function apic_clearPerfmon (line 18) | void apic_clearPerfmon()
  function setup_APIC_BASE (line 42) | void setup_APIC_BASE(void)
  function clean_APIC_BASE (line 62) | void clean_APIC_BASE(void)

FILE: src/ultimap2/apic.h
  type UINT128 (line 7) | typedef struct {
  type APIC (line 14) | typedef volatile struct {

FILE: src/vmxhelper.c
  function vmx_hasredirectedint1 (line 50) | int vmx_hasredirectedint1()
  function vmx_getversion (line 65) | unsigned int vmx_getversion()
  function vmx_getRealCR0 (line 86) | unsigned int vmx_getRealCR0()
  function UINT_PTR (line 102) | UINT_PTR vmx_getRealCR3()
  function vmx_getRealCR4 (line 118) | unsigned int vmx_getRealCR4()
  function vmx_redirect_interrupt1 (line 134) | unsigned int vmx_redirect_interrupt1(VMXInterruptRedirectType redirectty...
  function vmx_redirect_interrupt3 (line 161) | unsigned int vmx_redirect_interrupt3(VMXInterruptRedirectType redirectty...
  function vmx_redirect_interrupt14 (line 189) | unsigned int vmx_redirect_interrupt14(VMXInterruptRedirectType redirectt...
  function vmx_register_cr3_callback (line 216) | unsigned int vmx_register_cr3_callback(unsigned int cs, unsigned int eip...
  function vmx_exit_cr3_callback (line 244) | unsigned int vmx_exit_cr3_callback(unsigned int newcr3)
  function vmx_watch_pagewrites (line 267) | unsigned int vmx_watch_pagewrites(UINT64 PhysicalAddress, int Size, int ...
  function vmx_watch_pageaccess (line 306) | unsigned int vmx_watch_pageaccess(UINT64 PhysicalAddress, int Size, int ...
  function vmx_watch_retreivelog (line 345) | unsigned int vmx_watch_retreivelog(int ID, PPageEventListDescriptor resu...
  function vmx_watch_delete (line 376) | unsigned int vmx_watch_delete(int ID)
  function vmx_cloak_activate (line 398) | unsigned int vmx_cloak_activate(QWORD physicalPage)
  function vmx_cloak_deactivate (line 437) | unsigned int vmx_cloak_deactivate(QWORD physicalPage)
  function vmx_cloak_readOriginal (line 457) | unsigned int vmx_cloak_readOriginal(QWORD physicalPage, void *destination)
  function vmx_cloak_writeOriginal (line 482) | unsigned int vmx_cloak_writeOriginal(QWORD physicalPage, void *source)
  function vmx_changeregonbp (line 507) | unsigned int vmx_changeregonbp(QWORD physicalAddress, CHANGEREGONBPINFO ...
  function vmx_ultimap_getDebugInfo (line 540) | unsigned int vmx_ultimap_getDebugInfo(PULTIMAPDEBUGINFO debuginfo)
  function vmx_ultimap (line 564) | unsigned int vmx_ultimap(UINT_PTR cr3towatch, UINT64 debugctl_value, voi...
  function vmx_ultimap_disable (line 591) | unsigned int vmx_ultimap_disable()
  function vmx_ultimap_pause (line 609) | unsigned int vmx_ultimap_pause()
  function vmx_ultimap_resume (line 627) | unsigned int vmx_ultimap_resume()
  function vmx_disable_dataPageFaults (line 645) | unsigned int vmx_disable_dataPageFaults()
  function vmx_enable_dataPageFaults (line 663) | unsigned int vmx_enable_dataPageFaults()
  function UINT_PTR (line 681) | UINT_PTR vmx_getLastSkippedPageFault()
  function vmx_add_memory (line 699) | unsigned int vmx_add_memory(UINT64 *list, int count)
  function vmx_causedCurrentDebugBreak (line 754) | int vmx_causedCurrentDebugBreak()
  function vmx_init_dovmcall (line 772) | void vmx_init_dovmcall(int isIntel)

FILE: src/vmxhelper.h
  type UINT64 (line 66) | typedef UINT64 QWORD;
  type CHANGEREGONBPINFO (line 68) | typedef struct _CHANGEREGONBPINFO
  type PageEventBasic (line 124) | typedef struct _pageevent_basic
  type FXSAVE64 (line 158) | typedef struct _fxsave64
  type PageEventExtended (line 231) | typedef struct _pageevent_extended
  type PageEventBasicWithStack (line 237) | typedef struct _pageevent_basic_withstack
  type PageEventExtendedWithStack (line 243) | typedef struct _pageevent_extended_withstack
  type PageEventListDescriptor (line 250) | typedef struct _pageeventlistdescriptor
  type VMXInterruptRedirectType (line 268) | typedef enum {virt_differentInterrupt=0, virt_emulateInterrupt=1} VMXInt...
  type ULTIMAPDEBUGINFO (line 270) | typedef struct

FILE: src/vmxoffload.c
  type INITVARS (line 35) | typedef struct _INITVARS
  type OriginalState (line 48) | typedef struct
  function cleanupDBVM (line 223) | void cleanupDBVM() {
  function initializeDBVM (line 266) | void initializeDBVM(PCWSTR dbvmimgpath)
  function vmxoffload_override (line 963) | void vmxoffload_override(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID Defe...
  function __drv_maxIRQL (line 1002) | __drv_functionClass(KDEFERRED_ROUTINE)

FILE: src/vmxoffload.h
  type DBVMOffloadMemInfo (line 17) | typedef struct _DBVMOffloadMemInfo
  type _PTE (line 24) | struct _PTE
  type _PDE (line 41) | struct _PDE
  type _PDE2MB (line 58) | struct _PDE2MB
  type PTE_PAE (line 77) | typedef struct _PTE_PAE
  type PDE_PAE (line 95) | typedef struct _PDE_PAE
  type _PDE2MB_PAE (line 113) | struct _PDE2MB_PAE
  type _PDPTE_PAE (line 134) | struct _PDPTE_PAE
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (458K chars).
[
  {
    "path": ".editorconfig",
    "chars": 130,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\ninsert_final_newli"
  },
  {
    "path": ".gitignore",
    "chars": 61,
    "preview": "build\n.cache\n.env\nnode_modules\nsrc/CMakeLists.txt\ndist\ndists\n"
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2021 Dmitry Marov\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "README.md",
    "chars": 9509,
    "preview": "# Chamd (Chameleon DBK64)\n\n## Modified Driver Based on Cheat Engine DBK64\n\nThis project provides a modified version of t"
  },
  {
    "path": "package.json",
    "chars": 591,
    "preview": "{\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"dotenv\": \"^10.0.0\",\n    \"handlebars\": \"^4.7.7\"\n  },\n  \"scripts\": {\n    \"a"
  },
  {
    "path": "scripts/builder.js",
    "chars": 962,
    "preview": "import dotenv from 'dotenv';\nimport Context from './context.js';\nimport generateRandomName from './utils.js';\nimport pat"
  },
  {
    "path": "scripts/context.js",
    "chars": 6258,
    "preview": "import path from 'path';\nimport fs from 'fs';\nimport handlebars from 'handlebars';\nimport { spawn } from 'child_process'"
  },
  {
    "path": "scripts/multibuilder.js",
    "chars": 1429,
    "preview": "import Context from './context.js';\nimport generateRandomName from './utils.js';\nimport path from 'path';\nimport http fr"
  },
  {
    "path": "scripts/paths.js",
    "chars": 166,
    "preview": "import path from 'path';\nimport { fileURLToPath } from 'url';\nconst __filename = fileURLToPath(import.meta.url);\n\nexport"
  },
  {
    "path": "scripts/utils.js",
    "chars": 302,
    "preview": "export default (length) => {\n    let result = '';\n    const characters = 'abcdefghijklmnopqrstuvwxyz';\n    const charact"
  },
  {
    "path": "src/DBKDrvr.c",
    "chars": 15368,
    "preview": "#pragma warning( disable: 4100 4101 4103 4189)\n\n#include \"DBKFunc.h\"\n#include <ntifs.h>\n#include <windef.h>\n#include \"DB"
  },
  {
    "path": "src/DBKDrvr.h",
    "chars": 74,
    "preview": "#ifndef DBKDRVR_H\n#define DBKDRVR_H\n\n\n\n#define dbkversion 2000027\n\n\n#endif"
  },
  {
    "path": "src/DBKFunc.c",
    "chars": 8640,
    "preview": "#pragma warning( disable: 4103)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include \"DBKFunc.h\"\n\n/*\n#include \"vmxhelper.h\"\n#"
  },
  {
    "path": "src/DBKFunc.h",
    "chars": 9563,
    "preview": "#ifndef DBKFUNC_H\n#define DBKFUNC_H\n\n#pragma warning( disable: 4214 )\n\n#include <ntifs.h>\n#include <ntstrsafe.h>\n\n#inclu"
  },
  {
    "path": "src/IOPLDispatcher.c",
    "chars": 58597,
    "preview": "#pragma warning( disable: 4100 4101 4103 4189)\n\n\n#include \"IOPLDispatcher.h\"\n#include \"DBKFunc.h\"\n#include \"DBKDrvr.h\"\n\n"
  },
  {
    "path": "src/IOPLDispatcher.h",
    "chars": 12977,
    "preview": "#ifndef IOPLDISPACTCHER_H\n#define IOPLDISPACTCHER_H\n\n#include \"DBKfunc.h\"\n\n#define IOCTL_UNKNOWN_BASE\t\t\t\t\tFILE_DEVICE_UN"
  },
  {
    "path": "src/amd64/dbkfunca.asm",
    "chars": 1613,
    "preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n;I should pro"
  },
  {
    "path": "src/amd64/debuggera.asm",
    "chars": 5109,
    "preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK     "
  },
  {
    "path": "src/amd64/noexceptionsa.asm",
    "chars": 1137,
    "preview": "_TEXT SEGMENT 'CODE'\n\nPUBLIC NoException14\nNoException14:\n\n;Security cookies sucks, so getjmp/longjmp are not usable\n;So"
  },
  {
    "path": "src/amd64/ultimapa.asm",
    "chars": 4884,
    "preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK     "
  },
  {
    "path": "src/amd64/vmxhelpera.asm",
    "chars": 520,
    "preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n\n;vmcall:  rd"
  },
  {
    "path": "src/amd64/vmxoffloada.asm",
    "chars": 5477,
    "preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nGDTDesc\tSTRUC"
  },
  {
    "path": "src/debugger.c",
    "chars": 49540,
    "preview": "/*\ndebugger.c:\nThis unit will handle all debugging related code, from hooking, to handling interrupts\n\ntodo: this whole "
  },
  {
    "path": "src/debugger.h",
    "chars": 1820,
    "preview": "#ifndef DEBUGGER_H\n#define DEBUGGER_H\n\n#include <ntifs.h>\n#include <windef.h>\n\n#pragma pack(4)\ntypedef struct {\n\tUINT64 "
  },
  {
    "path": "src/deepkernel.c",
    "chars": 3591,
    "preview": "#pragma warning( disable: 4100 4103)\n\n#include \"deepkernel.h\"\n#include \"DBKFunc.h\"\n#include <windef.h>\n\n#include \"vmxhel"
  },
  {
    "path": "src/deepkernel.h",
    "chars": 426,
    "preview": "#include <ntifs.h>\n#include <windef.h>\n\n\nVOID LoadImageNotifyRoutine(IN PUNICODE_STRING  FullImageName, IN HANDLE  Proce"
  },
  {
    "path": "src/extradefines.h",
    "chars": 587,
    "preview": "/*#define HDESK\t\t\t\t\t\t\tULONG\n#define HWND\t\t\t\t\t\t\tULONG\n#define DWORD\t\t\t\t\t\t\tULONG\n#define WORD\t\t\t\t\t\t\tUSHORT\n#define BYTE\t\t\t"
  },
  {
    "path": "src/extraimports.h",
    "chars": 166,
    "preview": "NTSYSAPI\nBOOLEAN\nKeAddSystemServiceTable(\n    IN PULONG_PTR Base,\n    IN PULONG Count OPTIONAL,\n    IN ULONG Limit,\n    "
  },
  {
    "path": "src/interruptHook.c",
    "chars": 4861,
    "preview": "#pragma warning( disable: 4103)\n\n#include \"ntifs.h\"\n#include <windef.h>\n\n#include \"DBKFunc.h\"\n#include \"vmxhelper.h\"\n\n#i"
  },
  {
    "path": "src/interruptHook.h",
    "chars": 2075,
    "preview": "#ifndef INTERRUPTHOOK_H\n#define INTERRUPTHOOK_H\n\n#include <windef.h>\n\n//assuming the standard interrupt hook routine is "
  },
  {
    "path": "src/memscan.c",
    "chars": 30132,
    "preview": "#pragma warning( disable: 4100 4103 4146 4213)\n\n#include \"ntifs.h\"\n#include <windef.h>\n#ifdef CETC\n#include \"tdiwrapper."
  },
  {
    "path": "src/memscan.h",
    "chars": 2966,
    "preview": "#include <windef.h>\n\n#ifdef AMD64\n#define PAGETABLEBASE 0xfffff68000000000ULL\n//win10 1607 it's random\n#else\n#define PAG"
  },
  {
    "path": "src/noexceptions.c",
    "chars": 4409,
    "preview": "#include \"noexceptions.h\"\n\nint MaxCPUCount;\n\n\nPCPUSTATE cpustate = NULL;\n\n#ifdef AMD64\nextern void NoException14(void); "
  },
  {
    "path": "src/noexceptions.h",
    "chars": 672,
    "preview": "#ifndef NOEXCEPTIONS_H\n#define NOEXCEPTIONS_H\n\n/*\nWill be responsible for temporarily switching out the IDT of the curen"
  },
  {
    "path": "src/processlist.c",
    "chars": 10405,
    "preview": "#pragma warning( disable: 4100 4103 4706)\n\n#include \"ntifs.h\"\n#include \"processlist.h\"\n#include \"threads.h\"\n#include \"me"
  },
  {
    "path": "src/processlist.h",
    "chars": 1624,
    "preview": "#include <ntifs.h>\n#include \"extradefines.h\"\n#include \"extraimports.h\"\n\n\nVOID CreateProcessNotifyRoutine(IN HANDLE Paren"
  },
  {
    "path": "src/segmentinfo.asm",
    "chars": 570,
    "preview": "_TEXT SEGMENT 'CODE'\n\nPUBLIC _getAccessRights@8\t\t\t\t\t\t\t\t\t\t\n_getAccessRights@8:\n  push ebp\n  mov ebp,esp\n  \n  push ecx\n  m"
  },
  {
    "path": "src/threads.c",
    "chars": 5546,
    "preview": "#pragma warning( disable: 4100 4103)\n\n#include \"threads.h\"\n#include \"processlist.h\"\n#include \"memscan.h\"\n\n/*\nNTSTATUS NT"
  },
  {
    "path": "src/threads.h",
    "chars": 548,
    "preview": "#ifndef THREADS_H\n#define THREADS_H\n\n\n#include <ntifs.h>\n#include <windef.h>\n#include \"DBKFunc.h\"\n\n\nvoid Ignore(PKAPC Ap"
  },
  {
    "path": "src/ultimap.c",
    "chars": 17822,
    "preview": "/*\nUltimap implements the recording of all the branches in the target process\nRequires dbvm for process selection\n*/\n\n#p"
  },
  {
    "path": "src/ultimap.h",
    "chars": 2075,
    "preview": "#ifndef ULTIMAP_H\n#define ULTIMAP_H\n\n#include <ntifs.h>\n#include <windef.h>\n\ntypedef UINT64 QWORD;\n\n#pragma pack(push)\n#"
  },
  {
    "path": "src/ultimap2/apic.c",
    "chars": 1849,
    "preview": "#include <ntifs.h>\n\n#include \"apic.h\"\n#include <ntddk.h>\n#include \"..\\DBKFunc.h\"\n\n\n#define MSR_IA32_APICBASE            "
  },
  {
    "path": "src/ultimap2/apic.h",
    "chars": 1159,
    "preview": "#ifndef apic_h\n#define apic_h\n\n#include <ntddk.h>\n#include <windef.h>\n\ntypedef struct {\n\tDWORD a;\n\tDWORD b;\n\tDWORD c;\n\tD"
  },
  {
    "path": "src/ultimap2.c",
    "chars": 41425,
    "preview": "#pragma warning( disable: 4100 4706)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include <minwindef.h>\n#include <wdm.h>\n#inc"
  },
  {
    "path": "src/ultimap2.h",
    "chars": 2920,
    "preview": "#ifndef ULTIMAP2_H\n#define ULTIMAP2_H\n\n#include <ntifs.h>\n\n//MSR's\n#define IA32_PERF_GLOBAL_STATUS\t\t0x38e  \n#define IA32"
  },
  {
    "path": "src/vmxhelper.c",
    "chars": 20743,
    "preview": "#pragma warning( disable: 4100 4103 4213)\n#include <ntifs.h>\n#include <ntddk.h>\n#include <windef.h>\n#include \"vmxhelper."
  },
  {
    "path": "src/vmxhelper.h",
    "chars": 7348,
    "preview": "#ifndef VMXHELPER_H\n#define VMXHELPER_H\n\n#pragma warning( disable: 4200)\n\n#define VMCALL_GETVERSION 0\n#define VMCALL_CHA"
  },
  {
    "path": "src/vmxoffload.c",
    "chars": 28174,
    "preview": "/*\nsets up all the needed data structures \ncopies dbvm into physical memory\njumps into dbvm's os entry point\n\n*/\n#pragma"
  },
  {
    "path": "src/vmxoffload.h",
    "chars": 5802,
    "preview": "#ifndef VMXOFFLOAD_H\n#define VMXOFFLOAD_H\n\nvoid cleanupDBVM();\nvoid initializeDBVM(PCWSTR dbvmimgpath);\nvoid vmxoffload("
  },
  {
    "path": "templates/CMakeLists.txt.tpl",
    "chars": 1806,
    "preview": "cmake_minimum_required(VERSION 3.18.0)\nproject({{DRIVER_NAME}} VERSION 1.0.0)\n\nenable_language(C ASM_MASM)\n\nlist(APPEND "
  },
  {
    "path": "templates/chamd.inf.tpl",
    "chars": 2410,
    "preview": ";\n; {{DRIVER_NAME}}.inf\n;\n\n[Version]\nSignature=\"$WINDOWS NT$\"\nClass=Sample ; TODO: edit Class\nClassGuid={78A1C341-4539-1"
  },
  {
    "path": "templates/driver64.dat.tpl",
    "chars": 66,
    "preview": "fgfgfgfh\nfghcghfhg\nfvfghfbg\n{{DRIVER_NAME}}.sys\n76543210\nfedcba98\n"
  },
  {
    "path": "templates/makecat.cdf.tpl",
    "chars": 169,
    "preview": "[CatalogHeader]\nName={{DRIVER_NAME}}.cat\nPublicVersion=0x0000001\nEncodingType=0x00010001\nCATATTR1=0x10010001:OSAttr:2:6."
  },
  {
    "path": "wdk/FindWDK.cmake",
    "chars": 8507,
    "preview": "# Redistribution and use is allowed under the OSI-approved 3-clause BSD license.\n# Copyright (c) 2018 Sergey Podobry (se"
  }
]

About this extraction

This page contains the full source code of the dmarov/chamd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (397.1 KB), approximately 126.1k tokens, and a symbol index with 314 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!