[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": ".gitignore",
    "content": "build\n.cache\n.env\nnode_modules\nsrc/CMakeLists.txt\ndist\ndists\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Dmitry Marov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Chamd (Chameleon DBK64)\n\n## Modified Driver Based on Cheat Engine DBK64\n\nThis project provides a modified version of the Cheat Engine DBK64 kernel driver aimed at bypassing detection by anti-cheat systems.\nIt has been tested with EAC and BattlEye, potentially working with other systems as well.\n\nCurrent version is based on Cheat Engine version 7.5\n\n![screen](images/screen.png \"Screen\")\n*As shown below, the driver successfully bypasses EAC detection in Robocraft.*\n\n## 0. Important Warning\n\nEven if you manage to use this driver successfully, it does not guarantee that you will not be suspected of cheating.\nThe usage of this software and any actions outlined in this document are entirely at your own risk.\n\nPlease note that using these instructions **poses a significant security risk** to your system.\nIt is highly recommended to use an isolated computer for this purpose. Additionally, isolating the machine within a local network may further enhance security.\n\n## 1. System Requirements and Preparation\n- **Operating System**: Windows 11 only. This method will not work on Windows 10.\n- **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\n- 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).\n\n## 2. Obtain your driver\n\n2.1. **Download the Compiled Driver**\nVisit [GitHub](https://github.com/dmarov/chamd/releases/tag/v1.4) to download the compiled driver, which includes a multibuild file.\n\n2.2. **Extract the Archive**\nOnce 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\ndriver instance, thereby reducing detection risk.\n\n2.3. **Select and Copy the Driver**\nFrom the extracted files, choose any one random driver. Copy all three associated files to the directory where `cheatengine-x86_64.exe` is located.\n\nWhy Multiple Drivers?\nUsing a unique driver decreases the chances of your setup being flagged or blacklisted by anti-cheat systems.\nThe 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.\n\nFor better reliability, consider compiling your own driver following the instructions in Section 7. This process creates a custom driver, reducing the chances of\ndetection.\n\n## 3. Bypassing **Digital Signature Enforcement**\n\nAt this point you have driver signed with untrusted certificate.\nThere are a few options to load it.\nIn this section the method based on bypass of **Patchguard** and **Digital Signature Enforcement** will be explained.\nRefer to section 8 for some extra method.\n\n- [Video tutorial 1](https://www.youtube.com/watch?v=EJGuJp2fqpM)\n- [Video tutorial 2](https://www.youtube.com/watch?v=zsw3xoG3zgs)\n\n3.1. Create bootable usb drive\n\n3.1.1. Download [EfiGuard](https://github.com/Mattiwatti/EfiGuard/releases/) version >= 1.4.\n\n3.1.2. Mount you usb drive. 2GB drive should be more than enough.\n\n3.1.3. Format your usb drive as `FAT32`. **be carefull to format the correct device**, because it will erase all data on USB drive\n\n3.1.4. Partition your device as bootable `GPT` with `EFI` partition.\n**be carefull to partition the correct device!!!**\n\nOpen command prompt as administrator and perform the following commands:\n\n```shell\ndiskpart\nlist disk // detect your USB drive\nselect disk {put number of your USB drive here} // SELECTING CORRECT DISK!!!\nlist disk // make sure correct disk is selected\nclean // wipe out your drive\ncreate partition primary size=512 // create EFI partition\nlist partitions // created partition shoud be displayed\nselect partition 1 // select created partition\nactive // mark partition as active\nformat quick fs=fat32 // create filesystem\nassign // disk should be mounted\nexit\n```\n\n3.1.5. Copy files to USB drive\n\nCopy `EFI` directory from the extracted archive to the root of created partition.\n\n3.1.6. Rename bootloader\n\nLocate `EFI/Boot/Loader.efi` on the USB drive, than rename it to `EFI/Boot/bootx64.efi`.\n\n3.2. Boot your system from USB drive.\n\nRestart your computer and enter the UEFI settings (usually by pressing F2, F12, or DEL during startup).\nSet the first boot option to your USB drive (UEFI). The second option should be your windows drive (UEFI).\nEnsure Secure Boot is disabled since EFIGuard rootkit isn't signed.\n\n3.3. Copy files for digital signature enforcement bypass\n\n3.3.1. In the directory containing `cheatengine-x86_64.exe`, create a new file named `run.bat` with the following content:\n\n```shell\n\"%~dp0\\EfiDSEFix.exe\" -d\nstart /d \"%~dp0\" cheatengine-x86_64.exe\ntimeout /t 20\n\"%~dp0\\EfiDSEFix.exe\" -e\n```\n\nBefore doing that, make sure that file explored is not configured to hide known file extensions.\n\n3.3.2. Copy `EfiDSEFix.exe` from the archive to the same directory as `cheatengine-x86_64.exe`.\n\n## 4. Configure Cheat Engine\n\nMake sure that\n\n`Edit` > `Settings` > `Extra` > `Query memory region routines` is checked\n\n`Edit` > `Settings` > `Extra` > `Read/Write process memory` is checked\n\nClick `OK`.\n\nIt might end up with errors. Close Cheat Engine.\n\n## 5. Run Cheat Engine.\n\n### If you followed section 3:\n\nRun `run.bat` as Administrator.\n\nDo not close the window that pops out manually!!! Wait for it to close automatically.\n\nAfter the driver has been successfully loaded, you can directly run `cheatengine-x86_64.exe` without needing to execute `run.bat`.\n\n### If you followed section 8:\n\nRun `cheatengine-x86_64.exe`\n\n## 6. Congratulations\n\nYou have successfully loaded the DBK64 driver signed with an untrusted certificate.\nThis allows kernel mode anti-cheat (EAC) to permit starting the game and performing operations on the\ngame memory. Note: The last tested version was confirmed on EAC as of April 19, 2025.\n\n## 7. [Extra] Compile the driver from source\n\nAnti-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\ndriver with a unique signature.\n\n#### **Note:**\nUse PowerShell or Cmder for these steps.\n\n[Video Tutorial](https://www.youtube.com/watch?v=7ARwpxZPpE8)\n\n7.1. Clone this repository\n\n```shell\ngit clone https://github.com/dmarov/chamd.git\ncd chamd\n```\n\nEnsure you have Git installed on your system before cloning.\n\n7.2. Install [nodejs](https://nodejs.org/en/). Version `>=19` is required.\n\n7.3. Install packages\nRun the following command in your terminal:\n\n```shell\nnpm install\n```\n\nThis will install all required packages for building the driver.\n\n7.4. Copy `.env.tpl` to `.env`\nCreate a copy of the template environment file by running:\n\n```shell\ncp .env.tpl .env\n```\n\n7.5. Optionaly set `CHAMD_DBK_DRIVER_NAME` in `.env`.\n\nEdit the `.env` file and set the `CHAMD_DBK_DRIVER_NAME` variable to a unique name if desired.\n\nExample:\n```env\nCHAMD_DBK_DRIVER_NAME=mysupercooldrv\n```\n\n7.6. Install Visual Studio\n\nInstall **Visual Studio 2022** (Community or Enterprise) with support for C++ development.\n\n[Download Visual Studio](https://visualstudio.microsoft.com/downloads/)\n\nEnsure you select the following components during installation:\n- **Desktop Development with C++**\n- **MSVC v143 (C++ Compiler)**\n\n7.7. Install [Windows SDK and WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)\nCarefully follow the instructions from the link. It is important that SDK and WDK have the same version.\nCorrect versions of spectre mitigated libraries should be installed in the process.\n\n7.8. Install openssl. The most straightforward way is to use Chocolatey package manager.\n\n```shell\nchoco install openssl\n```\n\nThis command has to be performed as Admininstrator.\n\n7.9. Run build\n\n```shell\nnpm run all\n```\n\nNote:\n\nYou can use [EV certificate](https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/code-signing-cert-manage)\nto sign driver. You could skip digital signature enforcement bypass this way. They are costly though and can be revoked when misused.\n\n7.10. Copy all files from the 'dist' directory to directory where `cheatengine-x86_64.exe`\nis located.\n\n7.11. If you've managed to compile this driver successfully and want to share few\nrandomized copies then run `npm run multibuild 10`. `dist` directory will\ncontain `10` randomized drivers.\n\nThen go to section 3.\n\n## 8. [Extra] Another Method of dealing with *Digital Signature Enforcement*\n\nIf you want to bypass digital signature enforcement temporarily (for testing purposes only), follow these steps:\n\n8.1. Enable Test Signing Mode:\n```shell\nbcdedit /set testsigning on\n```\nThis command modifies the boot configuration to allow loading of unsigned or self-signed drivers.\n\n8.2. Reboot Your System:\nThe changes take effect after a system reboot.\n\n8.3. Proceed with Section 4:\nLoad the driver as outlined in section 4.\n\n8.4. Disable Test Signing Mode:\nAfter testing, disable test signing mode to restore normal security settings.\n```shell\nbcdedit /set testsigning off\n```\n\nEnabling test signing mode is intended for development and troubleshooting purposes only.\nIt temporarily reduces the system's security by allowing unsigned drivers to load.\nThis method does not work with anti-cheat systems, as they typically enforce strict driver signature requirements.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"dotenv\": \"^10.0.0\",\n    \"handlebars\": \"^4.7.7\"\n  },\n  \"scripts\": {\n    \"all\": \"node --unhandled-rejections=strict ./scripts/builder.js all\",\n    \"purge\": \"node --unhandled-rejections=strict ./scripts/builder.js purge\",\n    \"compile\": \"node --unhandled-rejections=strict ./scripts/builder.js compile\",\n    \"geninf\": \"node --unhandled-rejections=strict ./scripts/builder.js geninf\",\n    \"sign\": \"node --unhandled-rejections=strict ./scripts/builder.js sign\",\n    \"multibuild\": \"node --unhandled-rejections=strict ./scripts/multibuilder.js\"\n  }\n}\n"
  },
  {
    "path": "scripts/builder.js",
    "content": "import dotenv from 'dotenv';\nimport Context from './context.js';\nimport generateRandomName from './utils.js';\nimport path from 'path';\nimport { __dirname } from './paths.js';\n\nconst env = dotenv.config().parsed;\nconst driverName = env.CHAMD_DBK_DRIVER_NAME ?? generateRandomName();\nconst args = process.argv.slice(2);\nconst command = args[0];\nconst distDir = path.normalize(__dirname + '\\\\..\\\\dist\\\\');\nconst context = new Context(driverName, distDir);\n\nawait Context.purgeDir(distDir);\n\nswitch (command) {\n    case 'all':\n        await context.all();\n        break;\n    case 'purge':\n        await context.purge();\n        break;\n    case 'compile':\n        await context.generateCmakeFile();\n        await context.compile();\n        break;\n    case 'geninf':\n        await context.createInfFile();\n        await context.stampInfFile();\n        break;\n    case 'sign':\n        await context.signDriver();\n        await context.createInfFile();\n        break;\n}\n"
  },
  {
    "path": "scripts/context.js",
    "content": "import path from 'path';\nimport fs from 'fs';\nimport handlebars from 'handlebars';\nimport { spawn } from 'child_process';\nimport { __dirname } from './paths.js';\n\nexport default class Context {\n    buildDir = path.normalize(__dirname + '\\\\..\\\\build\\\\');\n\n    vcvarsCommunityPath = 'C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Community\\\\VC\\\\Auxiliary\\\\Build\\\\vcvarsall.bat';\n    vcvarsEnterprisePath = 'C:\\\\Program Files\\\\Microsoft Visual Studio\\\\2022\\\\Enterprise\\\\VC\\\\Auxiliary\\\\Build\\\\vcvarsall.bat';\n    vcPath = null;\n\n    cmakeTplPath = path.normalize(__dirname + '\\\\..\\\\templates\\\\CMakeLists.txt.tpl');\n    infTplPath = path.normalize(__dirname + '\\\\..\\\\templates\\\\chamd.inf.tpl');\n    makeCatTplPath = path.normalize(__dirname + '\\\\..\\\\templates\\\\makecat.cdf.tpl');\n    datTplPath = path.normalize(__dirname + '\\\\..\\\\templates\\\\driver64.dat.tpl');\n    datPath = `${this.buildDir}driver64.dat`;\n    srcDir = path.normalize(__dirname + '\\\\..\\\\src\\\\');\n    cmakeConfigPath = this.srcDir + 'CMakeLists.txt';\n\n    constructor(driverName, distDir) {\n        this.distDir = distDir;\n        this.driverName = driverName\n            .replace(/[^a-z0-9_]/gi, '')\n            .toLowerCase();\n\n        const communityVs = fs.existsSync(this.vcvarsCommunityPath);\n        const enterpriseVs = fs.existsSync(this.vcvarsEnterprisePath);\n\n        if (communityVs) {\n            this.vcPath = this.vcvarsCommunityPath;\n        }\n\n        if (enterpriseVs) {\n            this.vcPath = this.vcvarsEnterprisePath;\n        }\n\n        this.makeCatPath = `${this.buildDir}${this.driverName}.cdf`;\n    }\n\n    async all() {\n        console.log(`Generating ${this.driverName} driver ...`);\n        await this.purge();\n        await this.generateCmakeFile();\n        await this.compile();\n        await this.createMakeCatFile();\n        await this.makeCatFile();\n        await this.signDriver();\n        await this.createDriverDatFile();\n        await this.install();\n        await this.clearBuildDir();\n        console.log(`Success!!!`);\n        console.log(`Now copy all files from ${this.distDir} to directory where cheatengine.exe is located`);\n    }\n\n    async purge() {\n        await this.clearBuildDir();\n\n        if (!fs.existsSync(this.cmakeConfigPath)) {\n            return;\n        }\n\n        fs.rmSync(this.cmakeConfigPath);\n    }\n\n    static async purgeDir(dir) {\n\n        if (!fs.existsSync(dir)) {\n            return;\n        }\n\n        fs.rmSync(dir, { recursive: true })\n    }\n\n    async generateCmakeFile() {\n        await this.templateToFile(\n            this.cmakeTplPath,\n            this.cmakeConfigPath,\n            {\n                DRIVER_NAME: this.driverName,\n            }\n        );\n    }\n\n    async templateToFile(src, dist, vars) {\n        const templateContent = fs.readFileSync(src, 'utf-8');\n        const template = handlebars.compile(templateContent);\n        const res = template(vars)\n\n        fs.writeFileSync(dist, res);\n    }\n\n    async compile() {\n        console.log('Compiling');\n        if (this.vcPath === null) {\n            throw new Error('Visual studio not found');\n        }\n\n        if (!fs.existsSync(this.buildDir)) {\n            fs.mkdirSync(this.buildDir);\n        }\n\n        const cmd = `\"${this.vcPath}\" amd64 && cd \"${this.buildDir}\" && cmake -G \"Visual Studio 17 2022\" -A x64 -T v143 \"${this.srcDir}\" && cmake --build . --config Release`;\n        await this.execute(cmd, this.buildDir);\n    }\n\n    async createMakeCatFile() {\n        console.log('Creating makecat file');\n        await this.templateToFile(\n            this.makeCatTplPath,\n            this.makeCatPath, {\n                DRIVER_NAME: this.driverName,\n            },\n        );\n    }\n\n    async makeCatFile() {\n        console.log('Makeing cat file');\n        const cmd = `\"${this.vcPath}\" amd64 && MakeCat.exe -v .\\\\${this.driverName}.cdf`\n        await this.execute(cmd, this.buildDir);\n    }\n\n    async signDriver() {\n        console.log('Signing driver');\n        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\"`\n        const crt = `openssl x509 -signkey ${this.driverName}.key -in ${this.driverName}.csr -req -days 365 -out ${this.driverName}.crt`;\n        const pfx = `openssl pkcs12 -export -out ${this.driverName}.pfx -inkey ${this.driverName}.key -in ${this.driverName}.crt -password pass:`;\n        const vc = `\"${this.vcPath}\" amd64`;\n        const signtool = `signtool sign /fd SHA256 -f \"./${this.driverName}.pfx\" -t \"http://timestamp.digicert.com\" -v \"${this.driverName}.cat\"`;\n\n        const cmd = `${openssl} && ${crt} && ${pfx} && ${vc} && ${signtool}`;\n\n        await this.execute(cmd, this.buildDir);\n    }\n\n    async execute(cmd, cwd, params = []) {\n        console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);\n        console.log(`Executing: ${cmd}`);\n\n        return new Promise((res, rej) => {\n            const proc = spawn(cmd, params, {\n                cwd,\n                shell: true,\n            });\n\n            proc.stderr.setEncoding('utf-8');\n            proc.stdout.pipe(process.stdout);\n            proc.stderr.pipe(process.stderr);\n\n            proc.on('close', (code) => {\n                code == 0 ? res() : rej();\n            });\n        });\n    }\n\n    async createDriverDatFile() {\n        console.log('Creating dat file');\n        await this.templateToFile(\n            this.datTplPath,\n            this.datPath, {\n                DRIVER_NAME: this.driverName,\n            },\n        );\n    }\n\n    async install() {\n        console.log('Installing');\n\n        if (!fs.existsSync(this.distDir)) {\n            fs.mkdirSync(this.distDir, { recursive: true });\n        }\n\n        fs.copyFileSync(\n            `${this.buildDir}${this.driverName}.sys`,\n            `${this.distDir}${this.driverName}.sys`\n        );\n\n        fs.copyFileSync(\n            `${this.buildDir}${this.driverName}.cat`,\n            `${this.distDir}${this.driverName}.cat`\n        );\n\n        fs.copyFileSync(\n            `${this.buildDir}driver64.dat`,\n            `${this.distDir}driver64.dat`\n        );\n    }\n\n    async clearBuildDir() {\n        await Context.purgeDir(this.buildDir);\n    }\n}\n"
  },
  {
    "path": "scripts/multibuilder.js",
    "content": "import Context from './context.js';\nimport generateRandomName from './utils.js';\nimport path from 'path';\nimport http from 'http';\nimport { __dirname } from './paths.js';\n\nconst args = process.argv.slice(2);\nconst cnt = args[0] ? parseInt(args[0]) : 5;\nconst distDir = path.normalize(__dirname + '\\\\..\\\\dist\\\\');\n\nasync function getRandomWord() {\n    return new Promise((res, rej) => {\n        const options = {\n            host: 'random-word-api.herokuapp.com',\n            path: '/word'\n        };\n\n        const callback = function(response) {\n            let str = '';\n\n            response.on('data', function (chunk) {\n                str += chunk;\n            });\n\n            response.on('end', function () {\n                res(str);\n            });\n\n        }\n\n        const req = http.request(options, callback);\n\n        req.on('error', function (e) {\n            rej(e);\n        });\n\n        req.end();\n    });\n}\n\nawait Context.purgeDir(distDir);\n\nconst max = 15;\nconst min = 4;\n\nfor (let i = 0; i < cnt; i++) {\n    const len = min + Math.floor(Math.random() * (max - min));\n    let name = generateRandomName(len);\n\n    try {\n        const result = await getRandomWord();\n        name = JSON.parse(result)[0]\n            .replace(/[^a-z0-9_]/gi, '')\n            .toLowerCase();\n    } catch(e) {\n        console.log(e);\n    }\n\n    const context = new Context(name, distDir + name + '\\\\');\n\n    await context.all();\n}\n"
  },
  {
    "path": "scripts/paths.js",
    "content": "import path from 'path';\nimport { fileURLToPath } from 'url';\nconst __filename = fileURLToPath(import.meta.url);\n\nexport const __dirname = path.dirname(__filename);\n\n"
  },
  {
    "path": "scripts/utils.js",
    "content": "export default (length) => {\n    let result = '';\n    const characters = 'abcdefghijklmnopqrstuvwxyz';\n    const charactersLength = characters.length;\n\n    for (let i = 0; i < length; i++) {\n        result += characters.charAt(Math.floor(Math.random() * charactersLength));\n    }\n\n    return result;\n}\n"
  },
  {
    "path": "src/DBKDrvr.c",
    "content": "#pragma warning( disable: 4100 4101 4103 4189)\n\n#include \"DBKFunc.h\"\n#include <ntifs.h>\n#include <windef.h>\n#include \"DBKDrvr.h\"\n\n#include \"deepkernel.h\"\n#include \"processlist.h\"\n#include \"memscan.h\"\n#include \"threads.h\"\n#include \"vmxhelper.h\"\n#include \"debugger.h\"\n#include \"vmxoffload.h\"\n\n#include \"IOPLDispatcher.h\"\n#include \"interruptHook.h\"\n#include \"ultimap.h\"\n#include \"ultimap2.h\"\n#include \"noexceptions.h\"\n\n#include \"ultimap2\\apic.h\"\n\n\n#if (AMD64 && TOBESIGNED)\n#include \"sigcheck.h\"\n#endif\n\n\n#ifdef CETC\n\t#include \"cetc.h\"\n#endif\n\n\nvoid UnloadDriver(PDRIVER_OBJECT DriverObject);\n\nNTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);\nNTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);\n\n\n#ifndef AMD64\n//no api hooks for x64\n\n//-----NtUserSetWindowsHookEx----- //prevent global hooks\ntypedef ULONG (NTUSERSETWINDOWSHOOKEX)(\n    IN HANDLE hmod,\n    IN PUNICODE_STRING pstrLib OPTIONAL,\n    IN DWORD idThread,\n    IN int nFilterType,\n    IN PVOID pfnFilterProc,\n    IN DWORD dwFlags\n);\nNTUSERSETWINDOWSHOOKEX OldNtUserSetWindowsHookEx;\nULONG NtUserSetWindowsHookEx_callnumber;\n//HHOOK NewNtUserSetWindowsHookEx(IN HANDLE hmod,IN PUNICODE_STRING pstrLib OPTIONAL,IN DWORD idThread,IN int nFilterType, IN PROC pfnFilterProc,IN DWORD dwFlags);\n\n\ntypedef NTSTATUS (*ZWSUSPENDPROCESS)\n(\n    IN ULONG ProcessHandle  // Handle to the process\n);\nZWSUSPENDPROCESS ZwSuspendProcess;\n\nNTSTATUS ZwCreateThread(\n\tOUT PHANDLE  ThreadHandle,\n\tIN ACCESS_MASK  DesiredAccess,\n\tIN POBJECT_ATTRIBUTES  ObjectAttributes,\n\tIN HANDLE  ProcessHandle,\n\tOUT PCLIENT_ID  ClientId,\n\tIN PCONTEXT  ThreadContext,\n\tIN PVOID  UserStack,\n\tIN BOOLEAN  CreateSuspended);\n\n//PVOID GetApiEntry(ULONG FunctionNumber);\n#endif\n\n\n\n\n\ntypedef NTSTATUS(*PSRCTNR)(__in PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine);\nPSRCTNR PsRemoveCreateThreadNotifyRoutine2;\n\ntypedef NTSTATUS(*PSRLINR)(__in PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);\nPSRLINR PsRemoveLoadImageNotifyRoutine2;\n\nUNICODE_STRING  uszDeviceString;\nPVOID BufDeviceString=NULL;\n\n\n\nvoid hideme(PDRIVER_OBJECT DriverObject)\n{\n#ifndef AMD64\n\t\n\ttypedef struct _MODULE_ENTRY {\n\tLIST_ENTRY le_mod;\n\tDWORD  unknown[4];\n\tDWORD  base;\n\tDWORD  driver_start;\n\tDWORD  unk1;\n\tUNICODE_STRING driver_Path;\n\tUNICODE_STRING driver_Name;\n} MODULE_ENTRY, *PMODULE_ENTRY;\n\n\tPMODULE_ENTRY pm_current;\n\n\tpm_current =  *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14)); //eeeeew\n\n\t*((PDWORD)pm_current->le_mod.Blink)        = (DWORD) pm_current->le_mod.Flink;\n\tpm_current->le_mod.Flink->Blink            = pm_current->le_mod.Blink;\n\tHiddenDriver=TRUE;\n\n#endif\n}\n\n\nint testfunction(int p1,int p2)\n{\n\tDbgPrint(\"Hello\\nParam1=%d\\nParam2=%d\\n\",p1,p2);\n\t\n\n\n\treturn 0x666;\n}\n\n\nvoid* functionlist[1];\nchar  paramsizes[1];\nint registered=0;\n\n#ifdef DEBUG1\nVOID TestPassive(UINT_PTR param)\n{\n\tDbgPrint(\"passive cpu call for cpu %d\\n\", KeGetCurrentProcessorNumber());\n}\n\n\nVOID TestDPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2)\n{\n\tEFLAGS e=getEflags();\n\t\n    DbgPrint(\"Defered cpu call for cpu %d (Dpc=%p  IF=%d IRQL=%d)\\n\", KeGetCurrentProcessorNumber(), Dpc, e.IF, KeGetCurrentIrql());\n}\n#endif\n\n\nNTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,\n\tIN PUNICODE_STRING RegistryPath)\n\t/*++\n\n\tRoutine Description:\n\n\tThis routine is called when the driver is loaded by NT.\n\n\tArguments:\n\n\tDriverObject - Pointer to driver object created by system.\n\tRegistryPath - Pointer to the name of the services node for this driver.\n\n\tReturn Value:\n\n\tThe function value is the final status from the initialization operation.\n\n\t--*/\n{\n\n\n\tNTSTATUS        ntStatus;\n\tPVOID           BufDriverString = NULL, BufProcessEventString = NULL, BufThreadEventString = NULL;\n\tUNICODE_STRING  uszDriverString;\n\n\tUNICODE_STRING  uszProcessEventString;\n\tUNICODE_STRING\tuszThreadEventString;\n\tPDEVICE_OBJECT  pDeviceObject;\n\tHANDLE reg = 0;\n\tOBJECT_ATTRIBUTES oa;\n\n\tUNICODE_STRING temp;\n\tchar wbuf[100];\n\tWORD this_cs, this_ss, this_ds, this_es, this_fs, this_gs;\n\tULONG cr4reg;\n\n\n\n\tcriticalSection csTest;\n\n\tHANDLE Ultimap2Handle;\n\n\n\tKernelCodeStepping = 0;\n\tKernelWritesIgnoreWP = 0;\n\n\n\n\tthis_cs = getCS();\n\tthis_ss = getSS();\n\tthis_ds = getDS();\n\tthis_es = getES();\n\tthis_fs = getFS();\n\tthis_gs = getGS();\n\n\ttemp.Buffer = (PWCH)wbuf;\n\ttemp.Length = 0;\n\ttemp.MaximumLength = 100;\n\n\t//DbgPrint(\"Loading driver\\n\");\n\tif (RegistryPath)\n\t{\n\t\t//DbgPrint(\"Registry path = %S\\n\", RegistryPath->Buffer);\n\n\t\tInitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE, NULL, NULL);\n\t\tntStatus = ZwOpenKey(&reg, KEY_QUERY_VALUE, &oa);\n\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t{\n\t\t\tUNICODE_STRING A, B, C, D;\n\t\t\tPKEY_VALUE_PARTIAL_INFORMATION bufA, bufB, bufC, bufD;\n\t\t\tULONG ActualSize;\n\n\t\t\t//DbgPrint(\"Opened the key\\n\");\n\n\t\t\tBufDriverString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);\n\t\t\tBufDeviceString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);\n\t\t\tBufProcessEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);\n\t\t\tBufThreadEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);\n\n\t\t\tbufA = BufDriverString;\n\t\t\tbufB = BufDeviceString;\n\t\t\tbufC = BufProcessEventString;\n\t\t\tbufD = BufThreadEventString;\n\n\t\t\tRtlInitUnicodeString(&A, L\"A\");\n\t\t\tRtlInitUnicodeString(&B, L\"B\");\n\t\t\tRtlInitUnicodeString(&C, L\"C\");\n\t\t\tRtlInitUnicodeString(&D, L\"D\");\n\n\t\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\t\tntStatus = ZwQueryValueKey(reg, &A, KeyValuePartialInformation, bufA, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);\n\t\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\t\tntStatus = ZwQueryValueKey(reg, &B, KeyValuePartialInformation, bufB, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);\n\t\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\t\tntStatus = ZwQueryValueKey(reg, &C, KeyValuePartialInformation, bufC, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);\n\t\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\t\tntStatus = ZwQueryValueKey(reg, &D, KeyValuePartialInformation, bufD, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);\n\n\t\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\t{\n\t\t\t\t//DbgPrint(\"Read ok\\n\");\n\t\t\t\tRtlInitUnicodeString(&uszDriverString, (PCWSTR)bufA->Data);\n\t\t\t\tRtlInitUnicodeString(&uszDeviceString, (PCWSTR)bufB->Data);\n\t\t\t\tRtlInitUnicodeString(&uszProcessEventString, (PCWSTR)bufC->Data);\n\t\t\t\tRtlInitUnicodeString(&uszThreadEventString, (PCWSTR)bufD->Data);\n\n\t\t\t\t//DbgPrint(\"DriverString=%S\\n\", uszDriverString.Buffer);\n\t\t\t\t//DbgPrint(\"DeviceString=%S\\n\", uszDeviceString.Buffer);\n\t\t\t\t//DbgPrint(\"ProcessEventString=%S\\n\", uszProcessEventString.Buffer);\n\t\t\t\t//DbgPrint(\"ThreadEventString=%S\\n\", uszThreadEventString.Buffer);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tExFreePool(bufA);\n\t\t\t\tExFreePool(bufB);\n\t\t\t\tExFreePool(bufC);\n\t\t\t\tExFreePool(bufD);\n\n\t\t\t\t//DbgPrint(\"Failed reading the value\\n\");\n\t\t\t\tZwClose(reg);\n\t\t\t\treturn STATUS_UNSUCCESSFUL;;\n\t\t\t}\n\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//DbgPrint(\"Failed opening the key\\n\");\n\t\t\treturn STATUS_UNSUCCESSFUL;;\n\t\t}\n\t}\n\telse\n\t\tloadedbydbvm = TRUE;\n\n\tntStatus = STATUS_SUCCESS;\n\n\n\n\n\n\tif (!loadedbydbvm)\n\t{\n\n\t\t// Point uszDriverString at the driver name\n#ifndef CETC\n\n\n\t\t// Create and initialize device object\n\t\tntStatus = IoCreateDevice(DriverObject,\n\t\t\t0,\n\t\t\t&uszDriverString,\n\t\t\tFILE_DEVICE_UNKNOWN,\n\t\t\t0,\n\t\t\tFALSE,\n\t\t\t&pDeviceObject);\n\n\t\tif (ntStatus != STATUS_SUCCESS)\n\t\t{\n\t\t\t//DbgPrint(\"IoCreateDevice failed\\n\");\n\t\t\tExFreePool(BufDriverString);\n\t\t\tExFreePool(BufDeviceString);\n\t\t\tExFreePool(BufProcessEventString);\n\t\t\tExFreePool(BufThreadEventString);\n\n\n\t\t\tif (reg)\n\t\t\t\tZwClose(reg);\n\n\t\t\treturn ntStatus;\n\t\t}\n\n\t\t// Point uszDeviceString at the device name\n\n\t\t// Create symbolic link to the user-visible name\n\t\tntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);\n\n\t\tif (ntStatus != STATUS_SUCCESS)\n\t\t{\n\t\t\t//DbgPrint(\"IoCreateSymbolicLink failed: %x\\n\", ntStatus);\n\t\t\t// Delete device object if not successful\n\t\t\tIoDeleteDevice(pDeviceObject);\n\n\t\t\tExFreePool(BufDriverString);\n\t\t\tExFreePool(BufDeviceString);\n\t\t\tExFreePool(BufProcessEventString);\n\t\t\tExFreePool(BufThreadEventString);\n\n\n\t\t\tif (reg)\n\t\t\t\tZwClose(reg);\n\n\t\t\treturn ntStatus;\n\t\t}\n\n#endif\n\t}\n\n\t//when loaded by dbvm driver object is 'valid' so store the function addresses\n\n\n\t//DbgPrint(\"DriverObject=%p\\n\", DriverObject);\n\n\t// Load structure to point to IRP handlers...\n\tDriverObject->DriverUnload = UnloadDriver;\n\tDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;\n\tDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;\n\n\tif (loadedbydbvm)\n\t\tDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchIoctlDBVM;\n\telse\n\t\tDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;\n\n\n\n\t//Processlist init\n#ifndef CETC\n\tProcessEventCount = 0;\n\tExInitializeResourceLite(&ProcesslistR);\n#endif\n\n\tCreateProcessNotifyRoutineEnabled = FALSE;\n\n\t//threadlist init\n\tThreadEventCount = 0;\n\n\tprocesslist = NULL;\n\n#ifndef AMD64\n\t//determine if PAE is used\n\tcr4reg=(ULONG)getCR4();\n\n\tif ((cr4reg & 0x20)==0x20)\n\t{\n\t\tPTESize=8; //pae\n\t\tPAGE_SIZE_LARGE=0x200000;\n\t\tMAX_PDE_POS=0xC0604000;\n\t\tMAX_PTE_POS=0xC07FFFF8;\n\n\n\t}\n\telse\n\t{\n\t\tPTESize=4;\n\t\tPAGE_SIZE_LARGE=0x400000;\n\t\tMAX_PDE_POS=0xC0301000;\n\t\tMAX_PTE_POS=0xC03FFFFC;\n\t}\n#else\n\tPTESize = 8; //pae\n\tPAGE_SIZE_LARGE = 0x200000;\n\t//base was 0xfffff68000000000ULL\n\n\t//to \n\tMAX_PTE_POS = 0xFFFFF6FFFFFFFFF8ULL; // base + 0x7FFFFFFFF8\n\tMAX_PDE_POS = 0xFFFFF6FB7FFFFFF8ULL; // base + 0x7B7FFFFFF8\n#endif\n\n\n\n#ifdef CETC\n\tDbgPrint(\"Going to initialice CETC\\n\");\n\tInitializeCETC();\n#endif\n\n\n\t//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\n\n\tDbgPrint(\"Initializing debugger\\n\");\n\tdebugger_initialize();\n\n\n\t// Return success (don't do the devicestring, I need it for unload)\n\tDbgPrint(\"Cleaning up initialization buffers\\n\");\n\tif (BufDriverString)\n\t{\n\t\tExFreePool(BufDriverString);\n\t\tBufDriverString = NULL;\n\t}\n\n\tif (BufProcessEventString)\n\t{\n\t\tExFreePool(BufProcessEventString);\n\t\tBufProcessEventString = NULL;\n\t}\n\n\tif (BufThreadEventString)\n\t{\n\t\tExFreePool(BufThreadEventString);\n\t\tBufThreadEventString = NULL;\n\t}\n\n\tif (reg)\n\t{\n\t\tZwClose(reg);\n\t\treg = 0;\n\t}\n\n\n\n\t//fetch cpu info\n\t{\n\t\tDWORD r[4];\n\t\tDWORD a;\n\n\t\t__cpuid(r, 0);\n\t\tDbgPrint(\"cpuid.0: r[1]=%x\", r[1]);\n\t\tif (r[1] == 0x756e6547) //GenuineIntel\n\t\t{\n\n\t\t\t__cpuid(r, 1);\n\n\t\t\ta = r[0];\n\n\t\t\tcpu_stepping = a & 0xf;\n\t\t\tcpu_model = (a >> 4) & 0xf;\n\t\t\tcpu_familyID = (a >> 8) & 0xf;\n\t\t\tcpu_type = (a >> 12) & 0x3;\n\t\t\tcpu_ext_modelID = (a >> 16) & 0xf;\n\t\t\tcpu_ext_familyID = (a >> 20) & 0xff;\n\n\t\t\tcpu_model = cpu_model + (cpu_ext_modelID << 4);\n\t\t\tcpu_familyID = cpu_familyID + (cpu_ext_familyID << 4);\n\n\t\t\tvmx_init_dovmcall(1);\n\t\t\tsetup_APIC_BASE(); //for ultimap\n\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Not an intel cpu\");\n\t\t\tif (r[1] == 0x68747541)\n\t\t\t{\n\t\t\t\tDbgPrint(\"This is an AMD\\n\");\n\t\t\t\tvmx_init_dovmcall(0);\n\t\t\t}\n\n\t\t}\n\n\n\n\t}\n\n#ifdef DEBUG1\n\t{\n\t\tAPIC y;\n\n\t\tDebugStackState x;\n\t\tDbgPrint(\"offset of LBR_Count=%d\\n\", (UINT_PTR)&x.LBR_Count - (UINT_PTR)&x);\n\n\n\t\tDbgPrint(\"Testing forEachCpu(...)\\n\");\n\t\tforEachCpu(TestDPC, NULL, NULL, NULL, NULL);\n\n\t\tDbgPrint(\"Testing forEachCpuAsync(...)\\n\");\n\t\tforEachCpuAsync(TestDPC, NULL, NULL, NULL, NULL);\n\n\t\tDbgPrint(\"Testing forEachCpuPassive(...)\\n\");\n\t\tforEachCpuPassive(TestPassive, 0);\n\n\t\tDbgPrint(\"LVT_Performance_Monitor=%x\\n\", (UINT_PTR)&y.LVT_Performance_Monitor - (UINT_PTR)&y);\n\t}\n#endif\n\n#ifdef DEBUG2\n\tDbgPrint(\"No exceptions test:\");\n\tif (NoExceptions_Enter())\n\t{\n\t\tint o = 45678;\n\t\tint x = 0, r = 0;\n\t\t//r=NoExceptions_CopyMemory(&x, &o, sizeof(x));\n\n\t\tr = NoExceptions_CopyMemory(&x, (PVOID)0, sizeof(x));\n\n\t\tDbgPrint(\"o=%d x=%d r=%d\", o, x, r);\n\n\n\t\tDbgPrint(\"Leaving NoExceptions mode\");\n\t\tNoExceptions_Leave();\n\t}\n#endif\n\n\n\tRtlInitUnicodeString(&temp, L\"PsSuspendProcess\");\n\tPsSuspendProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);\n\n\tRtlInitUnicodeString(&temp, L\"PsResumeProcess\");\n\tPsResumeProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);\n\t\n\t\n    return STATUS_SUCCESS;\n}\n\n\nNTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,\n                       IN PIRP Irp)\n{\n\t// Check for SeDebugPrivilege. (So only processes with admin rights can use it)\n\n\tLUID sedebugprivUID;\n\tsedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;\n\tsedebugprivUID.HighPart=0;\n\n\tIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;\n\n\n\n\tif (SeSinglePrivilegeCheck(sedebugprivUID, UserMode))\n\t{\t\t\n\t\tIrp->IoStatus.Status = STATUS_SUCCESS;\n#ifdef AMD64\n#ifdef TOBESIGNED\n\t\t{\n\t\t\tNTSTATUS s=SecurityCheck();\t\n\t\t\tIrp->IoStatus.Status = s; \t\t\n\t\t}\n\t//\tDbgPrint(\"Returning %x (and %x)\\n\", Irp->IoStatus.Status, s);\n#endif\n#endif\n\n\n\t}\n\telse\n\t{\n\t\tDbgPrint(\"A process without SeDebugPrivilege tried to open the dbk driver\\n\");\n\t\tIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;\n\t}\n\n    Irp->IoStatus.Information=0;\n\n    IoCompleteRequest(Irp, IO_NO_INCREMENT);\n    return Irp->IoStatus.Status;\n}\n\n\nNTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,\n                       IN PIRP Irp)\n{\n    Irp->IoStatus.Status = STATUS_SUCCESS;\n    Irp->IoStatus.Information=0;\n\n    IoCompleteRequest(Irp, IO_NO_INCREMENT);\n    return Irp->IoStatus.Status;\n}\n\n\n\n\n\nvoid UnloadDriver(PDRIVER_OBJECT DriverObject)\n{\n\tcleanupDBVM();\n\t\n\tif (!debugger_stopDebugging())\n\t{\n\t\tDbgPrint(\"Can not unload the driver because of debugger\\n\");\n\t\treturn; //\n\t}\n\n\tdebugger_shutdown();\n\n\tultimap_disable();\n\tDisableUltimap2();\n\tUnregisterUltimapPMI();\n\n\tclean_APIC_BASE();\n\n\tNoExceptions_Cleanup();\n\t\n\tif ((CreateProcessNotifyRoutineEnabled) || (ImageNotifyRoutineLoaded)) \n\t{\n\t\tPVOID x;\n\t\tUNICODE_STRING temp;\n\n\t\tRtlInitUnicodeString(&temp, L\"PsRemoveCreateThreadNotifyRoutine\");\n\t\tPsRemoveCreateThreadNotifyRoutine2 = (PSRCTNR)MmGetSystemRoutineAddress(&temp);\n\n\t\tRtlInitUnicodeString(&temp, L\"PsRemoveCreateThreadNotifyRoutine\");\n\t\tPsRemoveLoadImageNotifyRoutine2 = (PSRLINR)MmGetSystemRoutineAddress(&temp);\n\t\t\n\t\tRtlInitUnicodeString(&temp, L\"ObOpenObjectByName\");\n\t\tx=MmGetSystemRoutineAddress(&temp);\n\t\t\n\t\tDbgPrint(\"ObOpenObjectByName=%p\\n\",x);\n\t\t\t\n\n\t\tif ((PsRemoveCreateThreadNotifyRoutine2) && (PsRemoveLoadImageNotifyRoutine2))\n\t\t{\n\t\t\tDbgPrint(\"Stopping processwatch\\n\");\n\n\t\t\tif (CreateProcessNotifyRoutineEnabled)\n\t\t\t{\n\t\t\t\tDbgPrint(\"Removing process watch\");\n#if (NTDDI_VERSION >= NTDDI_VISTASP1)\n\t\t\t\tPsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx,TRUE);\n#else\n\t\t\t\tPsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,TRUE);\n#endif\n\n\t\t\t\t\n\t\t\t\tDbgPrint(\"Removing thread watch\");\n\t\t\t\tPsRemoveCreateThreadNotifyRoutine2(CreateThreadNotifyRoutine);\n\t\t\t}\n\n\t\t\tif (ImageNotifyRoutineLoaded)\n\t\t\t\tPsRemoveLoadImageNotifyRoutine2(LoadImageNotifyRoutine);\n\t\t}\n\t\telse return;  //leave now!!!!!\t\t\n\t}\n\n\n\tDbgPrint(\"Driver unloading\\n\");\n\n    IoDeleteDevice(DriverObject->DeviceObject);\n\n#ifdef CETC\n#ifndef CETC_RELEASE\n\tUnloadCETC(); //not possible in the final build\n#endif\n#endif\n\n#ifndef CETC_RELEASE\n\tDbgPrint(\"DeviceString=%S\\n\",uszDeviceString.Buffer);\n\t{\n\t\tNTSTATUS r = IoDeleteSymbolicLink(&uszDeviceString);\n\t\tDbgPrint(\"IoDeleteSymbolicLink: %x\\n\", r);\n\t}\n\tExFreePool(BufDeviceString);\n#endif\n\n\tCleanProcessList();\n\n\tExDeleteResourceLite(&ProcesslistR);\n\n\tRtlZeroMemory(&ProcesslistR, sizeof(ProcesslistR));\n\n#if (NTDDI_VERSION >= NTDDI_VISTA)\n\tif (DRMHandle)\n\t{\n\t\tDbgPrint(\"Unregistering DRM handle\");\n\t\tObUnRegisterCallbacks(DRMHandle);\n\t\tDRMHandle = NULL;\n\t}\n#endif\n}\n"
  },
  {
    "path": "src/DBKDrvr.h",
    "content": "#ifndef DBKDRVR_H\n#define DBKDRVR_H\n\n\n\n#define dbkversion 2000027\n\n\n#endif"
  },
  {
    "path": "src/DBKFunc.c",
    "content": "#pragma warning( disable: 4103)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include \"DBKFunc.h\"\n\n/*\n#include \"vmxhelper.h\"\n#include \"interruptHook.h\"\n*/\n\n#ifdef TESTCOMPILE\n//small bypass to make test compiles function (this compiler doesn't have CLI/STI )\nvoid _enable() {}\nvoid _disable() {}\n#endif\n\n\nvoid forEachCpuPassive(PF f, UINT_PTR param)\n/*\ncalls a specific function for each cpu that runs in passive mode\n*/\n{\n\tCCHAR cpunr;\n\tKAFFINITY cpus, original;\n\tULONG cpucount;\n\n\t\n\t//KeIpiGenericCall is not present in xp\n\t\n\t//count cpus first KeQueryActiveProcessorCount is not present in xp)\n\tcpucount=0;\n\tcpus=KeQueryActiveProcessors();\n\toriginal=cpus;\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t\tcpucount++;\n\n\t\tcpus=cpus / 2;\t\t\n\t}\n\n\tcpus=KeQueryActiveProcessors();\n\tcpunr=0;\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t{\n\t\t\t//bit is set\n#if (NTDDI_VERSION >= NTDDI_VISTA)\n\t\t\tKAFFINITY oldaffinity;\n#endif\n\t\t\tKAFFINITY newaffinity;\n\n\n\t\t\t\n\t\t\t//DbgPrint(\"Calling passive function for cpunr %d\\n\", cpunr);\n\t\t\t//set affinity\n\n\t\t\tnewaffinity=(KAFFINITY)(1 << cpunr);\n\n#if (NTDDI_VERSION >= NTDDI_VISTA)\n\t\t\toldaffinity=KeSetSystemAffinityThreadEx(newaffinity);\n#else\n\t\t\t//XP and earlier (this routine is not called often, only when the user asks explicitly\n\t\t\t{\n\t\t\t\tLARGE_INTEGER delay;\n\t\t\t\tdelay.QuadPart=-50; //short wait just to be sure... (the docs do not say that a switch happens imeadiatly for the no Ex version)\n\t\t\t\t\n\t\t\t\tKeSetSystemAffinityThread(newaffinity);\n\t\t\t\tKeDelayExecutionThread(UserMode, FALSE, &delay);\n\t\t\t}\n#endif\n\n\n\n\t\t\t//call function\n\t\t\tf(param);\n\n#if (NTDDI_VERSION >= NTDDI_VISTA)\n\t\t\tKeRevertToUserAffinityThreadEx(oldaffinity);\n#endif\n\n\t\t}\n\n\t\tcpus=cpus / 2;\n\t\tcpunr++;\n\t}\n\n#if (NTDDI_VERSION < NTDDI_VISTA)\n\tKeSetSystemAffinityThread(original);\n#endif\n}\n\nvoid forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)\n{\n\tPKDPC dpc;\n\n\tif (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments\n\t\tpreDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);\n\t\n\n\tdpc = ExAllocatePool(NonPagedPool, sizeof(KDPC));\n\tKeInitializeDpc(dpc, dpcfunction, DeferredContext);\n\tKeSetTargetProcessorDpc(dpc, cpunr);\n\tKeInsertQueueDpc(dpc, SystemArgument1, SystemArgument2);\n\tKeFlushQueuedDpcs();\n\n\tExFreePool(dpc);\n}\n\nvoid forEachCpu(PKDEFERRED_ROUTINE dpcfunction,  PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)\n/*\ncalls a specified dpcfunction for each cpu on the system\n*/\n{\n\tCCHAR cpunr;\n\tKAFFINITY cpus;\n\tULONG cpucount;\n\tPKDPC dpc;\n\tint dpcnr;\n\n\n\t//KeIpiGenericCall is not present in xp\n\t\n\t//count cpus first KeQueryActiveProcessorCount is not present in xp)\n\tcpucount=0;\n\tcpus=KeQueryActiveProcessors();\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t\tcpucount++;\n\n\t\tcpus=cpus / 2;\t\t\n\t}\n\n\tdpc=ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);\n\n\t\t\n\n\tcpus=KeQueryActiveProcessors();\n\tcpunr=0;\n\tdpcnr=0;\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t{\n\t\t\t//bit is set\n\t\t\t\n\t\t\t//DbgPrint(\"Calling dpc routine for cpunr %d (dpc=%p)\\n\", cpunr, &dpc[dpcnr]);\n\n\t\t\tif (preDPCCallback)\n\t\t\t\tpreDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);\n\n\t\t\tKeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);\n\t\t\tKeSetTargetProcessorDpc (&dpc[dpcnr], cpunr);\n\t\t\tKeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);\n\t\t\tKeFlushQueuedDpcs();\n\t\t\tdpcnr++;\n\t\t}\n\n\t\tcpus=cpus / 2;\n\t\tcpunr++;\n\t}\n\n\n\tExFreePool(dpc);\n}\n\n\nvoid forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)\n/*\ncalls a specified dpcfunction for each cpu on the system\n*/\n{\n\tCCHAR cpunr;\n\tKAFFINITY cpus;\n\tULONG cpucount;\n\tPKDPC dpc;\n\tint dpcnr;\n\n\n\n\t//KeIpiGenericCall is not present in xp\n\n\t//count cpus first KeQueryActiveProcessorCount is not present in xp)\n\tcpucount = 0;\n\tcpus = KeQueryActiveProcessors();\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t\tcpucount++;\n\n\t\tcpus = cpus / 2;\n\t}\n\n\tdpc = ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);\n\n\tcpus = KeQueryActiveProcessors();\n\tcpunr = 0;\n\tdpcnr = 0;\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t{\n\t\t\t//bit is set\n\n\t\t\t//DbgPrint(\"Calling dpc routine for cpunr %d\\n\", cpunr);\n\t\t\tif (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments\n\t\t\t\tpreDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);\n\n\t\t\tKeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);\n\t\t\tKeSetTargetProcessorDpc(&dpc[dpcnr], cpunr);\n\t\t\tKeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);\t\t\t\n\t\t\tdpcnr++;\n\t\t}\n\n\t\tcpus = cpus / 2;\n\t\tcpunr++;\n\t}\n\n\tKeFlushQueuedDpcs();\n\n\n\tExFreePool(dpc);\n}\n\n\n\n//own critical section implementation for use when the os is pretty much useless (dbvm tech)\nvoid spinlock(volatile LONG *lockvar)\n{\n\twhile (1)\n\t{\n\n\t\t//it was 0, let's see if we can set it to 1\n\t\t//race who can set it to 1:\n\t\tif (_InterlockedExchange((volatile LONG *)lockvar, 1)==0)\n\t\t\treturn; //lock aquired, else continue loop\n\n\t\t_mm_pause();\n\n\t}\n\n}\n\nvoid csEnter(PcriticalSection CS)\n{ \n\tEFLAGS oldstate=getEflags();\n\t\n\tif ((CS->locked) && (CS->cpunr==cpunr())) \n\t{\n\t    //already locked but the locker is this cpu, so allow, just increase lockcount\n\t    CS->lockcount++;\n\t    return; \n\t} \n\n\tdisableInterrupts(); //disable interrupts to prevent taskswitch in same cpu\n\t\n\tspinlock(&(CS->locked)); //sets CS->locked to 1\n  \n\t//here so the lock is aquired and locked is 1\n\tCS->lockcount=1;\n\tCS->cpunr=cpunr();  \n\tCS->oldIFstate=oldstate.IF;\n}\n\nvoid csLeave(PcriticalSection CS)\n{\n\tif ((CS->locked) && (CS->cpunr==cpunr()))\n\t{\n\t    CS->lockcount--;\n\t    if (CS->lockcount==0)\n\t    {\n\t\t\t//unlock    \n\t\t\tif (CS->oldIFstate)\n\t\t\t\tenableInterrupts();\t\t\t\t\n\n\t\t\tCS->cpunr=-1; //set to an cpunr\n\t\t\tCS->locked=0;\n\t\t} \n\t}\n\t\n}\n\n\nint getCpuCount(void)\n{\n\tKAFFINITY ap=KeQueryActiveProcessors();\n\tint count=0;\n\twhile (ap>0)\n\t{\n\t\tif (ap % 2)\n\t\t\tcount++;\n\n\t\tap=ap / 2;\n\t}\n\treturn count;\n}\n\nint isPrefix(unsigned char b)\n{\n\tswitch (b)\n\t{\n\t\tcase 0x26:\n\t\tcase 0x2e:\n\t\tcase 0x36:\n\t\tcase 0x3e:\t\t\n\t\tcase 0x64:\n\t\tcase 0x65:\n\t\tcase 0x66:\n\t\tcase 0x67:\n\t\tcase 0xf0: //lock\n\t\tcase 0xf2: //repne\n\t\tcase 0xf3: //rep\n\t\t\treturn 1;\n\n\t\tdefault:\n\t\t\treturn 0;\n\n\t}\n\n}\n\nUINT64 getDR7(void)\n{\n\treturn __readdr(7);\n\n}\n\nint cpunr(void)\n{\t\n\tDWORD x[4];\n\t__cpuid(&x[0],1);\n\t\n\treturn (x[1] >> 24)+1;\n\n}\n\nEFLAGS getEflags(void)\n{\n\tUINT64 x=__getcallerseflags();\n\tPEFLAGS y = (PEFLAGS)&x;\n\treturn *y;\n}\n\nUINT64 readMSR(DWORD msr)\n{\n\treturn __readmsr(msr);\n}\n\nvoid setCR0(UINT64 newcr0)\n{\n\t__writecr0(newcr0);\n}\n\nUINT64 getCR0(void)\n{\n\treturn __readcr0();\n}\n\nUINT64 getCR2(void)\n{\n\treturn __readcr2();\n}\n\n\n\nvoid setCR3(UINT64 newCR3)\n{\n\t__writecr3((UINT_PTR)newCR3);\n}\n\nUINT64 getCR3(void)\n{\n\treturn __readcr3();\n}\n\n\n\nvoid setCR4(UINT64 newcr4)\n{\n\t__writecr4(newcr4);\n}\n\nUINT64 getCR4(void)\n{\n\treturn __readcr4();\n}\n\nvoid GetIDT(PIDT pIdt)\n{\n\t__sidt(pIdt);\n}\n\nvoid enableInterrupts(void)\n{\n#ifdef AMD64\n\t_enable();\n#else\n\t__asm{sti};\n#endif\n}\n\nvoid disableInterrupts(void)\n{\n#ifdef AMD64\n\t_disable();\n#else\n\t__asm{cli};\n#endif\n}\n\nUINT64 getTSC(void)\n{\n\treturn __rdtsc();\n}\n\n#ifndef AMD64\n//function declarations that can be done inline without needing an .asm file\n_declspec( naked ) WORD getSS(void)\n{\n\t__asm\n\t{\n\t\tmov ax,ss\n\t\tret\n\t}\n}\n\n_declspec( naked ) WORD getCS(void)\n{\n\t__asm\n\t{\n\t\tmov ax,cs\n\t\tret\n\t}\n}\n\n_declspec( naked ) WORD getDS(void)\n{\n\t__asm\n\t{\n\t\tmov ax,ds\n\t\tret\n\t}\n}\n\n_declspec( naked ) WORD getES(void)\n{\n\t__asm\n\t{\n\t\tmov ax,es\n\t\tret\n\t}\n}\n\n_declspec( naked ) WORD getFS(void)\n{\n\t__asm\n\t{\n\t\tmov ax,fs\n\t\tret\n\t}\n}\n\n_declspec( naked ) WORD getGS(void)\n{\n\t__asm\n\t{\n\t\tmov ax,gs\n\t\tret\n\t}\n}\n\n\n_declspec( naked ) ULONG getRSP(void) //...\n{\n\t__asm\n\t{\n\t\tmov eax,esp\n\t\tadd eax,4 //don't add this call\n\t\tret\n\t}\n}\n\n_declspec( naked ) ULONG getRBP(void)\n{\n\t__asm\n\t{\n\t\tmov eax,ebp\n\t\tret\n\t}\n}\n\n_declspec( naked ) ULONG getRAX(void)\n{\n\t__asm\n\t{\n\t\tmov eax,eax\n\t\tret\n\t}\n}\n_declspec( naked ) ULONG getRBX(void)\n{\n\t__asm\n\t{\n\t\tmov eax,ebx\n\t\tret\n\t}\n}\n_declspec( naked ) ULONG getRCX(void)\n{\n\t__asm\n\t{\n\t\tmov eax,ecx\n\t\tret\n\t}\n}\n_declspec( naked ) ULONG getRDX(void)\n{\n\t__asm\n\t{\n\t\tmov eax,edx\n\t\tret\n\t}\n}\n_declspec( naked ) ULONG getRSI(void)\n{\n\t__asm\n\t{\n\t\tmov eax,esi\n\t\tret\n\t}\n}\n_declspec( naked ) ULONG getRDI(void)\n{\n\t__asm\n\t{\n\t\tmov eax,edi\n\t\tret\n\t}\n}\n\n_declspec( naked ) unsigned short GetTR(void)\n{\n\t__asm{\n\t\tSTR AX\n\t\tret\n\t}\t\n}\n\n\nvoid GetGDT(PGDT pGdt)\n{\n\t__asm\n    {\n\t\tMOV EAX, [pGdt]\n\t    SGDT [EAX]\n    }       \n}\n\n_declspec( naked )WORD GetLDT()\n{\t\n\t__asm\n\t{\t\t\n\t\tSLDT ax\n\t\tret\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "src/DBKFunc.h",
    "content": "#ifndef DBKFUNC_H\n#define DBKFUNC_H\n\n#pragma warning( disable: 4214 )\n\n#include <ntifs.h>\n#include <ntstrsafe.h>\n\n#include <windef.h>\n\n#include \"interruptHook.h\"\n\n#ifdef RELEASE\n#define DbgPrint(...)\n#endif\n\nint _fltused;\n\n\ntypedef VOID F(UINT_PTR param);\ntypedef F *PF;\n\ntypedef VOID PREDPC_CALLBACK(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID DeferredContext, PVOID *SystemArgument1, PVOID *SystemArgument2);\n\ntypedef PREDPC_CALLBACK *PPREDPC_CALLBACK;\n\n\ntypedef struct _criticalSection\n{\n  LONG locked;\n  int cpunr; //unique id for a cpu\n  int lockcount;\n  int oldIFstate;\n} criticalSection, *PcriticalSection;\n\n\n//ntosp.h\n\ntypedef\n_Function_class_(KNORMAL_ROUTINE)\n_IRQL_requires_max_(PASSIVE_LEVEL)\n_IRQL_requires_min_(PASSIVE_LEVEL)\n_IRQL_requires_(PASSIVE_LEVEL)\n_IRQL_requires_same_\nVOID\nKNORMAL_ROUTINE(\n\t_In_opt_ PVOID NormalContext,\n\t_In_opt_ PVOID SystemArgument1,\n\t_In_opt_ PVOID SystemArgument2\n);\ntypedef KNORMAL_ROUTINE *PKNORMAL_ROUTINE;\n\ntypedef\n_Function_class_(KKERNEL_ROUTINE)\n_IRQL_requires_max_(APC_LEVEL)\n_IRQL_requires_min_(APC_LEVEL)\n_IRQL_requires_(APC_LEVEL)\n_IRQL_requires_same_\nVOID\nKKERNEL_ROUTINE(\n\t_In_ struct _KAPC *Apc,\n\t_Inout_ PKNORMAL_ROUTINE *NormalRoutine,\n\t_Inout_ PVOID *NormalContext,\n\t_Inout_ PVOID *SystemArgument1,\n\t_Inout_ PVOID *SystemArgument2\n);\ntypedef KKERNEL_ROUTINE *PKKERNEL_ROUTINE;\n\n\ntypedef\n_Function_class_(KRUNDOWN_ROUTINE)\n_IRQL_requires_max_(PASSIVE_LEVEL)\n_IRQL_requires_min_(PASSIVE_LEVEL)\n_IRQL_requires_(PASSIVE_LEVEL)\n_IRQL_requires_same_\nVOID\nKRUNDOWN_ROUTINE(\n\t_In_ struct _KAPC *Apc\n);\ntypedef KRUNDOWN_ROUTINE *PKRUNDOWN_ROUTINE;\n\n\ntypedef\n_IRQL_requires_same_\n_Function_class_(KENUM_ROUTINE)\nVOID\nKENUM_ROUTINE(\n\t_In_reads_(_Inexpressible_(Length)) PVOID Data,\n\t_In_ ULONG Length,\n\t_In_ PVOID Context\n);\n\ntypedef KENUM_ROUTINE *PKENUM_ROUTINE;\n\ntypedef enum _KAPC_ENVIRONMENT {\n\tOriginalApcEnvironment,\n\tAttachedApcEnvironment,\n\tCurrentApcEnvironment,\n\tInsertApcEnvironment\n} KAPC_ENVIRONMENT;\n\n\n\nNTKERNELAPI\n_IRQL_requires_max_(DISPATCH_LEVEL)\n_IRQL_requires_min_(PASSIVE_LEVEL)\n_IRQL_requires_same_\nVOID\nKeEnumerateQueueApc(\n\t_Inout_ PKTHREAD Thread,\n\t_In_ PKENUM_ROUTINE CallbackRoutine,\n\t_In_ PVOID Context,\n\t_In_opt_ KPROCESSOR_MODE *ApcMode\n);\n\n\nNTKERNELAPI\n_IRQL_requires_same_\n_When_(Environment != OriginalApcEnvironment, __drv_reportError(\"Caution: \"\n\t\"Using an APC environment other than the original environment can lead to \"\n\t\"a system bugcheck if the target thread is attached to a process with APCs \"\n\t\"disabled. APC environments should be used with care.\"))\n\tVOID\n\tKeInitializeApc(\n\t\t_Out_ PRKAPC Apc,\n\t\t_In_ PRKTHREAD Thread,\n\t\t_In_ KAPC_ENVIRONMENT Environment,\n\t\t_In_ PKKERNEL_ROUTINE KernelRoutine,\n\t\t_In_opt_ PKRUNDOWN_ROUTINE RundownRoutine,\n\t\t_In_opt_ PKNORMAL_ROUTINE NormalRoutine,\n\t\t_In_opt_ KPROCESSOR_MODE ProcessorMode,\n\t\t_In_opt_ PVOID NormalContext\n\t);\n\nNTKERNELAPI\n_Must_inspect_result_\n_IRQL_requires_max_(DISPATCH_LEVEL)\n_IRQL_requires_min_(PASSIVE_LEVEL)\n_IRQL_requires_same_\nBOOLEAN\nKeInsertQueueApc(\n\t_Inout_ PRKAPC Apc,\n\t_In_opt_ PVOID SystemArgument1,\n\t_In_opt_ PVOID SystemArgument2,\n\t_In_ KPRIORITY Increment\n);\n\n\n\nNTSYSAPI\nNTSTATUS\nNTAPI\nZwOpenThread(\n\tOUT PHANDLE             ThreadHandle,\n\tIN ACCESS_MASK          DesiredAccess,\n\tIN POBJECT_ATTRIBUTES   ObjectAttributes,\n\tIN PCLIENT_ID           ClientId\n);\n\n\n\nstruct PTEStruct\n{\n\tunsigned P         :  1; // present (1 = present)\n\tunsigned RW        :  1; // read/write\n\tunsigned US        :  1; // user/supervisor\n\tunsigned PWT       :  1; // page-level write-through\n\tunsigned PCD       :  1; // page-level cache disabled\n\tunsigned A         :  1; // accessed\n\tunsigned Reserved  :  1; // dirty\n\tunsigned PS        :  1; // page size (0 = 4-KB page)\n\tunsigned G         :  1; // global page\n\tunsigned A1\t\t   :  1; // available 1 aka copy-on-write\n\tunsigned A2\t\t   :  1; // available 2/ is 1 when paged to disk\n\tunsigned A3\t\t   :  1; // available 3\n\tunsigned PFN       : 20; // page-frame number\n};\n\n//typedef struct PTEStruct *PPDPTE;\n//typedef struct PTEStruct *PPDE;\n//typedef struct PTEStruct *PPTE;\n\nstruct PTEStruct64\n{\n\tunsigned long long P : 1; // present (1 = present)\n\tunsigned long long RW : 1; // read/write\n\tunsigned long long US : 1; // user/supervisor\n\tunsigned long long PWT : 1; // page-level write-through\n\tunsigned long long PCD : 1; // page-level cache disabled\n\tunsigned long long A : 1; // accessed\n\tunsigned long long Reserved : 1; // dirty\n\tunsigned long long PS : 1; // page size (0 = 4-KB page)\n\tunsigned long long G : 1; // global page\n\tunsigned long long A1 : 1; // available 1 aka copy-on-write\n\tunsigned long long A2 : 1; // available 2/ is 1 when paged to disk\n\tunsigned long long A3 : 1; // available 3\n\tunsigned long long PFN : 52; // page-frame number\n};\n\n//typedef struct PTEStruct64 *PPDPTE_PAE;\n//typedef struct PTEStruct64 *PPDE_PAE;\n//typedef struct PTEStruct64 *PPTE_PAE;\n\n\ntypedef struct tagDebugregs\n{\n\tULONG DR0;\n\tULONG DR1;\n\tULONG DR2;\n\tULONG DR3;\n\tULONG DR5;\n\tULONG DR6;\n\tULONG DR7;\n} Debugregs;\n\n\n\ntypedef struct \n{\n\tunsigned CF\t\t\t:1; // 0\n\tunsigned reserved1\t:1; // 1\n\tunsigned PF\t\t\t:1; // 2\n\tunsigned reserved2\t:1; // 3\n\tunsigned AF\t\t\t:1; // 4\n\tunsigned reserved3\t:1; // 5\n\tunsigned ZF\t\t\t:1; // 6\n\tunsigned SF\t\t\t:1; // 7\n\tunsigned TF\t\t\t:1; // 8\n\tunsigned IF\t\t\t:1; // 9\n\tunsigned DF\t\t\t:1; // 10\n\tunsigned OF\t\t\t:1; // 11\n\tunsigned IOPL\t\t:2; // 12+13\n\tunsigned NT\t\t\t:1; // 14\n\tunsigned reserved4\t:1; // 15\n\tunsigned RF\t\t\t:1; // 16\n\tunsigned VM\t\t\t:1; // 17\n\tunsigned AC\t\t\t:1; // 18\n\tunsigned VIF\t\t:1; // 19\n\tunsigned VIP\t\t:1; // 20\n\tunsigned ID\t\t\t:1; // 21\n\tunsigned reserved5\t:10; // 22-31\n#ifdef AMD64\n\tunsigned reserved6\t:8;\n\tunsigned reserved7\t:8;\n\tunsigned reserved8\t:8;\n\tunsigned reserved9\t:8;\n#endif\n} EFLAGS,*PEFLAGS;\n\ntypedef struct tagDebugReg7\n{\n\tunsigned L0\t\t\t:1; //\t\t\t0\n\tunsigned G0\t\t\t:1; //\t\t\t1\n\tunsigned L1\t\t\t:1; //\t\t\t2\n\tunsigned G1\t\t\t:1; //\t\t\t3\n\tunsigned L2\t\t\t:1; //\t\t\t4\n\tunsigned G2\t\t\t:1; //\t\t\t5\n\tunsigned L3\t\t\t:1; //\t\t\t6\n\tunsigned G3\t\t\t:1; //\t\t\t7\n\tunsigned GL\t\t\t:1; //\t\t\t8\n\tunsigned GE\t\t\t:1; //\t\t\t9\n\tunsigned undefined_1: 1; //1       10\n\tunsigned RTM\t\t: 1; //        11\n\tunsigned undefined_0: 1; //0       12\n\tunsigned GD\t\t\t:1; //\t\t   13\n\tunsigned undefined2\t:2; // 00 \n\tunsigned RW0\t\t:2;\n\tunsigned LEN0\t\t:2;\n\tunsigned RW1\t\t:2;\n\tunsigned LEN1\t\t:2;\n\tunsigned RW2\t\t:2;\n\tunsigned LEN2\t\t:2;\n\tunsigned RW3\t\t:2;\n\tunsigned LEN3\t\t:2;\n#ifdef AMD64\n\tunsigned undefined3\t:8;\n\tunsigned undefined4\t:8;\n\tunsigned undefined5\t:8;\n\tunsigned undefined6\t:8;\n#endif\n} DebugReg7;\n\ntypedef struct DebugReg6\n{\n\tunsigned B0\t\t\t:1;\n\tunsigned B1\t\t\t:1;\n\tunsigned B2\t\t\t:1;\n\tunsigned B3\t\t\t:1;\n\tunsigned undefined1\t:9; // 011111111\n\tunsigned BD\t\t\t:1;\n\tunsigned BS\t\t\t:1;\n\tunsigned BT\t\t\t:1;\n\tunsigned RTM       : 1; //0=triggered\n\tunsigned undefined2\t:15; // 111111111111111\n#ifdef AMD64\n\tunsigned undefined3\t:8;\n\tunsigned undefined4\t:8;\n\tunsigned undefined5\t:8;\n\tunsigned undefined6\t:8;\n#endif\n} DebugReg6;\n\n\n\n\n#pragma pack(2) //allignment of 2 bytes\ntypedef struct tagGDT\n{    \n    WORD wLimit;\n\tPVOID vector;\n} GDT, *PGDT;\n#pragma pack()\n\n//UCHAR BufferSize;\n\nvoid GetIDT(PIDT pIdt);\n\n#ifdef AMD64\nextern void _fxsave(volatile void *);\nextern void GetGDT(PGDT pGdt);\nextern WORD GetLDT();\nextern WORD GetTR(void);\n#else\nvoid GetGDT(PGDT pGdt);\nWORD GetLDT();\nWORD GetTR(void);\n#endif\n\n\n\nUINT64 readMSR(DWORD msr);\nUINT64 getDR7(void);\nvoid setCR0(UINT64 newCR0);\nUINT64 getCR0(void);\nUINT64 getCR2(void);\nvoid setCR3(UINT64 newCR3);\nUINT64 getCR3(void);\nUINT64 getCR4(void);\nvoid setCR4(UINT64 newcr4);\nUINT64 getTSC(void);\n\n#ifdef AMD64\n\nextern WORD getCS(void);\nextern WORD getSS(void);\nextern WORD getDS(void);\nextern WORD getES(void);\nextern WORD getFS(void);\nextern WORD getGS(void);\nextern UINT64 getRSP(void);\nextern UINT64 getRBP(void);\nextern UINT64 getRAX(void);\nextern UINT64 getRBX(void);\nextern UINT64 getRCX(void);\nextern UINT64 getRDX(void);\nextern UINT64 getRSI(void);\nextern UINT64 getRDI(void);\n#else\nWORD getCS(void);\nWORD getSS(void);\nWORD getDS(void);\nWORD getES(void);\nWORD getFS(void);\nWORD getGS(void);\nULONG getRSP(void);\nULONG getRBP(void);\nULONG getRAX(void);\nULONG getRBX(void);\nULONG getRCX(void);\nULONG getRDX(void);\nULONG getRSI(void);\nULONG getRDI(void);\n#endif\n\nextern UINT64 getR8(void);\nextern UINT64 getR9(void);\nextern UINT64 getR10(void);\nextern UINT64 getR11(void);\nextern UINT64 getR12(void);\nextern UINT64 getR13(void);\nextern UINT64 getR14(void);\nextern UINT64 getR15(void);\n\nextern UINT64 getAccessRights(UINT64 segment);\nextern UINT64 getSegmentLimit(UINT64 segment);\n\n\nint getCpuCount(void);\n\nBOOL loadedbydbvm;\nint PTESize;\nUINT_PTR PAGE_SIZE_LARGE;\nUINT_PTR MAX_PDE_POS;\nUINT_PTR MAX_PTE_POS;\n\nint cpu_stepping;\nint cpu_model;\nint cpu_familyID;\nint cpu_type;\nint cpu_ext_modelID;\nint cpu_ext_familyID;\n\nint KernelCodeStepping;\nint KernelWritesIgnoreWP;\n\nint isPrefix(unsigned char b);\nEFLAGS getEflags(void);\nint cpunr(void);\nvoid disableInterrupts(void);\nvoid enableInterrupts(void);\n\n\nvoid csEnter(PcriticalSection CS);\nvoid csLeave(PcriticalSection CS);\n\nvoid forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);\nvoid forEachCpu(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);\nvoid forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID  SystemArgument1, PVOID  SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);\nvoid forEachCpuPassive(PF f, UINT_PTR param);\n\n#endif;"
  },
  {
    "path": "src/IOPLDispatcher.c",
    "content": "#pragma warning( disable: 4100 4101 4103 4189)\n\n\n#include \"IOPLDispatcher.h\"\n#include \"DBKFunc.h\"\n#include \"DBKDrvr.h\"\n\n\n#include \"memscan.h\"\n\n#include \"deepkernel.h\"\n\n#include \"processlist.h\"\n#include \"threads.h\"\n\n#include \"interruptHook.h\"\n#include \"debugger.h\"\n\n#include \"vmxhelper.h\"\n#include \"vmxoffload.h\"\n#include \"ultimap.h\"\n#include \"ultimap2.h\"\n\n\nUINT64 PhysicalMemoryRanges=0; //initialized once, and used thereafter. If the user adds/removes ram at runtime, screw him and make him the reload the driver\nUINT64 PhysicalMemoryRangesListSize=0;\n\n#if (NTDDI_VERSION >= NTDDI_VISTA)\nPVOID DRMHandle = NULL;\nPEPROCESS DRMProcess = NULL;\nPEPROCESS DRMProcess2 = NULL;\n#endif\n\ntypedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process); \nGET_PROCESS_IMAGE_NAME PsGetProcessImageFileName; \n\n\n/*\ntypedef struct\n{\n\tint listcount;\n\tchar cpunrs[255];\n} CPULISTFILLSTRUCT, *PCPULISTFILLSTRUCT;\n\nVOID GetCPUIDS_all(PCPULISTFILLSTRUCT p)\n{\n\tDbgPrint(\"GetCPUIDS_all(for cpu %d)\\n\", cpunr());\n\tif (p->listcount<255)\n\t{\n\t\tp->cpunrs[p->listcount]=cpunr();\n\t\tp->listcount++;\n\t}\n}\n*/\n\nNTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL);\n\n\n\nvoid mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\tULONG_PTR iswow64;\n\tExFreePool(Apc);\n\tDbgPrint(\"My second kernelmode apc!!!!\\n\");\n\tDbgPrint(\"SystemArgument1=%x\\n\",*(PULONG)SystemArgument1);\n\tDbgPrint(\"SystemArgument2=%x\\n\", *(PULONG)SystemArgument2);\n\n\tif (ZwQueryInformationProcess(ZwCurrentProcess(), ProcessWow64Information, &iswow64, sizeof(iswow64), NULL) == STATUS_SUCCESS)\n\t{\n#if (NTDDI_VERSION >= NTDDI_VISTA)\t\n\t\tif (iswow64)\n\t\t{\n\t\t\tDbgPrint(\"WOW64 apc\");\n\t\t\tPsWrapApcWow64Thread(NormalContext, (PVOID*)NormalRoutine);\n\t\t}\n#endif\n\t}\n\n}\n\nvoid nothing2(PVOID arg1, PVOID arg2, PVOID arg3)\n{\n\t\n\treturn;\n}\n\nvoid mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\t//kernelmode apc, always gets executed\n\tPKAPC      kApc;\n\tLARGE_INTEGER Timeout;\n\n\tkApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));\n\n\tExFreePool(Apc);\n\n\tDbgPrint(\"My kernelmode apc!!!!(irql=%d)\\n\", KeGetCurrentIrql());\n\t\n\tDbgPrint(\"NormalRoutine=%p\\n\",*(PUINT_PTR)NormalRoutine);\n\tDbgPrint(\"NormalContext=%p\\n\",*(PUINT_PTR)NormalContext);\n\tDbgPrint(\"SystemArgument1=%p\\n\",*(PUINT_PTR)SystemArgument1);\n\tDbgPrint(\"SystemArgument2=%p\\n\",*(PUINT_PTR)SystemArgument2);\n\t\n\t\n\t\n\tKeInitializeApc(kApc,\n\t\t            (PKTHREAD)PsGetCurrentThread(),\n                    0,\n                    (PKKERNEL_ROUTINE)mykapc2,\n                    NULL,\n                    (PKNORMAL_ROUTINE)*(PUINT_PTR)SystemArgument1,\n                    UserMode,\n                    (PVOID)*(PUINT_PTR)NormalContext\n                    );\n\n\tKeInsertQueueApc (kApc, (PVOID)*(PUINT_PTR)SystemArgument1, (PVOID)*(PUINT_PTR)SystemArgument2, 0);\n\n\n\t//wait in usermode (so interruptable by a usermode apc)\n\tTimeout.QuadPart = 0;\n\tKeDelayExecutionThread(UserMode, TRUE, &Timeout);\n\n\treturn;\n}\n\nvoid nothing(PVOID arg1, PVOID arg2, PVOID arg3)\n{\n\treturn;\n}\n\n\nvoid CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)\n{\n\t\n\tPKTHREAD   kThread;\n\tPKAPC      kApc;\n\n\tkApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));\n\n\tkThread=(PKTHREAD)getPEThread(threadid);\n\tDbgPrint(\"(PVOID)KThread=%p\\n\",kThread);\n\tDbgPrint(\"addresstoexecute=%p\\n\", addresstoexecute);\n\t\n   \n\tKeInitializeApc(kApc,\n\t\t            kThread,\n                    0,\n                    (PKKERNEL_ROUTINE)mykapc,\n                    NULL,\n                    (PKNORMAL_ROUTINE)nothing,\n                    KernelMode,\n                    0\n                    );\n\n\tKeInsertQueueApc (kApc, addresstoexecute, addresstoexecute, 0);\n}\n\n#define PROCESS_TERMINATE                  (0x0001)  \n#define PROCESS_CREATE_THREAD              (0x0002)  \n#define PROCESS_SET_SESSIONID              (0x0004)  \n#define PROCESS_VM_OPERATION               (0x0008)  \n#define PROCESS_VM_READ                    (0x0010)  \n#define PROCESS_VM_WRITE                   (0x0020)  \n#define PROCESS_DUP_HANDLE                 (0x0040)  \n#define PROCESS_CREATE_PROCESS             (0x0080)  \n#define PROCESS_SET_QUOTA                  (0x0100)  \n#define PROCESS_SET_INFORMATION            (0x0200)  \n#define PROCESS_QUERY_INFORMATION          (0x0400)  \n#define PROCESS_SUSPEND_RESUME             (0x0800)  \n#define PROCESS_QUERY_LIMITED_INFORMATION  (0x1000)  \n\n\n#if (NTDDI_VERSION >= NTDDI_VISTA)\nOB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)\n{\t\t\n\tif (DRMProcess == NULL)\n\t\treturn OB_PREOP_SUCCESS;\n\n\tif (PsGetCurrentProcess() == DRMProcess)\n\t\treturn OB_PREOP_SUCCESS;\n\n\tif (OperationInformation->ObjectType == *PsThreadType)\n\t{\t\t\n\t\tif ((PsGetProcessId(DRMProcess) == PsGetThreadProcessId(OperationInformation->Object)) || ((DRMProcess2) && (PsGetProcessId(DRMProcess2) == PsGetThreadProcessId(OperationInformation->Object))))\n\t\t{\n\t\t\t//probably block it\n\n\t\t\tif (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)\n\t\t\t{\n\t\t\t\t//create handle\t\t\t\n\n\t\t\t\tACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;\n\n\t\t\t\tDbgPrint(\"PID %d opened a handle to the a CE thread with access mask %x\", PsGetCurrentProcessId(), da);\n\n\t\t\t\tda = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);\n\n\t\t\t\tOperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;\n\t\t\t}\n\t\t\telse if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)\n\t\t\t{\n\t\t\t\t//duplicate handle\n\t\t\t\tACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;\n\n\t\t\t\tDbgPrint(\"PID %d duplicated a handle to a CE thread with access mask %x\", PsGetCurrentProcessId(), da);\n\n\t\t\t\tda = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);\n\t\t\t\tOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;\n\t\t\t}\n\t\t}\n\t}\n\treturn OB_PREOP_SUCCESS;\n}\n\n\nVOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)\n{\n\t//DbgPrint(\"ProcessPostCallback\");\n}\n\n\nOB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)\n{\n\tif (DRMProcess == NULL)\n\t\treturn OB_PREOP_SUCCESS;\n\n\t//if (PsGetCurrentProcess() == DRMProcess)\n\t//\treturn OB_PREOP_SUCCESS;\n\n\tif (OperationInformation->ObjectType == *PsProcessType)\n\t{\n\t\tif ((OperationInformation->Object == DRMProcess) || (OperationInformation->Object == DRMProcess2))\n\t\t{\n\t\t\t//probably block it\n\n\t\t\tif (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)\n\t\t\t{\n\t\t\t\t//create handle\t\t\t\n\t\t\t\t\n\t\t\t\tACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;\n\n\t\t\t\tDbgPrint(\"PID %d(%p) opened a handle to the CE process(%p) with access mask %x\", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);\n\n\t\t\t\tda = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);\n\n\t\t\t\t//da = da & PROCESS_SUSPEND_RESUME;\n\n\t\t\t\tOperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;\n\t\t\t}\n\t\t\telse if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)\n\t\t\t{\n\t\t\t\t//duplicate handle\n\t\t\t\tACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;\n\n\t\t\t\tDbgPrint(\"PID %d(%p) opened a handle to the CE process(%p) with access mask %x\", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);\n\n\n\t\t\t\tda = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);\n\n\t\t\t\t//da = da & PROCESS_SUSPEND_RESUME;\n\n\t\t\t\tOperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;\n\t\t\t}\n\t\t}\n\t}\n\treturn OB_PREOP_SUCCESS;\n}\n\n\nVOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)\n{\n\t//DbgPrint(\"ProcessPostCallback\");\n}\n#endif\n\n\nBOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned)\n/*\nCalled if dbvm has loaded the driver. Use this to setup a fake irp\n*/\n{\n\t//allocate a in and out buffer\n\t//setup a fake IRP\n\tIRP FakeIRP;\n\tBOOL r;\n\tPVOID buffer;\n\tbuffer=ExAllocatePool(PagedPool, max(nInBufferSize, nOutBufferSize));\n\tRtlCopyMemory(buffer, lpInBuffer, nInBufferSize);\t\n\n\n\tDbgPrint(\"DispatchIoctlDBVM\\n\");\n\n\tFakeIRP.AssociatedIrp.SystemBuffer=buffer;\n\tFakeIRP.Flags=IoControlCode; //(ab)using an unused element\n\n\tr=DispatchIoctl(DeviceObject, &FakeIRP)==STATUS_SUCCESS;\n\n\n\tRtlCopyMemory(lpOutBuffer, buffer, nOutBufferSize);\n\n\tExFreePool(buffer);\n\n\treturn r;\n}\n\nNTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)\n{\n\tNTSTATUS ntStatus=STATUS_UNSUCCESSFUL;\n\n    PIO_STACK_LOCATION     irpStack=NULL;\n\tLUID sedebugprivUID;\n\tULONG IoControlCode;\n\n\tif (!loadedbydbvm)\n\t{\n\t\tirpStack=IoGetCurrentIrpStackLocation(Irp);\n\t\tIoControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;\n\t}\n\telse\n\t\tIoControlCode=Irp->Flags;\n\t\t\n\t//DbgPrint(\"DispatchIoctl. IoControlCode=%x\\n\", IoControlCode);\n#ifdef TOBESIGNED\n    sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;\n\tsedebugprivUID.HighPart=0;\n\t\n\tif (SeSinglePrivilegeCheck(sedebugprivUID, UserMode)==FALSE)\n\t{\n\t\tDbgPrint(\"DispatchIoctl called by a process without SeDebugPrivilege\");\n\t\treturn STATUS_UNSUCCESSFUL;\n\t}\n#endif\n\t\n\n\t\n    switch(IoControlCode)\n    {\n\t\t\n        case IOCTL_CE_READMEMORY:\t\t\t\n\t\t\t__try\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 processid;\n\t\t\t\t\tUINT64 startaddress;\n\t\t\t\t\tWORD bytestoread;\n\t\t\t\t} *pinp;\n\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tntStatus=ReadProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestoread,pinp) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;\n\t\t\t}\n\t\t\t__except(1)\n\t\t\t{\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t};\n\t\t\t\t\n            break;\n\t\t\t\n\n        case IOCTL_CE_WRITEMEMORY:\n\t\t\t__try\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 processid;\n\t\t\t\t\tUINT64 startaddress;\n\t\t\t\t\tWORD bytestowrite;\n\t\t\t\t} *pinp,inp;\n\n\t\t\t\tDbgPrint(\"sizeof(inp)=%d\\n\",sizeof(inp));\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tntStatus=WriteProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestowrite,(PVOID)((UINT_PTR)pinp+sizeof(inp))) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;\n\t\t\t}\n\t\t\t__except(1)\n\t\t\t{\n\t\t\t\t//something went wrong and I don't know what\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t};\n\n\n\t\t\t\t\n            break;\n\n\n\t\tcase IOCTL_CE_OPENPROCESS:\n\t\t\t{\t\t\t\t\t\n\t\t\t\tPEPROCESS selectedprocess = NULL;\n\t\t\t\tULONG processid=*(PULONG)Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tHANDLE ProcessHandle = GetHandleForProcessID((HANDLE)processid);\n\t\t\t\tstruct out\n\t\t\t\t{\n\t\t\t\t\tUINT64 h;\n\t\t\t\t\tBYTE   Special;\n\t\t\t\t} *POutput = Irp->AssociatedIrp.SystemBuffer;\n\n\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\tif (ProcessHandle == 0)\n\t\t\t\t{\n\t\t\t\t\tPOutput->Special = 0;\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tProcessHandle = 0;\n\n\t\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t\t\t{\n\n\t\t\t\t\t\t\t//DbgPrint(\"Calling ObOpenObjectByPointer\\n\");\n\t\t\t\t\t\t\tntStatus = ObOpenObjectByPointer(\n\t\t\t\t\t\t\t\tselectedprocess,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tNULL,\n\t\t\t\t\t\t\t\tPROCESS_ALL_ACCESS,\n\t\t\t\t\t\t\t\t*PsProcessType,\n\t\t\t\t\t\t\t\tKernelMode, //UserMode,\n\t\t\t\t\t\t\t\t&ProcessHandle);\n\n\t\t\t\t\t\t\t//DbgPrint(\"ntStatus=%x\",ntStatus);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t__except (1)\n\t\t\t\t\t{\n\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//DbgPrint(\"ProcessHandle=%x\", (int)ProcessHandle);\n\t\t\t\t\tPOutput->Special = 1;\t\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\tif (selectedprocess)\n\t\t\t\t{\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tPOutput->h=(UINT64)ProcessHandle;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_OPENTHREAD:\n\t\t\t{\n\t\t\t\tHANDLE ThreadHandle;\n\t\t\t\tCLIENT_ID ClientID;\n\t\t\t\tOBJECT_ATTRIBUTES ObjectAttributes;\n\t\n\t\t\t\tRtlZeroMemory(&ObjectAttributes,sizeof(OBJECT_ATTRIBUTES));\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tClientID.UniqueProcess=0;\n\t\t\t\tClientID.UniqueThread=(HANDLE)(UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tThreadHandle=0;\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tThreadHandle=0;\n\t\t\t\t\tntStatus=ZwOpenThread(&ThreadHandle,PROCESS_ALL_ACCESS,&ObjectAttributes,&ClientID);\t\t\t\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\t\t\t\n\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)ThreadHandle;\n\t\t\t\t\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t\n\t\tcase IOCTL_CE_MAKEWRITABLE:\n\t\t\t{\n#ifdef AMD64\n\t\t\t\t//untill I know how win64 handles paging, not implemented\n#else\n\t\t\t\tstruct InputBuf\n\t\t\t\t{\n\t\t\t\t    UINT64 StartAddress;\n\t\t\t\t\tULONG Size;\n\t\t\t\t\tBYTE CopyOnWrite;\n\t\t\t\t} *PInputBuf;\n\n\t\t\t\tPInputBuf=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\t\n\t\t\t\tntStatus=MakeWritable((PVOID)(UINT_PTR)PInputBuf->StartAddress,PInputBuf->Size,(PInputBuf->CopyOnWrite==1)) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; \n#endif\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\n\t\tcase IOCTL_CE_QUERY_VIRTUAL_MEMORY:\n\t\t\t{\n\t\t\t\tstruct InputBuf\n\t\t\t\t{\n\t\t\t\t    UINT64 ProcessID;\n\t\t\t\t\tUINT64 StartAddress;\n\t\t\t\t} *PInputBuf;\n\n\t\t\t\tstruct OutputBuf\n\t\t\t\t{\t\t\t\t\n\t\t\t\t\tUINT64 length;\n\t\t\t\t\tDWORD protection;\n\t\t\t\t} *POutputBuf;\n\n\t\t\t\t\n\t\t\t     \n\t\t\t\tUINT_PTR BaseAddress;\n\t\t\t\tUINT_PTR length;\n\t\t\t\tBOOL ShowResult=0;\n\n\t\t\t\t\n                ntStatus=STATUS_SUCCESS;\n\t\t\t\tPInputBuf=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tPOutputBuf=Irp->AssociatedIrp.SystemBuffer;\n\n\n\t\t\t\tif (PInputBuf->StartAddress==(UINT64)0x12000)\n\t\t\t\t\tShowResult=1;\n\t\t\t\t\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tntStatus = GetMemoryRegionData((DWORD)PInputBuf->ProcessID, NULL, (PVOID)(UINT_PTR)(PInputBuf->StartAddress), &(POutputBuf->protection), &length, &BaseAddress);\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"GetMemoryRegionData error\");\n\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tPOutputBuf->length=(UINT64)length;\n\n\t\t\t\tif (ShowResult)\n\t\t\t\t{\t\t\t\t\t\t\t\t\t\n\t\t\t\t  DbgPrint(\"GetMemoryRegionData returned %x\\n\",ntStatus);\n\t\t\t\t  DbgPrint(\"protection=%x\\n\",POutputBuf->protection);\n\t\t\t\t  DbgPrint(\"length=%p\\n\",POutputBuf->length);\n\t\t\t\t  DbgPrint(\"BaseAddress=%p\\n\", BaseAddress);\n\t\t\t\t}\n\n\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_TEST: //just a test to see it's working\n\t\t\t{\n\t\t\t\tUNICODE_STRING test;\n\t\t\t\tPVOID x;\n\t\t\t\tQWORD a, b;\n\n\t\t\t\t_disable();\n\t\t\t\ta = __rdtsc();\n\t\t\t\tb = __rdtsc();\n\n\t\t\t\t_enable();\n\n\t\t\t\t\n\t\t\t\tDbgPrint(\"%d\\n\", (int)(b - a));\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_GETPETHREAD:\n\t\t\t{\n\t\t\t\t\n\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)getPEThread((UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer);\n\t\t\t\tntStatus= STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_GETPEPROCESS:\n\t\t\t{\n\t\t\t\tDWORD processid=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tPEPROCESS selectedprocess;\n\t\t\t\n\n\t\t\t\tif (processid==0)\n\t\t\t\t{\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid),&selectedprocess)==STATUS_SUCCESS)\n\t\t\t\t\t{\n#ifdef AMD64\n\t\t\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)selectedprocess;\n#else\n\t\t\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(DWORD)selectedprocess;\n#endif\n\t\t\t\t\t\t//DbgPrint(\"PEProcess=%llx\\n\", *(PUINT64)Irp->AssociatedIrp.SystemBuffer);\n\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;\n\t\t\t\t}\n\n\t\t\t\t\n\n\t\t\t\tntStatus= STATUS_SUCCESS;\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t\n\t\tcase IOCTL_CE_READPHYSICALMEMORY:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 startaddress;\n\t\t\t\t\tUINT64 bytestoread;\n\t\t\t\t} *pinp;\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_READPHYSICALMEMORY:pinp->startaddress=%x, pinp->bytestoread=%d\", pinp->startaddress, pinp->bytestoread); \n\n\n\t\t\t\tntStatus = ReadPhysicalMemory((PVOID)(UINT_PTR)pinp->startaddress, (UINT_PTR)pinp->bytestoread, pinp);\n\t\t\t\tbreak;\n\n\n\n\t\t\t}\n\n\t\tcase IOCTL_CE_WRITEPHYSICALMEMORY:\n\t\t\t{\n\t\t\t\tHANDLE\t\t\tphysmem;\n\t\t\t\tUNICODE_STRING\tphysmemString;\n\t\t\t\tOBJECT_ATTRIBUTES attributes;\n\t\t\t\tWCHAR\t\t\tphysmemName[] = L\"\\\\device\\\\physicalmemory\";\n\t\t\t\tUCHAR*\t\t\tmemoryview;\n\n\t\t\t\tRtlInitUnicodeString( &physmemString, physmemName );\t\n\n            \tInitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );\t\n\t\t\t    ntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );\n\t\t\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t//hey look, it didn't kill it\n\t\t\t\t\tstruct input\n\t\t\t\t\t{\n\t\t\t\t\t\tUINT64 startaddress;\n\t\t\t\t\t\tUINT64 bytestoread;\n\t\t\t\t\t} *pinp;\n\n\t\t\t\t\tUCHAR* pinp2;\n\n\t\t\t\t\tSIZE_T length;\n\t\t\t\t\tPHYSICAL_ADDRESS\tviewBase;\n\t\t\t\t\tUINT_PTR offset;\n\t\t\t\t\tUINT_PTR toread;\n\n\t\t\t\t\t\n\t\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\t\tpinp2=(UCHAR *)pinp;\n\t\t\t\t\tviewBase.QuadPart = (ULONGLONG)(pinp->startaddress);\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tlength=0x2000;//pinp->bytestoread;\n\t\t\t\t\ttoread=(UINT_PTR)pinp->bytestoread;\n\n\t\t\t\t\tmemoryview=NULL;\n\t\t\t\t\tntStatus=ZwMapViewOfSection(\n\t\t\t\t\t\tphysmem,  //sectionhandle\n\t\t\t\t\t\tNtCurrentProcess(), //processhandle\n\t\t\t\t\t\t&memoryview, //BaseAddress\n\t\t\t\t\t\t0L, //ZeroBits\n\t\t\t\t\t\tlength, //CommitSize\n\t\t\t\t\t\t&viewBase, //SectionOffset\n\t\t\t\t\t\t&length, //ViewSize\n\t\t\t\t\t\tViewShare,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\tPAGE_READWRITE);\n\n\t\t\t\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t\t\t\t{\n                        offset=(UINT_PTR)(pinp->startaddress)-(UINT_PTR)viewBase.QuadPart;\n\t\t\t\t\t\tRtlCopyMemory(&memoryview[offset],&pinp2[16],toread);\n\n\t\t\t\t\t\tZwUnmapViewOfSection(\n\t\t\t\t\t\t\tNtCurrentProcess(), //processhandle\n\t\t\t\t\t\t\tmemoryview);\n\t\t\t\t\t}\n\n\t\t\t\t\tZwClose(physmem);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t\n\n\t\tcase IOCTL_CE_GETPHYSICALADDRESS:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64  ProcessID;\n\t\t\t\t\tUINT64 BaseAddress; \n\t\t\t\t} *pinp;\n\n\t\t\t\tPEPROCESS selectedprocess;\n\t\t\t\tPHYSICAL_ADDRESS physical;\n\t\t\t\tphysical.QuadPart = 0;\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\t//DbgPrint(\"IOCTL_CE_GETPHYSICALADDRESS. ProcessID(%p)=%x BaseAddress(%p)=%x\\n\",&pinp->ProcessID, pinp->ProcessID, &pinp->BaseAddress, pinp->BaseAddress);\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\t//switch to the selected process\n\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(pinp->ProcessID),&selectedprocess)==STATUS_SUCCESS)\n\t\t\t\t\t{\n\t\t\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\t\t\tRtlZeroMemory(&apc_state,sizeof(apc_state));\t\t\t\t\t\n    \t\t\t\t\tKeStackAttachProcess((PVOID)selectedprocess,&apc_state);\n                 \n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tphysical=MmGetPhysicalAddress((PVOID)(UINT_PTR)pinp->BaseAddress);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__finally\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t\t\t}\n\t\n\n\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t//DbgPrint(\"physical.LowPart=%x\",physical.LowPart);\n                    RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&physical.QuadPart,8);\n\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_GETMEMORYRANGES:\n\t\t\t{\n\t\t\t\t\n\t\t\t\tstruct output\n\t\t\t\t{\n\t\t\t\t\tUINT64 address;\n\t\t\t\t\tUINT64 size;\n\t\t\t\t} *poutp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_GETMEMORYRANGES\\n\");\n\n\n\t\t\t\tif (PhysicalMemoryRanges==0)\n\t\t\t\t{\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tPPHYSICAL_MEMORY_RANGE mr=MmGetPhysicalMemoryRanges();\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (mr)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//find the end\n\t\t\t\t\t\t\tint i;\n\t\t\t\t\t\t\tPhysicalMemoryRanges=(UINT64)mr;\n\t\t\t\t\t\t\tfor (i=0; mr[i].NumberOfBytes.QuadPart || mr[i].BaseAddress.QuadPart; i++);\n\n\t\t\t\t\t\t\tPhysicalMemoryRangesListSize=(UINT64)(&mr[i])-(UINT64)(&mr[0]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\n\n\t\t\t\t\t}\n\t\t\t\t\t__except(1)\n\t\t\t\t\t{\n\t\t\t\t\t\t//just in case this function decides to bug out in the future\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tpoutp->address=PhysicalMemoryRanges;\n\t\t\t\tpoutp->size=PhysicalMemoryRangesListSize;\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\tcase IOCTL_CE_GETSDTADDRESS:\n\t\t\t{\n\t\t\t\tDbgPrint(\"Obsolete\\n\");\n\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_GETCR0:\n\t\t\t{\n\t\t\t\t*(UINT64*)Irp->AssociatedIrp.SystemBuffer=getCR0();\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_GETCR4:\n\t\t\t{\n\t\t\t\t//seems CR4 isn't seen as a register...\n\t\t\t\t*(UINT64*)Irp->AssociatedIrp.SystemBuffer=(UINT64)getCR4();\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_SETCR4:\n\t\t\t{\n\t\t\t\t//seems CR4 isn't seen as a register...\n\t\t\t\tULONG cr4reg=*(ULONG*)Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tsetCR4((UINT64)cr4reg);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_GETCR3:\n\t\t\t{\n\t\t\t\tUINT_PTR cr3reg=0;\n\t\t\t\tPEPROCESS selectedprocess;\n\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\t//switch context to the selected process.  (processid is stored in the systembuffer)\n\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(*(ULONG*)Irp->AssociatedIrp.SystemBuffer),&selectedprocess)==STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\t\t\tRtlZeroMemory(&apc_state,sizeof(apc_state));\t\t\t\t\t\n    \t\t\t\t\tKeStackAttachProcess((PVOID)selectedprocess,&apc_state);\n\n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcr3reg=(UINT_PTR)getCR3();\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__finally\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\t__except(1)\n\t\t\t\t\t{\n\t\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\n\t\t\t\t}\n\n\t\t\t\tDbgPrint(\"cr3reg=%p\\n\",cr3reg);\n\n\t\t\t\t*(UINT64*)Irp->AssociatedIrp.SystemBuffer=cr3reg;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t\n\n\t\tcase IOCTL_CE_GETSDT:\n\t\t\t{\n\t\t\t\t//returns the address of KeServiceDescriptorTable\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\tbreak;\n\t\t\t}\t\n\t\t\t\n\n\n\t\tcase IOCTL_CE_GETIDT:\n\t\t\t{\n\t\t\t\t//returns the address of the IDT of the current CPU\n\t\t\t\tIDT idt;\n\t\t\t\tRtlZeroMemory(&idt,sizeof(IDT));\t\t\t\t\n\t\t\t\tGetIDT(&idt);\n\t\t\t\tRtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); //so that the 32-bit version doesn't have to deal with garbage at the end\n\t\t\t\tRtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&idt,sizeof(IDT)); //copy idt\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\t\n\n\t\tcase IOCTL_CE_GETGDT:\n\t\t\t{\n\t\t\t\t//returns the address of the IDT of the current CPU\n\t\t\t\tGDT gdt;\n\t\t\t\tRtlZeroMemory(&gdt,sizeof(GDT));\n\t\t\t\tGetGDT(&gdt);\n\t\t\t\tRtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); \n\t\t\t\tRtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&gdt,sizeof(GDT)); //copy gdt\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\tcase IOCTL_CE_LAUNCHDBVM:\n\t\t\t{\n\t\t\t\tstruct intput\n\t\t\t\t{\n\t\t\t\t\tUINT64 dbvmimgpath;\t\n\t\t\t\t\tDWORD32 cpuid;\n\t\t\t\t} *pinp;\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tDbgPrint(\"IOCTL_CE_LAUNCHDBVM\\n\");\n\n\t\t\t\tinitializeDBVM((PCWSTR)(UINT_PTR)pinp->dbvmimgpath);\n\n\t\t\t\tif (pinp->cpuid == 0xffffffff) {\n\t\t\t\t\tforEachCpu(vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);\n\t\t\t\t\tcleanupDBVM();\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tforOneCpu((CCHAR)pinp->cpuid, vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);\n\n\t\t\t\tDbgPrint(\"Returned from vmxoffload()\\n\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_HOOKINTS: //hooks the DEBUG interrupts\n\t\t\t{\n\t\t\t\tDbgPrint(\"IOCTL_CE_HOOKINTS\\n\");\n\t\t\t\tforEachCpu(debugger_initHookForCurrentCPU_DPC, NULL, NULL, NULL, NULL);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\t/*\n\t\t\t\tDbgPrint(\"IOCTL_CE_HOOKINTS for cpu %d\\n\", cpunr());\n\t\t\t\tif (debugger_initHookForCurrentCPU())\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\telse\n\t\t\t\t    ntStatus=STATUS_UNSUCCESSFUL;*/\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_USERDEFINEDINTERRUPTHOOK:\n\t\t\t{\n\t\t\t\tstruct intput\n\t\t\t\t{\n\t\t\t\t\tUINT64 interruptnumber;\n\t\t\t\t\tUINT64 newCS;\n\t\t\t\t\tUINT64 newRIP;\n\t\t\t\t\tUINT64 addressofjumpback;\n\t\t\t\t} *pinp;\n\t\t\t\tDbgPrint(\"IOCTL_CE_USERDEFINEDINTERRUPTHOOK\\n\");\n\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\n\t\t\t\tinthook_HookInterrupt((unsigned char)(pinp->interruptnumber), (int)pinp->newCS, (ULONG_PTR)pinp->newRIP, (PJUMPBACK)(UINT_PTR)(pinp->addressofjumpback));\n\t\t\t\tDbgPrint(\"After the hook\\n\");\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\tcase IOCTL_CE_UNHOOKALLINTERRUPTS:\n\t\t\t{\n\t\t\t\tint i;\n\t\t\t\tDbgPrint(\"IOCTL_CE_UNHOOKALLINTERRUPTS for cpu %d\\n\",cpunr());\n\t\t\t\tfor (i=0; i<256; i++)\n\t\t\t\t\tinthook_UnhookInterrupt((unsigned char)i);\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_SETGLOBALDEBUGSTATE:\n\t\t\t{\n\t\t\t\tstruct intput\n\t\t\t\t{\n\t\t\t\t\tBOOL newstate;\n\t\t\t\t} *pinp;\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tdebugger_setGlobalDebugState(pinp->newstate);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_DEBUGPROCESS:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\tDWORD\tProcessID;\n\t\t\t\t} *pinp;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_DEBUGPROCESS\\n\");\t\t\t\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tdebugger_startDebugging(pinp->ProcessID);\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\tcase IOCTL_CE_STOPDEBUGGING:\n\t\t\t{\n\t\t\t\tdebugger_stopDebugging();\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\t\t\n\n\n\t\tcase IOCTL_CE_STARTPROCESSWATCH:\n\t\t\t{\n\t\t\t\tNTSTATUS r = STATUS_SUCCESS;\n\t\t\t\tDbgPrint(\"IOCTL_CE_STARTPROCESSWATCH\\n\");\n\n\t\t\t\tProcessWatcherOpensHandles = *(char *)Irp->AssociatedIrp.SystemBuffer != 0;\n\n\t\t\t\tif (CreateProcessNotifyRoutineEnabled && WatcherProcess)\n\t\t\t\t{\t\n\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\t\t\t\t\t\t\t\n\n\t\t\t\t//still here\n\t\t\t\tExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);\t\t\t\t\n\t\t\t\tProcessEventCount=0;\t\t\t\t\n\t\t\t\tExReleaseResourceLite(&ProcesslistR);\n\t\t\t\t\n\t\t\t\t//DbgPrint(\"IOCTL_CE_STARTPROCESSWATCH\\n\");\n\n\t\t\t\tCleanProcessList();\n\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\tif ((r == STATUS_SUCCESS) && (CreateProcessNotifyRoutineEnabled == FALSE))\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\tDbgPrint(\"calling PsSetCreateProcessNotifyRoutine\\n\");\n\n\t\t\t\t\t\n#if (NTDDI_VERSION >= NTDDI_VISTASP1) \n\t\t\t\t\tr=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx, FALSE);\n\t\t\t\t\tCreateProcessNotifyRoutineEnabled = r== STATUS_SUCCESS;\n#else\n\t\t\t\t    CreateProcessNotifyRoutineEnabled = (PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,FALSE)==STATUS_SUCCESS);\t\t\t\t\t\n#endif\n\t\t\t\t\tif (CreateProcessNotifyRoutineEnabled)\n\t\t\t\t\t\tCreateThreadNotifyRoutineEnabled = (PsSetCreateThreadNotifyRoutine(CreateThreadNotifyRoutine) == STATUS_SUCCESS);\n\t\t\t\t}\n\n\t\t\t\tntStatus=(CreateProcessNotifyRoutineEnabled) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;\n\n\t\t\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t\t\t\tDbgPrint(\"CreateProcessNotifyRoutineEnabled worked\\n\");\n\t\t\t\telse\n\t\t\t\t\tDbgPrint(\"CreateProcessNotifyRoutineEnabled failed (r=%x)\\n\",r);\n\t\t\t\t\t\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t\n\n\t\tcase IOCTL_CE_GETPROCESSEVENTS:\n\t\t\t{\n\t\t\t\t\n\t\t\t\tExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);\n\n\t\t\t\t*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ProcessEventCount;\t\n\t\t\t\tRtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ProcessEventdata[0],ProcessEventCount*sizeof(ProcessEventdta));\n\t\t\t\tProcessEventCount=0; //there's room for new events\n\n\t\t\t\tExReleaseResourceLite(&ProcesslistR);\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_GETTHREADEVENTS:\n\t\t\t{\n\t\t\t\tExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);\n\n\t\t\t\t*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ThreadEventCount;\t\n\t\t\t\tRtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ThreadEventData[0],ThreadEventCount*sizeof(ThreadEventDta));\n\t\t\t\tThreadEventCount=0; //there's room for new events\n\n\t\t\t\tExReleaseResourceLite(&ProcesslistR);\n\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\n\t\tcase IOCTL_CE_CREATEAPC:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 threadid;\n\t\t\t\t\tUINT64 addresstoexecute;\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t} *inp;\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tCreateRemoteAPC((ULONG)inp->threadid,(PVOID)(UINT_PTR)inp->addresstoexecute);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\n\t\tcase IOCTL_CE_SUSPENDTHREAD:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG threadid;\t\t\t\t\t\t\t\n\t\t\t\t} *inp;\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"CE_SUSPENDTHREAD\\n\");\n\n\t\t\t\tDBKSuspendThread(inp->threadid);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_RESUMETHREAD:            \n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG threadid;\t\t\t\t\t\t\t\n\t\t\t\t} *inp;\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"CE_RESUMETHREAD\\n\");\n\n\t\t\t\tDBKResumeThread(inp->threadid);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n            }\n\t\t\t\n\n\t\tcase IOCTL_CE_SUSPENDPROCESS:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG processid;\t\t\t\t\t\t\t\n\t\t\t\t} *inp;\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\t\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_SUSPENDPROCESS\\n\");\n\n\t\t\t\tif (PsSuspendProcess)\n\t\t\t\t{\n\t\t\t\t\tPEPROCESS selectedprocess;\n\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t\t{\n\t\t\t\t\t\tntStatus = PsSuspendProcess(selectedprocess);\n\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tntStatus = STATUS_NOT_FOUND;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tntStatus = STATUS_NOT_IMPLEMENTED;\n\n\t\t\t\tbreak;\t\t\t\t\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_RESUMEPROCESS:            \n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG processid;\n\t\t\t\t} *inp;\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\n\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_RESUMEPROCESS\\n\");\n\n\t\t\t\tif (PsResumeProcess)\n\t\t\t\t{\n\t\t\t\t\tPEPROCESS selectedprocess;\n\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t\t{\n\t\t\t\t\t\tntStatus = PsResumeProcess(selectedprocess);\n\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tntStatus = STATUS_NOT_FOUND;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tntStatus = STATUS_NOT_IMPLEMENTED;\n\n\t\t\t\tbreak;\n            }\n\n\t\tcase IOCTL_CE_ALLOCATEMEM:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 ProcessID;\n\t\t\t\t\tUINT64 BaseAddress;\n\t\t\t\t\tUINT64 Size;\n\t\t\t\t\tUINT64 AllocationType;\n\t\t\t\t\tUINT64 Protect;\n\t\t\t\t} *inp;\n\t\t\t\tPEPROCESS selectedprocess;\n\n\t\t\t\tPVOID BaseAddress;\n\t\t\t\tSIZE_T RegionSize;\n\n\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tBaseAddress=(PVOID)(UINT_PTR)inp->BaseAddress;\n\t\t\t\tRegionSize=(SIZE_T)(inp->Size);\n\n\n\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID),&selectedprocess)==STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\t\t\tRtlZeroMemory(&apc_state,sizeof(apc_state));\t\t\t\t\t\n    \t\t\t\t\tKeAttachProcess((PVOID)selectedprocess); //local process is much more fun!!!!\n\n\t\t\t\t\t\tDbgPrint(\"Switched Process\\n\");\n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Calling ZwAllocateVirtualMemory\\n\");\n\t\t\t\t\t\t\tDbgPrint(\"Before call: BaseAddress=%p\\n\", BaseAddress);\t\t\n\t\t\t\t\t\t\tDbgPrint(\"Before call: RegionSize=%x\\n\", RegionSize);\n\n\t\t\t\t\t\t\tntStatus=ZwAllocateVirtualMemory((HANDLE)-1, &BaseAddress, 0, &RegionSize, (ULONG)inp->AllocationType, (ULONG)inp->Protect);\n\n\t\t\t\t\t\t\tif ((ntStatus==STATUS_SUCCESS) && (HiddenDriver))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t//initialize the memory with crap so it becomes paged\n\t\t\t\t\t\t\t\tint i;\n\t\t\t\t\t\t\t\tchar *x;\n\t\t\t\t\t\t\t\tx=BaseAddress;\n\t\t\t\t\t\t\t\tfor (i=0; i < (int)RegionSize;i++)\n\t\t\t\t\t\t\t\t\tx[i]=(unsigned char)i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tDbgPrint(\"ntStatus=%x\\n\", ntStatus);\n\t\t\t\t\t\t\tDbgPrint(\"BaseAddress=%p\\n\",BaseAddress);\n\t\t\t\t\t\t\tDbgPrint(\"RegionSize=%x\\n\",RegionSize);\n\t\t\t\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;\n\t\t\t\t\t\t\t*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)BaseAddress;\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__finally\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tKeDetachProcess();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\t__except(1)\n\t\t\t\t\t{\n\t\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_ALLOCATEMEM_NONPAGED:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG Size;\n\t\t\t\t} *inp;\n\t\t\t\tPVOID address;\n\t\t\t\tint size;\n\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tsize=inp->Size;\n\n\t\t\t\taddress=ExAllocatePool(NonPagedPool,size);\n\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;\n\t\t\t\t*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)address;\n\t\t\t\t\n\n\t\t\t\tif (address==0)\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Alloc success. Cleaning memory... (size=%d)\\n\",size);\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\tDbgPrint(\"address=%p\\n\", address);\n\t\t\t\t\tRtlZeroMemory(address, size);\n\t\t\t\t\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_FREE_NONPAGED:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 Address;\n\t\t\t\t} *inp;\n\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tExFreePool((PVOID)(UINT_PTR)inp->Address);\n\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\tcase IOCTL_CE_MAP_MEMORY:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 FromPID;\n\t\t\t\t\tUINT64 ToPID;\n\t\t\t\t\tUINT64 address;\n\t\t\t\t\tDWORD size;\n\t\t\t\t} *inp;\n\n\t\t\t\tstruct output\n\t\t\t\t{\n\t\t\t\t\tUINT64 FromMDL;\n\t\t\t\t\tUINT64 Address;\n\t\t\t\t} *outp;\n\n\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\tPEPROCESS selectedprocess;\n\t\t\t\tPMDL FromMDL=NULL;\n\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\toutp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_MAP_MEMORY\\n\");\n\t\t\t\tDbgPrint(\"address %x size %d\\n\", inp->address, inp->size);\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\t\t\t\t\n\n\t\t\t\tif (inp->FromPID)\t\t\t\n\t\t\t\t{\n\t\t\t\t\t//switch\n\t\t\t\t\tDbgPrint(\"From PID %d\\n\", inp->FromPID);\n\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->FromPID), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t\t{\n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRtlZeroMemory(&apc_state, sizeof(apc_state));\n\t\t\t\t\t\t\tKeStackAttachProcess((PVOID)selectedprocess, &apc_state); \n\n\t\t\t\t\t\t\t__try\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tFromMDL=IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);\n\t\t\t\t\t\t\t\tif (FromMDL)\n\t\t\t\t\t\t\t\t\tMmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t__finally\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__except (1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Exception\\n\");\n\t\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\t\n\n\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"From kernel or self\\n\", inp->FromPID);\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tFromMDL = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);\n\t\t\t\t\t\tif (FromMDL)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"IoAllocateMdl success\\n\");\n\t\t\t\t\t\t\tMmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t__except (1)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Exception\\n\");\n\n\t\t\t\t\t\tif (FromMDL)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tIoFreeMdl(FromMDL);\n\t\t\t\t\t\t\tFromMDL = NULL;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (FromMDL)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"FromMDL is valid\\n\");\n\n\t\t\t\t\tif (inp->ToPID)\n\t\t\t\t\t{\n\t\t\t\t\t\t//switch\n\t\t\t\t\t\tDbgPrint(\"To PID %d\\n\", inp->ToPID);\n\t\t\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ToPID), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t__try\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tRtlZeroMemory(&apc_state, sizeof(apc_state));\n\t\t\t\t\t\t\t\tKeStackAttachProcess((PVOID)selectedprocess, &apc_state);\n\n\t\t\t\t\t\t\t\t__try\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\toutp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);\n\t\t\t\t\t\t\t\t\toutp->FromMDL = (UINT64)FromMDL;\n\t\t\t\t\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t__finally\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t__except (1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tDbgPrint(\"Exception part 2\\n\");\n\t\t\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"To kernel or self\\n\", inp->FromPID);\n\n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\toutp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);\n\t\t\t\t\t\t\toutp->FromMDL = (UINT64)FromMDL;\n\t\t\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__except (1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Exception part 2\\n\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\n\t\t\t\t\t\n\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tDbgPrint(\"FromMDL==NULL\\n\");\n\n\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_UNMAP_MEMORY:\n\t\t\t{\n\t\t\t\tstruct output\n\t\t\t\t{\n\t\t\t\t\tUINT64 FromMDL;\n\t\t\t\t\tUINT64 Address;\n\t\t\t\t} *inp;\n\n\t\t\t\tPMDL mdl;\n\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tmdl = (PMDL)(UINT_PTR)inp->FromMDL;\n\n\t\t\t\tMmUnmapLockedPages((PMDL)(UINT_PTR)inp->Address, mdl);\n\t\t\t\tMmUnlockPages(mdl);\n\t\t\t\tIoFreeMdl(mdl);\n\n\t\t\t\tntStatus = STATUS_SUCCESS; //no BSOD means success ;)\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_LOCK_MEMORY:\n\t\t\t{\n\t\t\t\tstruct\n\t\t\t\t{\n\t\t\t\t\tUINT64 ProcessID;\n\t\t\t\t\tUINT64 address;\n\t\t\t\t\tUINT64 size;\n\t\t\t\t} *inp;\n\t\t\t\t\n\t\t\t\tstruct\n\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\tUINT64 mdl;\n\t\t\t\t} *outp;\n\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\tPEPROCESS selectedprocess;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_LOCK_MEMORY\");\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\toutp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\t \n\t\t\t\t\n\n\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\tPMDL mdl = NULL;\n\t\t\t\t\tKeStackAttachProcess(selectedprocess, &apc_state);\n\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tmdl = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, (ULONG)inp->size, FALSE, FALSE, NULL);\n\t\t\t\t\t\tif (mdl)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t__try\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tMmProbeAndLockPages(mdl, UserMode, IoReadAccess);\n\n\t\t\t\t\t\t\t\tDbgPrint(\"MmProbeAndLockPages succeeded\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t__except (1)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tDbgPrint(\"MmProbeAndLockPages failed\");\n\t\t\t\t\t\t\t\tIoFreeMdl(mdl);\n\t\t\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t__finally\n\t\t\t\t\t{\n\t\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t\t}\n\n\t\t\t\t\toutp->mdl = (UINT_PTR)mdl;\n\n\n\t\t\t\t\tDbgPrint(\"Locked the page\\n\");\n\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_UNLOCK_MEMORY:\n\t\t{\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tUINT64 mdl;\n\t\t\t} *inp;\n\t\t\tDbgPrint(\"IOCTL_CE_UNLOCK_MEMORY\");\n\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\tMmUnlockPages((PMDL)(UINT_PTR)inp->mdl);\n\t\t\tIoFreeMdl((PMDL)(UINT_PTR)inp->mdl);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_GETPROCADDRESS:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 s;\n\t\t\t\t} *inp;\n\t\t\t\tUNICODE_STRING y;\n\t\t\t\tUINT64 result;\n\t\t\t\tPVOID x;\n\n\n\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tRtlInitUnicodeString(&y, (PCWSTR)(UINT_PTR)(inp->s));\n\t\t\t\tx=MmGetSystemRoutineAddress(&y);\n\t\t\t\tresult=(UINT64)x;\n\n\n\t\t\t\tRtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&result,8);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_GETPROCESSNAMEADDRESS:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 PEPROCESS;\n\t\t\t\t} *inp;\n\n\t\t\t\tstruct output\n\t\t\t\t{\n\t\t\t\t\tUINT64 Address;\n\t\t\t\t} *outp;\n\n\t\t\t\tUNICODE_STRING temp;\n\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\toutp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tRtlInitUnicodeString(&temp, L\"PsGetProcessImageFileName\");\n\t\t\t\tPsGetProcessImageFileName=(GET_PROCESS_IMAGE_NAME)MmGetSystemRoutineAddress(&temp);\n\t\t\t\tif (PsGetProcessImageFileName!=NULL)\n\t\t\t\t{\n\t\t\t\t\toutp->Address=(UINT_PTR)PsGetProcessImageFileName((PEPROCESS)((UINT_PTR)(inp->PEPROCESS)));\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\telse \n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"PsGetProcessImageFileName==NULL\");\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n/*x\n\t\tcase IOCTL_CE_MAKEKERNELCOPY:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG Base;\n\t\t\t\t\tULONG KernelSize;\n\t\t\t\t} *inp;\n\t\t\t\tDbgPrint(\"IOCTL_CE_MAKEKERNELCOPY\");\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tntStatus=makeKernelCopy(inp->Base, inp->KernelSize);\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n*/\n\t\t\t\n\n\t\tcase IOCTL_CE_CONTINUEDEBUGEVENT:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tBOOL handled;\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_CONTINUEDEBUGEVENT\\n\");\n\t\t\t\tntStatus=debugger_continueDebugEvent(inp->handled);\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\tcase IOCTL_CE_WAITFORDEBUGEVENT:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG timeout;\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tntStatus=debugger_waitForDebugEvent(inp->timeout);\n\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\tcase IOCTL_CE_GETDEBUGGERSTATE:\n\t\t\t{\t\n\t\t\t\tDbgPrint(\"IOCTL_CE_GETDEBUGGERSTATE\\n\");\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tntStatus=debugger_getDebuggerState((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer));\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Exception happened\\n\");\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tDbgPrint(\"ntStatus=%x rax=%x\\n\",ntStatus, ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_SETDEBUGGERSTATE:\n\t\t\t{\t\n\t\t\t\tDbgPrint(\"IOCTL_CE_SETDEBUGGERSTATE: state->rax=%x\\n\", ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tntStatus=debugger_setDebuggerState((PDebugStackState)Irp->AssociatedIrp.SystemBuffer);\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Exception happened\\n\");\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_SETKERNELSTEPABILITY:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tint state;\n\t\t\t\t\t\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tKernelCodeStepping=inp->state;\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_WRITESIGNOREWP:\n\t\t{\n\t\t\tKernelWritesIgnoreWP = *(BYTE*)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t\t\n\t\tcase IOCTL_CE_GD_SETBREAKPOINT:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tBOOL active;\n\t\t\t\t\tint debugregspot;\n\t\t\t\t\tUINT64 address;\n\t\t\t\t\tDWORD breakType;\n\t\t\t\t\tDWORD breakLength;\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\t\n\t\t\t\tDbgPrint(\"sizeof(struct input)=%d\\n\",sizeof(struct input));\n\t\t\t\t//DbgPrint(\"address=%llx breakType=%d breakLength=%d\\n\",inp->address, inp->breakType,inp->breakLength);\n\n\t\t\t\tif (inp->active)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"activating breapoint %d\\n\", inp->debugregspot);\n\t\t\t\t\tntStatus=debugger_setGDBreakpoint(inp->debugregspot, (UINT_PTR)inp->address, (BreakType)inp->breakType, (BreakLength)inp->breakLength);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\tDbgPrint(\"Deactivating breakpoint :%d\\n\", inp->debugregspot);\n\t\t\t\t\tntStatus=debugger_unsetGDBreakpoint(inp->debugregspot);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_TOUCHDEBUGREGISTER: //used after setting a global debug breakpoint\n\t\t\t{\n\t\t\t\tdebugger_touchDebugRegister(0);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_SETSTORELBR:\n\t\t\t{\n\t\t\t\tBOOL newstate=*(PBOOL)Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"Calling debugger_setStoreLBR(%d)\\n\", newstate);\n\t\t\t\tdebugger_setStoreLBR(newstate);\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\t\n\n\n\t\tcase IOCTL_CE_EXECUTE_CODE:\n\t\t\t{\t\t\n\t\t\t\ttypedef NTSTATUS (*PARAMETERLESSFUNCTION)(UINT64 parameters);\n\t\t\t\tPARAMETERLESSFUNCTION functiontocall;\n\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64\tfunctionaddress; //function address to call\n\t\t\t\t\tUINT64\tparameters;\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tDbgPrint(\"IOCTL_CE_EXECUTE_CODE\\n\");\n\n\t\t\t\tfunctiontocall=(PARAMETERLESSFUNCTION)(UINT_PTR)(inp->functionaddress);\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tntStatus=functiontocall(inp->parameters);\n\t\t\t\t\tDbgPrint(\"Still alive\\n\");\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Exception occured\\n\");\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\tcase IOCTL_CE_GETVERSION:\n\t\t\t{\n\t\t\t\tDbgPrint(\"IOCTL_CE_GETVERSION. Version=%d\\n\",dbkversion);\n\t\t\t\t*(PULONG)Irp->AssociatedIrp.SystemBuffer=dbkversion;\t\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_READMSR:\n\t\t\t{\n\t\t\t\tDWORD msr=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\t//DbgPrint(\"IOCTL_CE_READMSR: msr=%x\\n\", msr);\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\t*(PUINT64)Irp->AssociatedIrp.SystemBuffer=__readmsr(msr);\n\t\t\t\t\t//DbgPrint(\"Output: %llx\\n\",*(PUINT64)Irp->AssociatedIrp.SystemBuffer); \n\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\t\n\n\t\tcase IOCTL_CE_WRITEMSR:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 msr;\t\t\t\n\t\t\t\t\tUINT64 value;\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_WRITEMSR:\\n\");\n\t\t\t\tDbgPrint(\"msr=%llx\\n\", inp->msr);\n\t\t\t\tDbgPrint(\"value=%llx\\n\", inp->value);\n\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\t__writemsr(inp->msr, inp->value );\t\t\t\t\t\n\t\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t__except(1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Error while writing value\\n\");\n\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT32 PID;\t\n\t\t\t\t\tUINT32 Size;\n\t\t\t\t\tUINT32 RangeCount;\n\t\t\t\t\tUINT32 NoPMI;\n\t\t\t\t\tUINT32 UserMode;\n\t\t\t\t\tUINT32 KernelMode;\n\t\t\t\t\tURANGE Ranges[8];\n\t\t\t\t\tWCHAR OutputPath[200];\n\t\t\t\t} *inp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tint i;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_ULTIMAP2\");\n\t\t\t\tfor (i = 0; i < (int)(inp->RangeCount); i++)\n\t\t\t\t\tDbgPrint(\"%d=%p -> %p\", i, (PVOID)(UINT_PTR)inp->Ranges[i].StartAddress, (PVOID)(UINT_PTR)inp->Ranges[i].EndAddress);\n\n\t\t\t\tSetupUltimap2(inp->PID, inp->Size, inp->OutputPath, inp->RangeCount, inp->Ranges, inp->NoPMI, inp->UserMode, inp->KernelMode);\n\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_WAITFORDATA:\n\t\t{\n\n\t\t\tULONG timeout = *(ULONG *)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tPULTIMAP2DATAEVENT output = Irp->AssociatedIrp.SystemBuffer;\n\t\t\toutput->Address = 0;\n\n\t\t\tntStatus = ultimap2_waitForData(timeout, output);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_LOCKFILE:\n\t\t{\n\t\t\tint cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tultimap2_LockFile(cpunr);\n\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_RELEASEFILE:\n\t\t{\n\t\t\tint cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tultimap2_ReleaseFile(cpunr);\n\n\t\t\tntStatus = STATUS_SUCCESS;\t\t\t\t\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_GETTRACESIZE:\n\t\t{\n\t\t\t*(UINT64*)Irp->AssociatedIrp.SystemBuffer = ultimap2_GetTraceFileSize();\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_RESETTRACESIZE:\n\t\t{\n\t\t\tultimap2_ResetTraceFileSize();\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\n\t\tcase IOCTL_CE_ULTIMAP2_CONTINUE:\n\t\t{\n\t\t\tint cpunr=*(int*)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tntStatus = ultimap2_continue(cpunr);\n\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_FLUSH:\n\t\t{\t\t\t\n\t\t\tntStatus = ultimap2_flushBuffers();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_PAUSE:\n\t\t{\n\t\t\tntStatus = ultimap2_pause();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP2_RESUME:\n\t\t{\n\t\t\tntStatus = ultimap2_resume();\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_DISABLEULTIMAP2:\n\t\t\t{\n\t\t\t\tDisableUltimap2();\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP:\n\t\t\t{\n\t\t\t\t#pragma pack(1)\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 targetCR3;\n\t\t\t\t\tUINT64 dbgctl;\t\t\t\n\t\t\t\t\tUINT64 dsareasize;\n\t\t\t\t\tBOOL savetofile;\n\t\t\t\t\tint HandlerCount;\n\t\t\t\t\tWCHAR filename[200];\t\t\t\t\n\t\t\t\t} *inp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\t#pragma pack()\n\n\t\t\t\t\n\t\t\t\tDbgPrint(\"IOCTL_CE_ULTIMAP:\\n\");\n\t\t\t\tDbgPrint(\"ultimap(%I64x, %I64x, %d):\\n\", (UINT64)inp->targetCR3, (UINT64)inp->dbgctl, inp->dsareasize);\n\n\t\t\t\tif (inp->savetofile)\n\t\t\t\t\tDbgPrint(\"filename=%S\\n\", &inp->filename[0]);\n\n\t\t\t\tntStatus=ultimap(inp->targetCR3, inp->dbgctl, (int)inp->dsareasize, inp->savetofile, &inp->filename[0], inp->HandlerCount);\n\t\t\t\t\n\t\t\t\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_DISABLE:\n\t\t\t{\n\t\t\t\tultimap_disable();\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_WAITFORDATA:\n\t\t\t{\n\t\t\t\t\n\t\t\t\tULONG timeout=*(ULONG *)Irp->AssociatedIrp.SystemBuffer;\t\t\t\t\n\t\t\t\tPULTIMAPDATAEVENT output=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tntStatus=ultimap_waitForData(timeout, output);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_CONTINUE:\n\t\t\t{\n\t\t\t\tPULTIMAPDATAEVENT input=Irp->AssociatedIrp.SystemBuffer;\t\t\t\t\n\t\t\t\tntStatus=ultimap_continue(input);\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_FLUSH:\n\t\t\t{\n\t\t\t\tultimap_flushBuffers();\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_PAUSE:\n\t\t{\t\t\t\n\t\t\tultimap_pause();\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ULTIMAP_RESUME:\n\t\t{\t\t\t\n\t\t\tultimap_resume();\n\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\tbreak;\n\t\t}\n\n\t\t\t/*\n\t\tcase IOCTL_CE_GETCPUIDS:\n\t\t\t{\n\t\t\t\tCPULISTFILLSTRUCT x;\t\n\n\t\t\t\tforEachCpuPassive(GetCPUIDS_all,&x);\n\t\t\t}*/\n\n\t\tcase IOCTL_CE_STARTACCESMONITOR:\n\t\t\t{\n\t\t\t\t//this is used instead of writeProcessMemory for speed reasons (the reading out is still done with readProcessMemory because of easier memory management)\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 ProcessID;\n\t\t\t\t} *inp;\n\t\t\t\tPEPROCESS selectedprocess;\n\n\t\t\t\tPVOID BaseAddress;\n\t\t\t\tSIZE_T RegionSize;\n\n\t\t\t\tinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tDbgPrint(\"IOCTL_CE_STARTACCESMONITOR(%d)\\n\", inp->ProcessID);\n\n\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\n\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\tntStatus = markAllPagesAsNeverAccessed(selectedprocess);\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_ENUMACCESSEDMEMORY:\n\t\t\t{\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 ProcessID;\n\t\t\t\t} *inp;\n\t\t\t\tPEPROCESS selectedprocess;\n\n\t\t\t\tPVOID BaseAddress;\n\t\t\t\tSIZE_T RegionSize;\n\n\t\t\t\tinp = Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tDbgPrint(\"IOCTL_CE_ENUMACCESSEDMEMORY(%d)\\n\", inp->ProcessID);\n\n\n\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\n\t\t\t\tif (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t*(int *)Irp->AssociatedIrp.SystemBuffer = enumAllAccessedPages(selectedprocess);\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t}\n\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_GETACCESSEDMEMORYLIST:\n\t\t\t{\n\t\t\t\tint ListSizeInBytes = *(int *)Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tPPRANGE List = (PPRANGE)Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_GETACCESSEDMEMORYLIST\\n\"); \n\n\t\t\t\tgetAccessedPageList(List, ListSizeInBytes);\n\n\t\t\t\tDbgPrint(\"return from IOCTL_CE_GETACCESSEDMEMORYLIST\\n\");\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_INITIALIZE:\n\t\t\t{\n\t\t\t\t//find the KeServiceDescriptorTableShadow \n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tUINT64 AddressOfWin32K;\n\t\t\t\t\tUINT64 SizeOfWin32K;\n\t\t\t\t\tUINT64 NtUserBuildHwndList_callnumber;\n\t\t\t\t\tUINT64 NtUserQueryWindow_callnumber;\n\t\t\t\t\tUINT64 NtUserFindWindowEx_callnumber;\n\t\t\t\t\tUINT64 NtUserGetForegroundWindow_callnumber;\n\t\t\t\t\tUINT64 ActiveLinkOffset;\n\t\t\t\t\tUINT64 ProcessNameOffset;\n\t\t\t\t\tUINT64 DebugportOffset;\t\n\t\t\t\t\tUINT64 ProcessEvent;\n\t\t\t\t\tUINT64 ThreadEvent;\n  \t\t\t\t} *pinp;\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_INITIALIZE\\n\");\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\t//referencing event handles to objects\n\n\t\t\t\tObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ProcessEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ProcessEvent, NULL); \n\t\t\t\tObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ThreadEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ThreadEvent, NULL); \n\t\t\t\t\n\t\t\t\t*(UINT_PTR*)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\n\t\tcase IOCTL_CE_VMXCONFIG:\n\t\t\t{\n#pragma pack(1)\n\t\t\t\tstruct input\n\t\t\t\t{\n\t\t\t\t\tULONG Virtualization_Enabled;\n\t\t\t\t\tQWORD Password1;\n\t\t\t\t\tULONG Password2;\n\t\t\t\t\tQWORD Password3;\n  \t\t\t\t} *pinp;\n#pragma pack()\n\t\t\t\t\n\n\t\t\t\tDbgPrint(\"IOCTL_CE_VMXCONFIG called\\n\");\t\n\t\t\t\tntStatus=STATUS_SUCCESS;\n\n\t\t\t\tpinp=Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\t\tif (pinp->Virtualization_Enabled)\n\t\t\t\t{\n\t\t\t\t\tvmx_password1=pinp->Password1;\n\t\t\t\t\tvmx_password2=pinp->Password2;\n\t\t\t\t\tvmx_password3=pinp->Password3;\n\n\t\t\t\t\tDbgPrint(\"new passwords are: %p-%x-%p\\n\", (void*)vmx_password1, vmx_password2, (void*)vmx_password3);\n\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tvmx_version=vmx_getversion();\n\t\t\t\t\t\tDbgPrint(\"Still here, so vmx is loaded. vmx_version=%x\\n\",vmx_version);\t\n\t\t\t\t\t\tvmxusable = 1;\n\t\t\t\t\t}\n\t\t\t\t\t__except(1)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Exception happened. This means no vmx installed, or one of the passwords is wrong\\n\");\n\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\n\t\t\t\t\t\tvmxusable = 0;\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Virtualization_Enabled=0\\n\");\n\t\t\t\t\tvmxusable=0;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\n\t\tcase IOCTL_CE_ENABLE_DRM:\n\t\t\t{\n#if (NTDDI_VERSION >= NTDDI_VISTA)\t\t\t\t\n\t\t\t\tstruct\n\t\t\t\t{\n\t\t\t\t\tQWORD PreferedAltitude;\n\t\t\t\t\tQWORD ProtectedProcess;\t\t\t\t\t\t\t\t\t\n\t\t\t\t} *inp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\n\t\t\t\t\n\t\t\t\tDbgPrint(\"inp->PreferedAltitude=%p\", inp->PreferedAltitude);\n\t\t\t\tDbgPrint(\"inp->PreferedAltitude=%p\", inp->ProtectedProcess);\n\n\t\t\t\t\n\t\t\t\tif (DRMProcess)\n\t\t\t\t{\n\t\t\t\t\t//check if this process has been terminated\n\t\t\t\t\tLARGE_INTEGER timeout;\n\n\t\t\t\t\ttimeout.QuadPart = -500000;\n\t\t\t\t\tntStatus=KeWaitForSingleObject(DRMProcess, UserRequest, UserMode, FALSE, &timeout);\n\n\t\t\t\t\tif (ntStatus != STATUS_SUCCESS)\n\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t}\n\n\t\t\t\tDRMProcess = PsGetCurrentProcess();\n\n\t\t\t\tif (inp->ProtectedProcess)\n\t\t\t\t{\n\t\t\t\t\tif (DRMProcess != (PEPROCESS)((UINT_PTR)inp->ProtectedProcess))\t\t\t\t\t\t\n\t\t\t\t\t\tDRMProcess2 = (PEPROCESS)((UINT_PTR)inp->ProtectedProcess);\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\tDbgPrint(\"DRMProcess=%p\", DRMProcess);\n\t\t\t\tDbgPrint(\"DRMProcess2=%p\", DRMProcess2);\n\n\t\t\t\tif (DRMHandle == NULL)\n\t\t\t\t{\n\t\t\t\t\tWCHAR wcAltitude[10];\n\t\t\t\t\tUNICODE_STRING usAltitude;\n\t\t\t\t\tOB_CALLBACK_REGISTRATION r;\n\t\t\t\t\tLARGE_INTEGER tc;\n\t\t\t\t\tOB_OPERATION_REGISTRATION obr[2];\n\t\t\t\t\tint RandomVal = (int)(inp->PreferedAltitude);\n\t\t\t\t\tint trycount = 0;\n\n\t\t\t\t\tif (RandomVal == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttc.QuadPart = 0;\n\t\t\t\t\t\tKeQueryTickCount(&tc);\n\t\t\t\t\t\tRandomVal = 1000 + (tc.QuadPart % 50000);\n\t\t\t\t\t}\n\n\t\t\t\t\tDbgPrint(\"Activating CE's super advanced DRM\"); //yeah right....\n\n\t\t\t\t\tDbgPrint(\"RandomVal=%d\", RandomVal);\n\t\t\t\t\tRtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L\"%d\", RandomVal);\n\n\t\t\t\t\tDbgPrint(\"wcAltitude=%S\", wcAltitude);\n\t\t\t\t\tRtlInitUnicodeString(&usAltitude, wcAltitude);\n\n\t\t\t\t\tr.Version = OB_FLT_REGISTRATION_VERSION;\n\t\t\t\t\tr.Altitude = usAltitude;\n\t\t\t\t\tr.RegistrationContext = NULL;\n\n\n\t\t\t\t\tobr[0].ObjectType = PsProcessType;\n\t\t\t\t\tobr[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;\n\t\t\t\t\tobr[0].PreOperation = ProcessPreCallback;\n\t\t\t\t\tobr[0].PostOperation = ProcessPostCallback;\n\n\t\t\t\t\tobr[1].ObjectType = PsThreadType;\n\t\t\t\t\tobr[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;\n\t\t\t\t\tobr[1].PreOperation = ThreadPreCallback;\n\t\t\t\t\tobr[1].PostOperation = ThreadPostCallback;\n\n\t\t\t\t\tr.OperationRegistration = obr;\n\t\t\t\t\tr.OperationRegistrationCount = 2;\n\n\t\t\t\t\tntStatus = ObRegisterCallbacks(&r, &DRMHandle);\n\n\t\t\t\t\twhile ((ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) && (trycount<10))\n\t\t\t\t\t{\n\t\t\t\t\t\tRandomVal++;\n\t\t\t\t\t\tRtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L\"%d\", RandomVal);\n\t\t\t\t\t\tRtlInitUnicodeString(&usAltitude, wcAltitude);\n\t\t\t\t\t\tr.Altitude = usAltitude;\n\n\t\t\t\t\t\ttrycount++;\n\n\t\t\t\t\t\tntStatus = ObRegisterCallbacks(&r, &DRMHandle);\n\t\t\t\t\t}\n\n\t\t\t\t\tDbgPrint(\"ntStatus=%X\", ntStatus);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tntStatus = STATUS_SUCCESS;\n#else\n\t\t\t\tntStatus = STATUS_NOT_IMPLEMENTED;\n#endif\t\t\t\t\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\tcase IOCTL_CE_GET_PEB:\n\t\t{\n\t\t\tKAPC_STATE oldstate;\n\t\t\tPEPROCESS ep = *(PEPROCESS *)Irp->AssociatedIrp.SystemBuffer;\n\n\n\t\t\t//DbgPrint(\"IOCTL_CE_GET_PEB\");\n\t\t\tKeStackAttachProcess((PKPROCESS)ep, &oldstate);\n\t\t\t__try\n\t\t\t{\n\t\t\t\tULONG r;\n\t\t\t\tPROCESS_BASIC_INFORMATION pbi;\n\t\t\t\t//DbgPrint(\"Calling ZwQueryInformationProcess\");\n\t\t\t\tntStatus = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &r);\n\t\t\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t//DbgPrint(\"pbi.UniqueProcessId=%x\\n\", (int)pbi.UniqueProcessId);\n\t\t\t\t\t//DbgPrint(\"pbi.PebBaseAddress=%p\\n\", (PVOID)pbi.PebBaseAddress);\t\t\t\t\t\n\t\t\t\t\t*(QWORD *)Irp->AssociatedIrp.SystemBuffer = (QWORD)(pbi.PebBaseAddress);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tDbgPrint(\"ZwQueryInformationProcess failed\");\n\t\t\t}\n\t\t\t__finally\n\t\t\t{\n\t\t\t\tKeUnstackDetachProcess(&oldstate);\n\t\t\t}\t\n\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_QUERYINFORMATIONPROCESS:\n\t\t{\n\t\t\tstruct\n\t\t\t{\t\n\t\t\t\tQWORD processid;\n\t\t\t\tQWORD ProcessInformationAddress;\n\t\t\t\tQWORD ProcessInformationClass;\n\t\t\t\tQWORD ProcessInformationLength;\t\t\t\t\n\t\t\t}  *inp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\tstruct\n\t\t\t{\n\t\t\t\tQWORD result;\n\t\t\t\tQWORD returnLength;\n\t\t\t\tchar data;\n\t\t\t} *outp = Irp->AssociatedIrp.SystemBuffer;\n\n\t\t\tPEPROCESS selectedprocess;\n\t\t\tDbgPrint(\"IOCTL_CE_QUERYINFORMATIONPROCESS\");\n\n\t\t\tif (inp->processid == 0)\n\t\t\t{\n\t\t\t\tDbgPrint(\"Still works\\n\");\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t__try\n\t\t\t{\n\t\t\t\t\n\t\t\t\tif (PsLookupProcessByProcessId((HANDLE)(UINT_PTR)inp->processid, &selectedprocess) == STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\tKAPC_STATE oldstate;\n\t\t\t\t\tKeStackAttachProcess((PKPROCESS)selectedprocess, &oldstate);\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\tULONG returnLength;\n\n\t\t\t\t\t\tif (inp->ProcessInformationAddress == 0)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"NULL ProcessInformationAddress\");\n\t\t\t\t\t\t\toutp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, NULL, (ULONG)inp->ProcessInformationLength, &returnLength);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\toutp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, &(outp->data), (ULONG)inp->ProcessInformationLength, &returnLength);\n\n\t\t\t\t\t\tDbgPrint(\"outp->result=%x\", outp->result);\n\n\t\t\t\t\t\toutp->returnLength = returnLength;\n\t\t\t\t\t\tDbgPrint(\"outp->returnLength=%x\", outp->returnLength);\n\n\t\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t\t}\n\t\t\t\t\t__finally\n\t\t\t\t\t{\n\t\t\t\t\t\tKeUnstackDetachProcess(&oldstate);\n\t\t\t\t\t}\n\n\t\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Failed to find pid %x\", inp->processid);\n\t\t\t\t\tntStatus = STATUS_EXPIRED_HANDLE;\n\t\t\t\t}\n\t\t\t}\n\t\t\t__except (1)\n\t\t\t{\n\t\t\t\tDbgPrint(\"Exception\");\n\t\t\t\tntStatus = STATUS_EXPIRED_HANDLE;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_NTPROTECTVIRTUALMEMORY:\n\t\t{\n\n\t\t\t\n\t\t\tbreak;\n\t\t}\n\n\t\tcase IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM:\n\t\t{\n\t\t\tPHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;\n\t\t\tPMDL mdl;\n\t\t\tQWORD pagecount = *(QWORD*)Irp->AssociatedIrp.SystemBuffer;\n\t\t\tPFN_NUMBER *pfnlist;\n\t\t\tDbgPrint(\"IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM(%d)\\n\", pagecount);\n\n\t\t\tif (!vmxusable)\n\t\t\t{\n\t\t\t\tDbgPrint(\"This only works when DBVM is present\\n\");\n\t\t\t\tntStatus = STATUS_INVALID_DEVICE_STATE;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tLowAddress.QuadPart = 0;\n\t\t\tHighAddress.QuadPart = 0xffffffffffffffffI64;\n\t\t\tSkipBytes.QuadPart = 0;\n\t\t\tmdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, (SIZE_T)pagecount * 4096, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED); //do not free this, EVER\n\t\t\tif (mdl)\n\t\t\t{\n\t\t\t\tint i;\n\t\t\t\tPDBVMOffloadMemInfo mi;\n\n\t\t\t\tpagecount = MmGetMdlByteCount(mdl) / 4096;\n\t\t\t\tDbgPrint(\"Allocated %d pages\\n\", pagecount);\n\n\t\t\t\tpfnlist = MmGetMdlPfnArray(mdl);\n\n\t\t\t\tif (pfnlist)\n\t\t\t\t{\n\t\t\t\t\t//convert the pfnlist to a list dbvm understands, and go in blocks of 32\n\t\t\t\t\tmi = ExAllocatePool(PagedPool, sizeof(DBVMOffloadMemInfo));\n\t\t\t\t\tif (mi)\n\t\t\t\t\t{\n\t\t\t\t\t\tmi->List = ExAllocatePool(PagedPool, sizeof(UINT64) * 32);\n\t\t\t\t\t\tif (mi->List)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmi->Count = 0;\n\t\t\t\t\t\t\tfor (i = 0; i < pagecount; i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tmi->List[mi->Count] = pfnlist[i] << 12;\n\t\t\t\t\t\t\t\tmi->Count++;\n\n\t\t\t\t\t\t\t\tif (mi->Count == 32)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tint j;\n\t\t\t\t\t\t\t\t\tint r = vmx_add_memory(mi->List, mi->Count);\n\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tDbgPrint(\"vmx_add_memory for %d pages returned %d\\n\", mi->Count, r);\n\n\t\t\t\t\t\t\t\t\tfor (j = 0; j < mi->Count; j++)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tDbgPrint(\"%d : %p\\n\", j, (void*)((UINT_PTR)mi->List[j]));\n\t\t\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\t\t\tmi->Count = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (mi->Count)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tint r = vmx_add_memory(mi->List, mi->Count);\n\t\t\t\t\t\t\t\tDbgPrint(\"vmx_add_memory for %d pages returned %d\\n\", mi->Count, r);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tExFreePool(mi->List);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tDbgPrint(\"Failure allocating mi->List\");\n\t\t\t\t\t\tExFreePool(mi);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tDbgPrint(\"Failure allocting mi\");\n\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tDbgPrint(\"Failure getting pfn list\");\n\t\t\t\tExFreePool(mdl); //only free the mdl, the rest belongs to dbvm now\n\n\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDbgPrint(\"Failure allocating MDL\");\n\t\t\t\tntStatus = STATUS_MEMORY_NOT_ALLOCATED;\n\t\t\t}\n\n\n\t\t\tbreak;\n\t\t}\n\n        default:\n\t\t\tDbgPrint(\"Unhandled IO request: %x\\n\", IoControlCode);\t\t\t\n            break;\n    }\n\n\t\n    Irp->IoStatus.Status = ntStatus;\n    \n    // Set # of bytes to copy back to user-mode...\n\tif (irpStack) //only NULL when loaded by dbvm\n\t{\n\t\tif (ntStatus == STATUS_SUCCESS)\n\t\t\tIrp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;\n\t\telse\n\t\t\tIrp->IoStatus.Information = 0;\n\n\t\tIoCompleteRequest(Irp, IO_NO_INCREMENT);\n\t}\n\n    \n    return ntStatus;\n}\n"
  },
  {
    "path": "src/IOPLDispatcher.h",
    "content": "#ifndef IOPLDISPACTCHER_H\n#define IOPLDISPACTCHER_H\n\n#include \"DBKfunc.h\"\n\n#define IOCTL_UNKNOWN_BASE\t\t\t\t\tFILE_DEVICE_UNKNOWN\n\n#define IOCTL_CE_READMEMORY\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_WRITEMEMORY\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_OPENPROCESS    \t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_QUERY_VIRTUAL_MEMORY\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_TEST\t\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPEPROCESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0805, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_READPHYSICALMEMORY\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_WRITEPHYSICALMEMORY\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0807, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPHYSICALADDRESS\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0808, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//#define IOCTL_CE_PROTECTME\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0809, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETCR3 \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SETCR3 \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETSDT \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_INITIALIZE     \t\t    \tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_DONTPROTECTME\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETIDT \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x080f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_HOOKINTS \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0810, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_DEBUGPROCESS \t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0811, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//#define IOCTL_CE_RETRIEVEDEBUGDATA\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0812, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_STARTPROCESSWATCH\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0813, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPROCESSEVENTS\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0814, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETTHREADEVENTS\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0815, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETVERSION\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0816, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETCR4 \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0817, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_OPENTHREAD\t    \t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0818, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_MAKEWRITABLE\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0819, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//obsolete: #define IOCTL_CE_DEBUGPROCESS_CHANGEREG\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_STOPDEBUGGING\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//obsolete: #define\tIOCTL_CE_STOP_DEBUGPROCESS_CHANGEREG\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//#define\tIOCTL_CE_USEALTERNATEMETHOD\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//#define\tIOCTL_CE_ISUSINGALTERNATEMETHOD\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define\tIOCTL_CE_ALLOCATEMEM\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x081f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_CREATEAPC\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0820, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPETHREAD\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0821, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_SUSPENDTHREAD\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0822, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_RESUMETHREAD\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0823, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SUSPENDPROCESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0824, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_RESUMEPROCESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0825, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ALLOCATEMEM_NONPAGED\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0826, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPROCADDRESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0827, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n//#define IOCTL_CE_SETSDTADDRESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0828, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETSDTADDRESS\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0829, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_GETGDT \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SETCR4 \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETTR \t\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_VMXCONFIG\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETCR0 \t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_USERDEFINEDINTERRUPTHOOK\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x082f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SETGLOBALDEBUGSTATE\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0830, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_CONTINUEDEBUGEVENT\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0831, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_WAITFORDEBUGEVENT\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0832, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETDEBUGGERSTATE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0833, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SETDEBUGGERSTATE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0834, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GD_SETBREAKPOINT\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0835, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_TOUCHDEBUGREGISTER\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0836, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_LAUNCHDBVM\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_UNHOOKALLINTERRUPTS\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_EXECUTE_CODE\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETPROCESSNAMEADDRESS\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_SETKERNELSTEPABILITY\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_READMSR\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x083f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_WRITEMSR\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0840, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_SETSTORELBR\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0841, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0842, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP_DISABLE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0843, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP_WAITFORDATA\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0844, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP_CONTINUE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0845, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP_FLUSH\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0846, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_GETMEMORYRANGES\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0847, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_STARTACCESMONITOR\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0848, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ENUMACCESSEDMEMORY \t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0849, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GETACCESSEDMEMORYLIST\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_WRITESIGNOREWP\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_FREE_NONPAGED\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_MAP_MEMORY\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_UNMAP_MEMORY\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ULTIMAP2\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x084f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_DISABLEULTIMAP2\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0850, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_WAITFORDATA\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0851, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_CONTINUE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0852, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_FLUSH\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0853, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_PAUSE\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_RESUME\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ULTIMAP2_LOCKFILE\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0856, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_RELEASEFILE\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0857, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ULTIMAP_PAUSE  \t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0858, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP_RESUME  \t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0859, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ULTIMAP2_GETTRACESIZE\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ULTIMAP2_RESETTRACESIZE\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_ENABLE_DRM\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_GET_PEB\t\t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_QUERYINFORMATIONPROCESS\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_NTPROTECTVIRTUALMEMORY \t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x085f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n#define IOCTL_CE_LOCK_MEMORY \t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0860, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_UNLOCK_MEMORY \t\t\t\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0861, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n#define IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM\t\tCTL_CODE(IOCTL_UNKNOWN_BASE, 0x0862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)\n\n\nextern PVOID DRMHandle;\n\n#define SYSTEMSERVICE(_function)\t\tKeServiceDescriptorTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]\n#define SYSTEMSERVICELINK(_function)\tKeServiceDescriptorTable->ServiceTable[*((PUCHAR)(*(PULONG)*((PULONG)((PUCHAR)_function+2)))+1)]\n\n\nNTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);\nBOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned);\n\n\n\n#endif"
  },
  {
    "path": "src/amd64/dbkfunca.asm",
    "content": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n;I should probably start converting to inrinsics\n\n_TEXT SEGMENT 'CODE'\nPUBLIC getCS\ngetCS:\n\tmov ax,cs\n\tret\n\nPUBLIC getSS\ngetSS:\n\tmov ax,ss\n\tret\n\t\nPUBLIC getDS\ngetDS:\n\tmov ax,ds\n\tret\n\t\nPUBLIC getES\ngetES:\n\tmov ax,es\n\tret\t\n\t\nPUBLIC getFS\ngetFS:\n\tmov ax,fs\n\tret\n\t\nPUBLIC getGS\ngetGS:\n\tmov ax,gs\n\tret\t\n\t\nPUBLIC GetTR\nGetTR:\n\tSTR AX\n\tret\t\n\t\nPUBLIC GetLDT\nGetLDT:\n\tSLDT ax\n\tret\n\t\nPUBLIC GetGDT\nGetGDT:\n\tSGDT [rcx]\n\tret\n\t\nPUBLIC _fxsave\n_fxsave:\n    fxsave [rcx]\n    ret\n\t\nPUBLIC getRSP\ngetRSP:\n\tmov rax,rsp\n\tadd rax,8 ;undo the call push\n\tret\t\n\t\nPUBLIC getRBP\ngetRBP:\n    push rbp\n    pop rax\t\n\tret\t\n\t\nPUBLIC getRAX\ngetRAX:\t\n\tret\t\t\t\t\t\t\t\n\t\nPUBLIC getRBX\ngetRBX:\n\tmov rax,rbx\n\tret\t\n\t\nPUBLIC getRCX\ngetRCX:\n\tmov rax,rcx\n\tret\t\n\t\nPUBLIC getRDX\ngetRDX:\n\tmov rax,rdx\n\tret\t\t\n\t\nPUBLIC getRSI\ngetRSI:\n\tmov rax,rsi\n\tret\t\t\n\t\nPUBLIC getRDI\ngetRDI:\n\tmov rax,rdi\n\tret\t\t\n\t\nPUBLIC getR8\ngetR8:\n\tmov rax,r8\n\tret\t\t\n\t\nPUBLIC getR9\ngetR9:\n\tmov rax,r9\n\tret\t\t\n\t\nPUBLIC getR10\ngetR10:\n\tmov rax,r10\n\tret\t\t\n\t\nPUBLIC getR11\ngetR11:\n\tmov rax,r11\n\tret\t\t\n\t\nPUBLIC getR12\ngetR12:\n\tmov rax,r12\n\tret\t\t\n\t\nPUBLIC getR13\ngetR13:\n\tmov rax,r13\n\tret\t\t\n\t\nPUBLIC getR14\ngetR14:\n\tmov rax,r14\n\tret\t\t\n\t\nPUBLIC getR15\ngetR15:\n\tmov rax,r15\n\tret\t\t\t\t\n\t\nPUBLIC getAccessRights\t\t\t\t\t\t\t\t\t\t\ngetAccessRights:\n  xor rax,rax\n  lar rax,rcx\n  jnz getAccessRights_invalid\n  shr rax,8\n  and rax,0f0ffh\n  ret\n  getAccessRights_invalid:\n  mov rax,010000h\n  ret\n\n\nPUBLIC getSegmentLimit\t\t\t\t\t\t\t\t\t\t\ngetSegmentLimit:\n  xor rax,rax\n  lsl rax,rcx\n  ret\n\n_TEXT   ENDS\n        END\n\n"
  },
  {
    "path": "src/amd64/debuggera.asm",
    "content": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK        struct\nA\t\t \t\tqword ?\nS\t\t\t\tqword ?\nCALLBACK        ends\n\n\nASMENTRY_STACK\tstruct ;keep this 16 byte aligned\n\tScratchspace\tqword ?\n\tScratchspace2\tqword ? \n\tScratchspace3\tqword ?\n\tScratchspace4\tqword ? \t\n\tOriginalmxcsr\tqword ?\t\n\tOriginalRAX\t\tqword ?  ;0\n\tOriginalRBX\t\tqword ?  ;1\n\tOriginalRCX\t\tqword ?  ;2\n\tOriginalRDX\t\tqword ?  ;3\n\tOriginalRSI\t\tqword ?  ;4\n\tOriginalRDI\t\tqword ?  ;5\n\tOriginalRBP\t\tqword ?  ;6\n\tOriginalRSP\t\tqword ?  ;7 not really 'original'\n\tOriginalR8\t\tqword ?  ;8\n\tOriginalR9\t\tqword ?  ;9\n\tOriginalR10\t\tqword ?  ;10\n\tOriginalR11\t\tqword ?  ;11\n\tOriginalR12\t\tqword ?  ;12\n\tOriginalR13\t\tqword ?  ;13\n\tOriginalR14\t\tqword ?  ;14\n\tOriginalR15\t\tqword ?  ;15\n\tOriginalES\t\tqword ?  ;16\n\tOriginalDS\t\tqword ?\t ;17\n\tOriginalSS\t\tqword ?\t ;18\n\tfxsavespace     db 512 dup(?)  ;fpu state\n\n\t;errorcode/returnaddress   ;19\n\t;4096 bytes \n\t;eip     ;20\n\t;cs      ;21\n\t;eflags\n\t;esp\n\t;ss\n\t\nASMENTRY_STACK\tends\n\n\n_TEXT SEGMENT 'CODE'\n\nEXTERN interrupt1_centry : proc\nEXTERN Int1JumpBackLocation : CALLBACK\n\nPUBLIC interrupt1_asmentry\ninterrupt1_asmentry:\n\t\t;save stack position\n\t\tpush [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\n\t\t\n\t\tsub rsp,4096  ;functions like setThreadContext adjust the stackframe entry directly. I can't have that messing up my own stack\n\n\t\tcld\t\t\t\n\n\t\t;stack is aligned at this point\n\t\tsub rsp,SIZEOF ASMENTRY_STACK\n\t\t\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp\n\t\tlea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX\n\t\t\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15\n\n\t\tfxsave (ASMENTRY_STACK PTR [rsp]).fxsavespace\n\n\t\n\t\t\n\t\t\n\t\t\n\t\tmov ax,ds\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax\n\t\t\n\t\tmov ax,es\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax\n\t\t\n\t\tmov ax,ss\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax\t\t\n\t\t\n\n\t\tmov ax,2bh \n\t\tmov ds,ax\n\t\tmov es,ax\n\t\t\n\t\tmov ax,18h\n\t\tmov ss,ax\n\t\t\n\t\t\n\t\t; rbp= pointer to OriginalRAX\n\t\t\n\t\tcmp qword ptr [rbp+8*21+512+4096],010h ;check if origin is in kernelmode (check ss)\n\t\tje skipswap1 ;if so, skip the swapgs\n\t\t\n\t\tswapgs ;swap gs with the kernel version\n\t\t\nskipswap1:\n\t\t\n\t\t\n\t\t\n\t\tstmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).scratchspace2,1f80h\t\t\n\t\tldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace2\n\n\t\t\n\t\tmov rcx,rbp\n\t\tcall interrupt1_centry\n\t\t\n\t\tldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr\n\t\t\n\t\tcmp qword ptr [rbp+8*21+512+4096],10h ;was it a kernelmode interrupt ?\n\t\tje skipswap2 ;if so, skip the swapgs part\n\t\t\t\t\n\t\tswapgs ;swap back\nskipswap2:\n\n\t\tcmp al,1\n\n\n\t\t;restore state\n\t\tfxrstor (ASMENTRY_STACK PTR [rsp]).fxsavespace\n\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS\n\t\tmov ds,ax\n\t\t\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES\n\t\tmov es,ax\n\t\t\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS\n\t\tmov ss,ax\n\t\t\n\t\t\n\t\tmov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX\n\t\tmov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX\n\t\tmov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX\n\t\tmov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX\n\t\tmov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI\n\t\tmov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI\n\t\tmov r8, (ASMENTRY_STACK PTR [rsp]).OriginalR8\n\t\tmov r9, (ASMENTRY_STACK PTR [rsp]).OriginalR9\n\t\tmov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10\n\t\tmov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11\n\t\tmov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12\n\t\tmov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13\n\t\tmov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14\n\t\tmov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15\n\n\t\n\t\tje skip_original_int1\n\t\t\n\t\t;stack unwind\n\t\tmov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP\n\t\tadd rsp,SIZEOF ASMENTRY_STACK  \n\t\tadd rsp,4096\n\n\t\t;at this point [rsp] holds the original int1 handler\n\t\tret ; used to be add rsp,8 ;+8 for the push 0\n\n\t\t;todo: do a jmp [Int1JumpBackLocationCPUNR] and have 256 Int1JumpBackLocationCPUNR's and each cpu goes to it's own interrupt1_asmentry[cpunr]\n\t\t\n\t\t;jmp [Int1JumpBackLocation.A] ;<-works fine\t\n\n\nskip_original_int1:\n\t\t;stack unwind\n\t\tmov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP\n\t\tadd rsp,SIZEOF ASMENTRY_STACK \t\n\t\tadd rsp,4096\n\t\tadd rsp,8  ;+8 for the push\t\n\t\t\n\t\tiretq\n\n\t\n_TEXT   ENDS\n        END\t"
  },
  {
    "path": "src/amd64/noexceptionsa.asm",
    "content": "_TEXT SEGMENT 'CODE'\n\nPUBLIC NoException14\nNoException14:\n\n;Security cookies sucks, so getjmp/longjmp are not usable\n;So, just falling back to an exceptionless Copy command instead\n;or disassemble the instruction RIP points at\n\n;rsp=errorcode\n;rsp+8=rip\n;rsp+10=cs     ;20\n;rsp+18=eflags\n;rsp+20=rsp\n;rsp+28=ss\n\nadd rsp,8 ;skip the errorcode\npush rax ;push rax -state as above again\nmov rax,ExceptionlessCopy_Exception\nmov [rsp+8],rax\npop rax\niretq ;go to the designated return address\n\n\nPUBLIC ExceptionlessCopy_Internal\n;rcx=destination\n;rdx=source\n;r8=size in bytes\n\nExceptionlessCopy_Internal:\npush rbp\nmov rbp,rsp\n\n;[rbp] = old rbp value\n;[rbp+8] = return address\n;[rbp+10h] - [rbp+30h] = scratchspace\n\nmov [rbp+10h],rsi\nmov [rbp+18h],rdi\n\nmov rsi,rdx\nmov rdi,rcx\nmov rcx,r8\n\nrep movsb  ;todo: split this up into movsq, movsd, movsw, movsd, or some of those other string routines\n\n;on exception just exit\n\nExceptionlessCopy_Exception:\nmov rsi,[rbp+10h]\nmov rdi,[rbp+18h]\nsub r8,rcx ;decrease the number of bytes left from the total amount of bytes to get the total bytes written\nmov rax,r8 \n\npop rbp\nret\n\n\n\n_TEXT   ENDS\n        END\t"
  },
  {
    "path": "src/amd64/ultimapa.asm",
    "content": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK        struct\nA\t\t \t\tqword ?\nS\t\t\t\tqword ?\nCALLBACK        ends\n\n\nASMENTRY_STACK\tstruct ;keep this 16 byte aligned\n\tScratchspace\tqword ?   ;0\n\tScratchspace2\tqword ?   ;8\n\tScratchspace3\tqword ?   ;0\n\tScratchspace4\tqword ?   ;8\n\tOriginalmxcsr\tqword ?\t\n\tOriginalRAX\t\tqword ?\n\tOriginalRBX\t\tqword ?\n\tOriginalRCX\t\tqword ?\n\tOriginalRDX\t\tqword ?\n\tOriginalRSI\t\tqword ?\n\tOriginalRDI\t\tqword ?\n\tOriginalRBP\t\tqword ?\n\tOriginalRSP\t\tqword ? ;not really 'original'\n\tOriginalR8\t\tqword ?\n\tOriginalR9\t\tqword ?\n\tOriginalR10\t\tqword ?\n\tOriginalR11\t\tqword ?\n\tOriginalR12\t\tqword ?\n\tOriginalR13\t\tqword ?\n\tOriginalR14\t\tqword ?\n\tOriginalR15\t\tqword ?\n\tOriginalES\t\tqword ?\n\tOriginalDS\t\tqword ?\t\t\n\tOriginalSS\t\tqword ?\t\n\t\nASMENTRY_STACK\tends\n\n\n_TEXT SEGMENT 'CODE'\n\nEXTERN perfmon_interrupt_centry : proc\nEXTERN perfmonJumpBackLocation : CALLBACK\n\nPUBLIC perfmon_interrupt\n\n\n\nperfmon_interrupt:\n\t\t;save stack position\n\t\t\n\t\tcld\t\t\t\n\t\tpush 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)\n\t\t\n\t\t;stack is aligned at this point\n\t\tsub rsp, 4096\n\t\t\n\t\tsub rsp,SIZEOF ASMENTRY_STACK\n\t\t\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp\n\t\tlea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX ;make rbp point to the start of the structure\n\t\t\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14\n\t\tmov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15\n\t\n\t\t\n\t\tmov ax,ds\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax\n\t\t\n\t\tmov ax,es\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax\n\t\t\n\t\tmov ax,ss\n\t\tmov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax\t\t\n\t\t\n\n\t\tmov ax,2bh \n\t\tmov ds,ax\n\t\tmov es,ax\n\t\t\n\t\tmov ax,18h\n\t\tmov ss,ax\n\t\t\n\t\t\n\t\tcmp qword ptr [rbp+8*21+4096],010h ;check if origin is in kernelmode (check ss)\n\t\tje skipswap1 ;if so, skip the swapgs\n\t\t\n\t\tswapgs ;swap gs with the kernel version (not to self fix when called from inside kernel)\n\t\t\nskipswap1:\n\t\t\n\t\t\n\t\t\n\t\tstmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr\n\t\t\n\t\tmov (ASMENTRY_STACK PTR [rsp]).scratchspace,1f80h\t\t\n\t\tldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace\n\n\n\t\t\n\t\t;mov rcx,rbp\n\t\tcall perfmon_interrupt_centry\n\t\t\n\t\tldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr\n\t\t\n\t\tcmp qword ptr [rbp+8*21+4096],10h ;was it a kernelmode interrupt ?\n\t\tje skipswap2 ;if so, skip the swapgs part\n\t\t\t\t\n\t\tswapgs ;swap back\nskipswap2:\n\n\t\tcmp al,1\n\n\n\t\t;restore state\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS\n\t\tmov ds,ax\n\t\t\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES\n\t\tmov es,ax\n\t\t\n\t\tmov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS\n\t\tmov ss,ax\n\t\t\n\t\t\n\t\tmov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX\n\t\tmov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX\n\t\tmov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX\n\t\tmov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX\n\t\tmov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI\n\t\tmov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI\n\t\tmov r8,(ASMENTRY_STACK PTR [rsp]).OriginalR8\n\t\tmov r9,(ASMENTRY_STACK PTR [rsp]).OriginalR9\n\t\tmov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10\n\t\tmov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11\n\t\tmov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12\n\t\tmov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13\n\t\tmov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14\n\t\tmov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15\n\n\t\n\t\tje skip_original_perfmon\n\t\tjmp skip_original_perfmon\n\t\t\n\t\t;stack unwind\n\t\tmov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP\n\t\tadd rsp,SIZEOF ASMENTRY_STACK  ;+8 for the push 0\n\t\tadd rsp,8\n\t\t\n\t\tadd rsp,4096\n\t\t\n\t\t\n\t\tjmp [perfmonJumpBackLocation.A] ;<-works fine\t\n\n\nskip_original_perfmon:\n\t\t;stack unwind\n\t\tmov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP\n\t\tadd rsp,SIZEOF ASMENTRY_STACK  ;+8 for the push 0\t\n\t\t\n\t\tadd rsp,4096\n\t\tadd rsp,8\n\n;jump to when the stack has been completly restored to what it was at interrupt time\n\t    ;push rax\n\t\t;push rbx\n\t\t\t\t\n\t\t;unmask the perfmon interrupt\n\t\t;mov rax,0fffffffffffe0330h\n\t\t;mov rbx,[rax]\n\t\t;and rbx,0ffh\n\t\t;mov [rax],rbx \n\t\t\n\t\t;End of interrupt\n\t\n\t\t;mov rax,0fffffffffffe00b0h\n\t\t;xor rbx,rbx\n\t\t;mov [rax],rbx ;set EOI to 0\t\t\n\t\t\t\t\n\t\t;pop rbx\n\t\t;pop rax\n\t\t\n\t\tiretq\n  \n  \t\t\n\n\t\n_TEXT   ENDS\n        END\t"
  },
  {
    "path": "src/amd64/vmxhelpera.asm",
    "content": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n\n;vmcall:  rdx = password1  info(rax)->password(@offset 4)=password 2\n\n;vmcall(info)\n\nextern vmx_password1 : QWORD\nextern vmx_password3 : QWORD\n\n_TEXT SEGMENT 'CODE'\nPUBLIC dovmcall_intel\ndovmcall_intel:\n\tmov rax,rcx\n\tmov rdx,vmx_password1\n\tmov rcx,vmx_password3\n\tvmcall\n\tret\n\t\nPUBLIC dovmcall_amd\ndovmcall_amd:\n\tmov rax,rcx\n\tmov rdx,vmx_password1\n\tmov rcx,vmx_password3\n\tvmmcall\n\tret\t\n\t\n_TEXT   ENDS\n        END\t"
  },
  {
    "path": "src/amd64/vmxoffloada.asm",
    "content": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nGDTDesc\tSTRUCT\nLimit\tWORD\t?\nBase\tQWORD\t?\nGDTDesc\tENDS\n\nS_ORIGINALSTATE STRUCT\n_cpucount\t\tQWORD ?\n_originalEFER   QWORD ?\n_originalLME\tQWORD ?\n_idtbase\t\tQWORD ?\n_idtlimit\t\tQWORD ?\n_gdtbase\t\tQWORD ?\n_gdtlimit\t\tQWORD ?\n_cr0\t\t\tQWORD ?\n_cr2\t\t\tQWORD ?\n_cr3\t\t\tQWORD ?\n_cr4\t\t\tQWORD ?\n_dr7\t\t\tQWORD ?\n_rip\t\t\tQWORD ?\n_rax\t\t\tQWORD ?\n_rbx\t\t\tQWORD ?\n_rcx\t\t\tQWORD ?\n_rdx\t\t\tQWORD ?\n_rsi\t\t\tQWORD ?\n_rdi\t\t\tQWORD ?\n_rbp\t\t\tQWORD ?\n_rsp\t\t\tQWORD ?\n_r8\t\t\t\tQWORD ?\n_r9\t\t\t\tQWORD ?\n_r10\t\t\tQWORD ?\n_r11\t\t\tQWORD ?\n_r12\t\t\tQWORD ?\n_r13\t\t\tQWORD ?\n_r14\t\t\tQWORD ?\n_r15\t\t\tQWORD ?\n_rflags\t\t\tQWORD ?\n_cs\t\t\t\tQWORD ?\n_ss\t\t\t\tQWORD ?\n_ds\t\t\t\tQWORD ?\n_es\t\t\t\tQWORD ?\n_fs\t\t\t\tQWORD ?\n_gs\t\t\t\tQWORD ?\n_tr\t\t\t\tQWORD ?\n_ldt\t\t\tQWORD ?\t\n_cs_AccessRights\tQWORD ?\t\n_ss_AccessRights\tQWORD ?\t\n_ds_AccessRights\tQWORD ?\t\n_es_AccessRights\tQWORD ?\t\n_fs_AccessRights\tQWORD ?\t\n_gs_AccessRights\tQWORD ?\t\n_cs_Limit\tQWORD ?\t\n_ss_Limit\tQWORD ?\t\n_ds_Limit\tQWORD ?\t\n_es_Limit\tQWORD ?\t\n_fs_Limit\tQWORD ?\t\n_gs_Limit\tQWORD ?\t\n_fsbase\t\t\tQWORD ?\n_gsbase\t\t\tQWORD ?\nS_ORIGINALSTATE ENDS\nPS_ORIGNALSTATE TYPEDEF PTR S_ORIGINALSTATE\n\n\nEXTERN NewGDTDescriptor: GDTDesc\nEXTERN NewGDTDescriptorVA: QWORD\nEXTERN DBVMPML4PA: QWORD\nEXTERN TemporaryPagingSetupPA: QWORD\nEXTERN enterVMM2PA: QWORD\nEXTERN originalstatePA: QWORD\nEXTERN enterVMM2: QWORD\n\nEXTERN originalstate: PS_ORIGNALSTATE\nEXTERN vmmPA: QWORD\n\n_TEXT SEGMENT 'CODE'\n\nPUBLIC JTAGBP\nJTAGBP:\ndb 0f1h\nret\n\nPUBLIC enterVMM\nenterVMM:\nbegin:\n\t;switch to identity mapped pagetable\n\n\tmov cr3,rdx\n\tjmp short weee\nweee:\n\tnop\n\tnop\n\n\t\n\t;now jump to the physical address (identity mapped to the same virtual address)\n\tmov rax,secondentry\n\tmov r8,enterVMM\n    sub rax,r8\n\tadd rax,rsi ;add the physical address to the offset location\t\n\t\n\tjmp rax\n\nsecondentry:\n\t;contrary to the 32-bit setup, we don't disable paging to make the switch to 64-bit, we're already there\n\t;we can just set the CR3 value\n\t\n\t\n;----------TEST----------\n;\twaitforready:\n;\tmov dx,0ec05h\n;\tin al,dx\n;\tand al,20h\n;\tcmp al,20h\n;\tjne waitforready\n;\t\n;\tmov dx,0ec00h\n;\tmov al,'1'\n;\tout dx,al\n;^^^^^^^^TEST^^^^^^^^\n\t\n\n\t;enable PAE and PSE (just to make sure)\n\tmov eax,30h\n\tmov cr4,rax\t\n\n\tmov cr3,rcx\n\tnop\n\tnop\n\tjmp short weee2\nweee2:\n    nop\n\tnop\n\n\tmov rbx,0\n\tmov ds,bx\n\tmov es,bx\n\tmov fs,bx\n\tmov gs,bx\n\tmov ss,bx\n\t\n\tmov rax,cr0\n\tor eax,10000h\n\tmov cr0,rax ;enable WP bit\n\t\t\n\tnop\n\tnop\n\tnop\n\tnop\n\t;db 0f1h  ;jtag\n\tnop\n\tnop\n\tnop\t\n\n\t\n\tjmp fword ptr [vmmjump]\n\t;jmp fword ptr [vmmjump] ;one thing that I don't mind about x64, relative addressing, so no need to change it by me\n\n\nextrastorage:\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\nvmmjump:\t\n\tdd 00400000h\n\tdw 50h\t\n\t\n\ndetectionstring:\n\tdb 0ceh\n\tdb 0ceh\n\tdb 0ceh\n\tdb 0ceh\n\tdb 0ceh\n\tdb 0ceh\n\tdb 0ceh\n\t\n\t\nPUBLIC enterVMMPrologue\nenterVMMPrologue:\t\n\tcli ;goodbye interrupts\n\t\n\tpush rbx\n\tmov rbx,originalstate\n\tmov (S_ORIGINALSTATE PTR [rbx])._rax,rax\n\tpop rbx\n\t\n\tmov rax,originalstate\t\n\tmov (S_ORIGINALSTATE PTR [rax])._rbx,rbx\n\tmov (S_ORIGINALSTATE PTR [rax])._rcx,rcx\n\tmov (S_ORIGINALSTATE PTR [rax])._rdx,rdx\n\tmov (S_ORIGINALSTATE PTR [rax])._rsi,rsi\n\tmov (S_ORIGINALSTATE PTR [rax])._rdi,rdi\t\n\tmov (S_ORIGINALSTATE PTR [rax])._rbp,rbp\n\tmov (S_ORIGINALSTATE PTR [rax])._rsp,rsp\n\tmov (S_ORIGINALSTATE PTR [rax])._r8,r8\n\tmov (S_ORIGINALSTATE PTR [rax])._r9,r9\n\tmov (S_ORIGINALSTATE PTR [rax])._r10,r10\n\tmov (S_ORIGINALSTATE PTR [rax])._r11,r11\n\tmov (S_ORIGINALSTATE PTR [rax])._r12,r12\n\tmov (S_ORIGINALSTATE PTR [rax])._r13,r13\n\tmov (S_ORIGINALSTATE PTR [rax])._r14,r14\n\tmov (S_ORIGINALSTATE PTR [rax])._r15,r15\n\t\n\tmov rbx,enterVMMEpilogue\n\tmov (S_ORIGINALSTATE PTR [rax])._rip,rbx\n\t\n\t;jmp enterVMMEpilogue ;test to see if the loader is bugged\n\t\n\t;still here, loader didn't crash, start executing the move to the dbvm environment\n\txchg bx,bx ;bochs break\n\t\n\tmov rbx,NewGDTDescriptorVA\n\tlgdt fword ptr [rbx]\n\t\n\tmov rcx,DBVMPML4PA\n\tmov rdx,TemporaryPagingSetupPA \n\tmov rsi,enterVMM2PA\n\t\n\n\tjmp [enterVMM2]\n\t\t\t\nPUBLIC enterVMMEpilogue\nenterVMMEpilogue:\n\tnop\n\tnop\n\tpush rax\n\tpush rbx\n\tpush rcx\n\tpush rdx\t\n\tcpuid\n\tpop rdx\n\tpop rcx\n\tpop rbx\n\tpop rax\n\tnop\t\t\t\t\t\t\n\tnop\t\n\tnop\t\n\t\n\t\n\t\n\n\t\n\tmov r8,originalstate\t\n\t\n\t;mov rbx,(S_ORIGINALSTATE PTR [r8])._tr\n\t;ltr bx\n\n\tmov rbx,(S_ORIGINALSTATE PTR [r8])._ss\n\tmov ss,bx\t\n\tmov rbx,(S_ORIGINALSTATE PTR [r8])._ds\n\tmov ds,bx\n\tmov rbx,(S_ORIGINALSTATE PTR [r8])._es\n\tmov es,bx\n\tmov rbx,(S_ORIGINALSTATE PTR [r8])._fs\n\tmov fs,bx\n\tmov rbx,(S_ORIGINALSTATE PTR [r8])._gs\n\tmov gs,bx\n\t\n\t\n\t\n\tmov rcx,0c0000100h\n\tmov rax,(S_ORIGINALSTATE PTR [r8])._fsbase\n\tmov rdx,rax\n\tshr rdx,32\n\twrmsr\n\t\n\tmov rcx,0c0000101h\n\tmov rax,(S_ORIGINALSTATE PTR [r8])._gsbase\n\tmov rdx,rax\n\tshr rdx,32\n\twrmsr\n\n\t\n\n\t\n\t\t\n\tmov rax,originalstate\t\n\tmov rbx,(S_ORIGINALSTATE PTR [rax])._rbx\n\tmov rcx,(S_ORIGINALSTATE PTR [rax])._rcx\n\tmov rdx,(S_ORIGINALSTATE PTR [rax])._rdx\n\tmov rsi,(S_ORIGINALSTATE PTR [rax])._rsi\n\tmov rdi,(S_ORIGINALSTATE PTR [rax])._rdi\n\tmov rbp,(S_ORIGINALSTATE PTR [rax])._rbp\n\tmov rsp,(S_ORIGINALSTATE PTR [rax])._rsp\n\tmov r8,(S_ORIGINALSTATE PTR [rax])._r8\n\tmov r9,(S_ORIGINALSTATE PTR [rax])._r9\n\tmov r10,(S_ORIGINALSTATE PTR [rax])._r10\n\tmov r11,(S_ORIGINALSTATE PTR [rax])._r11\n\tmov r12,(S_ORIGINALSTATE PTR [rax])._r12\n\tmov r13,(S_ORIGINALSTATE PTR [rax])._r13\n\tmov r14,(S_ORIGINALSTATE PTR [rax])._r14\n\tmov r15,(S_ORIGINALSTATE PTR [rax])._r15\n\tmov rax,(S_ORIGINALSTATE PTR [rax])._rax\n\t\n\t;crashtest\n\t;mov rax,0deadh\n\t;mov [rax],rax\n\t\n\t;sti\n\tret\n\tnop\n\tnop\n\tnop\n\n_TEXT   ENDS\n        END"
  },
  {
    "path": "src/debugger.c",
    "content": "/*\ndebugger.c:\nThis unit will handle all debugging related code, from hooking, to handling interrupts\n\ntodo: this whole thing can be moved to a few simple lines in dbvm...\n*/\n#pragma warning( disable: 4100 4103 4189)\n#include <ntifs.h>\n#include <windef.h>\n\n#include \"DBKFunc.h\"\n#include \"interruptHook.h\"\n\n#include \"debugger.h\"\n#include \"vmxhelper.h\"\n\n#ifdef AMD64 \nextern void interrupt1_asmentry( void ); //declared in debuggera.asm\n#else\nvoid interrupt1_asmentry( void );\n#endif\n\n\n\nvolatile struct\n{\n\tBOOL\t\tisDebugging;\t\t//TRUE if a process is currently being debugged\n\tBOOL\t\tstoppingTheDebugger;\n\tDWORD\t\tdebuggedProcessID;\t//The processID that is currently debugger\n\tstruct {\n\t\tBOOL\t\tactive;\n\t\tUINT_PTR\taddress;\t\t//Up to 4 addresses to break on\n\t\tBreakType\tbreakType;\t\t//What type of breakpoint for each seperate address\n\t\tBreakLength breakLength;\t//How many bytes does this breakpoint look at\n\t} breakpoint[4];\n\n\t//...\n\tBOOL globalDebug;\t\t\t//If set all threads of every process will raise an interrupt on taskswitch\n\n\t//while debugging:\n\tUINT_PTR *LastStackPointer;\n\tUINT_PTR *LastRealDebugRegisters;\n\tHANDLE LastThreadID;\n\tBOOL CausedByDBVM;\n\tBOOL handledlastevent;\n\t\n\t//BOOL storeLBR;\n\t//int storeLBR_max;\n\t//UINT_PTR *LastLBRStack;\n\n\tvolatile struct {\t\t\n\t\tUINT_PTR DR0;\n\t\tUINT_PTR DR1;\n\t\tUINT_PTR DR2;\n\t\tUINT_PTR DR3;\n\t\tUINT_PTR DR6;\n\t\tUINT_PTR DR7;\n\t\tUINT_PTR reserved;\n\t\tvolatile int inEpilogue; //if set the global debug bit does no faking\n\t} FakedDebugRegisterState[256];\n\n\tchar b[1];\n\n\t//volatile BYTE DECLSPEC_ALIGN(16) fxstate[512];\n\n\tBOOL 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\n\n} DebuggerState;\n\n\nKEVENT debugger_event_WaitForContinue; //event for kernelmode. Waits till it's set by usermode (usermode function: DBK_Continue_Debug_Event sets it)\nKEVENT debugger_event_CanBreak; //event for kernelmode. Waits till a break has been handled so a new one can enter\nKEVENT debugger_event_WaitForDebugEvent; //event for usermode. Waits till it's set by a debugged event\n\nDebugReg7 debugger_dr7_getValue(void);\nvoid debugger_dr7_setValue(DebugReg7 value);\nDebugReg6 debugger_dr6_getValue(void);\n\nJUMPBACK Int1JumpBackLocation;\n\n\n\ntypedef struct _SavedStack\n{\n\tBOOL inuse;\n\tQWORD stacksnapshot[600];\n} SavedStack, *PSavedStack;\n\ncriticalSection StacksCS;\nint StackCount;\nPSavedStack *Stacks;\n\n\n\nvoid debugger_dr7_setGD(int state)\n{\n\n\tDebugReg7 _dr7=debugger_dr7_getValue();\n\t_dr7.GD=state; //usually 1\n\tdebugger_dr7_setValue(_dr7);\n\n\t\n}\n\nvoid debugger_dr0_setValue(UINT_PTR value)\n{\n\t__writedr(0,value);\n}\n\nUINT_PTR debugger_dr0_getValue(void)\n{\n\treturn __readdr(0);\n}\n\nvoid debugger_dr1_setValue(UINT_PTR value)\n{\n\t__writedr(1,value);\n}\n\nUINT_PTR debugger_dr1_getValue(void)\n{\n\treturn __readdr(1);\n}\n\nvoid debugger_dr2_setValue(UINT_PTR value)\n{\n\t__writedr(2,value);\n}\n\nUINT_PTR debugger_dr2_getValue(void)\n{\n\treturn __readdr(2);\n}\n\nvoid debugger_dr3_setValue(UINT_PTR value)\n{\n\t__writedr(3,value);\n}\n\nUINT_PTR debugger_dr3_getValue(void)\n{\n\treturn __readdr(3);\n}\n\nvoid debugger_dr6_setValue(UINT_PTR value)\n{\n\t__writedr(6,value);\n}\n\nvoid debugger_dr7_setValue(DebugReg7 value)\n{\n\tUINT_PTR temp=*(UINT_PTR *)&value;\t\t\n\t__writedr(7,temp);\n}\n\nvoid debugger_dr7_setValueDword(UINT_PTR value)\n{\n\t__writedr(7,value);\t\n}\n\nUINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just typecast the DebugReg7 to a dword...\n{\n\treturn __readdr(7);\n}\n\n\nDebugReg7 debugger_dr7_getValue(void)\n{\n\tUINT_PTR temp=debugger_dr7_getValueDword();\n\treturn *(DebugReg7 *)&temp;\n}\n\nUINT_PTR debugger_dr6_getValueDword(void)\n{\n\treturn __readdr(6);\n}\n\nDebugReg6 debugger_dr6_getValue(void)\n{\n\tUINT_PTR temp=debugger_dr6_getValueDword();\n\treturn *(DebugReg6 *)&temp;\n}\n\n\n\nvoid debugger_touchDebugRegister(UINT_PTR param)\n{\n\t//DbgPrint(\"Touching debug register. inepilogue=\\n\", DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue);\n\n\t\n\tdebugger_dr0_setValue(debugger_dr0_getValue());\n\t\n}\n\nvoid debugger_initialize(void)\n{\n\t//DbgPrint(\"Initializing debugger events\\n\");\n\n\tKeInitializeEvent(&debugger_event_WaitForContinue, SynchronizationEvent, FALSE);\t\n\tKeInitializeEvent(&debugger_event_CanBreak, SynchronizationEvent, TRUE); //true so the first can enter\n\tKeInitializeEvent(&debugger_event_WaitForDebugEvent, SynchronizationEvent, FALSE);\n\n\t//DbgPrint(\"DebuggerState.fxstate=%p\\n\",DebuggerState.fxstate);\n\n\n\n\tStackCount = getCpuCount() * 4;\n\tStacks = (PSavedStack*)ExAllocatePool(NonPagedPool, StackCount*sizeof(PSavedStack));\n\n\n\tint i;\n\tfor (i = 0; i < StackCount; i++)\n\t{\n\t\tStacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));\n\t\tRtlZeroMemory(Stacks[i], sizeof(SavedStack));\n\t}\n}\n\nvoid debugger_shutdown(void)\n{\n\tif (Stacks)\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < StackCount; i++)\n\t\t{\n\t\t\tif (Stacks[i])\n\t\t\t{\n\t\t\t\tExFreePool(Stacks[i]);\n\t\t\t\tStacks[i] = NULL;\n\t\t\t}\n\t\t}\n\n\t\tExFreePool(Stacks);\n\t\tStacks = NULL;\n\t}\n}\n\nvoid debugger_growstack()\n//called in passive mode\n{\n\tif (Stacks)\n\t{\n\t\tKIRQL oldIRQL=KeRaiseIrqlToDpcLevel();\n\n\t\tcsEnter(&StacksCS);\n\t\tenableInterrupts(); //csEnter disables it, but we need it\n\n\t\tint newStackCount = StackCount * 2;\n\t\tint i;\n\t\tPSavedStack *newStacks;\n\t\tnewStacks = (PSavedStack*)ExAllocatePool(NonPagedPool, newStackCount * sizeof(PSavedStack));\n\n\t\tif (newStacks)\n\t\t{\n\t\t\tfor (i = 0; i < StackCount; i++)\n\t\t\t\tnewStacks[i] = Stacks[i];\n\n\t\t\tfor (i = StackCount; i < newStackCount; i++)\n\t\t\t{\n\t\t\t\tnewStacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));\n\t\t\t\tif (newStacks[i])\t\t\t\t\n\t\t\t\t\tRtlZeroMemory(newStacks[i], sizeof(SavedStack));\t\t\t\t\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tExFreePool(newStacks);\n\t\t\t\t\tcsLeave(&StacksCS);\n\t\t\t\t\tKeLowerIrql(oldIRQL);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\n\t\t\tExFreePool(Stacks);\n\t\t\tStacks = newStacks;\n\t\t}\n\n\t\tcsLeave(&StacksCS);\n\t\tKeLowerIrql(oldIRQL);\n\n\t}\n}\n\nvoid debugger_setInitialFakeState(void)\n{\t\n\t//DbgPrint(\"setInitialFakeState for cpu %d\\n\",cpunr());\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR0=debugger_dr0_getValue();\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR1=debugger_dr1_getValue();\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR2=debugger_dr2_getValue();\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR3=debugger_dr3_getValue();\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR6=debugger_dr6_getValueDword();\n\tDebuggerState.FakedDebugRegisterState[cpunr()].DR7=debugger_dr7_getValueDword();\n}\n\nVOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2)\n{\n\tdebugger_initHookForCurrentCPU();\n}\n\nint debugger_removeHookForCurrentCPU(UINT_PTR params)\n{\n\t//DbgPrint(\"Unhooking int1 for this cpu\\n\");\n    return inthook_UnhookInterrupt(1);\t\n}\n\nint debugger_initHookForCurrentCPU(void)\n/*\nMust be called for each cpu\n*/\n{\n\tint result=TRUE;\n\t//DbgPrint(\"Hooking int1 for cpu %d\\n\", cpunr());\n\t\n\tresult=inthook_HookInterrupt(1,getCS() & 0xfff8, (ULONG_PTR)interrupt1_asmentry, &Int1JumpBackLocation);\t\n\n#ifdef AMD64\n\tif (result)\n\t{\n\t\t;//DbgPrint(\"hooked int1. Int1JumpBackLocation=%x:%llx\\n\", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);\n\t}\n\telse\n\t{\n\t\t//DbgPrint(\"Failed hooking interrupt 1\\n\");\n\t\treturn result;\n\t}\n#endif\n\n\tif (DebuggerState.globalDebug)\n\t{\n\t\t//set the fake state\n\t\t//debugger_setInitialFakeState();\n\t\t//DbgPrint(\"Setting GD bit for cpu %d\\n\",cpunr());\n\n\t\tdebugger_dr7_setGD(1); //enable the GD flag\t\t\n\t}\n\n\t/*if (DebuggerState.storeLBR)\n\t{\t\t\n\t\t//DbgPrint(\"Enabling LBR logging. IA32_DEBUGCTL was %x\\n\", __readmsr(0x1d9));\n\t\t__writemsr(0x1d9, __readmsr(0x1d9) | 1);\n\t\t//DbgPrint(\"Enabling LBR logging. IA32_DEBUGCTL is  %x\\n\", __readmsr(0x1d9));\n\t}*/\n\t\t\n\treturn result;\n}\n\nvoid debugger_setStoreLBR(BOOL state)\n{\n\treturn; //disabled for now\n\t/*\n\t//if (state)\n\t//\tDbgPrint(\"Setting storeLBR to true\\n\");\n\t//else\n\t//\tDbgPrint(\"Setting storeLBR to false\\n\");\n\n\tDebuggerState.storeLBR=state; //it's not THAT crucial to disable/enable it\n\n\tDebuggerState.storeLBR_max=0;\n\n\tswitch (cpu_model)\n    {\n        case 0x2a:\n        case 0x1a:\n        case 0x1e:\n        case 0x1f:\n        case 0x2e:\n        case 0x25:\n        case 0x2c:\n          DebuggerState.storeLBR_max=16;\n          break;\n\n        case 0x17:\n        case 0x1d:\n        case 0x0f:\n          DebuggerState.storeLBR_max=4;\n          break;\n\n        case 0x1c:\n          DebuggerState.storeLBR_max=8;\n          break;\n    }\n\n\t//DbgPrint(\"Because your cpu_model=%d I think that your storeLBR_max=%d\\n\", cpu_model, DebuggerState.storeLBR_max);\n\t*/\n\t\n}\n\n\nint debugger_setGlobalDebugState(BOOL state)\n//call this BEFORE debugging, if already debugging, the user must call this for each cpu\n{\n\t//DbgPrint(\"debugger_setGlobalDebugState(%d)\\n\",state);\n\tif (state)\n\t  DebuggerState.globalDebug=state; //on enable set this first\n\n\tif (inthook_isHooked(1))\n\t{\n\t\tint oldEpilogueState=DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue;\n\n\t\t//DbgPrint(\"Int 1 is hooked,%ssetting GD\\n\",(state ? \"\":\"un\"));\n\t\t//DbgPrint(\"oldEpilogueState=%d\\n\",oldEpilogueState);\n\t\t//debugger_setInitialFakeState();\n\n\t\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=TRUE;\n\t\tDebuggerState.globalDebug=state;\n\t\tdebugger_dr7_setGD(state);\n\t\t\n\t\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=oldEpilogueState;\n\t\t\n\n\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR7=0x400;\n\t\tdebugger_dr7_setValueDword(0x400);\t\t\n\n\t}\n\n\treturn TRUE;\n}\n\n\n\nint debugger_startDebugging(DWORD debuggedProcessID)\n/*\nCall this AFTER the interrupts are hooked\n*/\n{\n\t//DbgPrint(\"debugger_startDebugging. Processid=%x\\n\",debuggedProcessID);\n\tInt1JumpBackLocation.eip=inthook_getOriginalEIP(1);\n\tInt1JumpBackLocation.cs=inthook_getOriginalCS(1);\n\n#ifdef AMD64\n\t//DbgPrint(\"Int1 jump back = %x:%llx\\n\", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);\n#endif\n\n\tDebuggerState.isDebugging=TRUE;\n\tDebuggerState.debuggedProcessID=debuggedProcessID;\n\n\treturn TRUE;\n}\n\nint debugger_stopDebugging(void)\n{\t\n\tint i;\n\n\t//DbgPrint(\"Stopping the debugger if it is running\\n\");\n\n\tDebuggerState.stoppingTheDebugger=TRUE;\t\n\n\tif (DebuggerState.globalDebug)\n\t{\n\t\t//touch the global debug for each debug processor\n\t\t//DbgPrint(\"Touching the debug registers\\n\");\n        forEachCpuPassive(debugger_touchDebugRegister, 0);\n\t}\n\n\t\n\n    DebuggerState.globalDebug=FALSE; //stop when possible, saves speed\n\tDebuggerState.isDebugging=FALSE;\t\n\n\tfor (i=0; i<4; i++)\n\t\tDebuggerState.breakpoint[i].active=FALSE;\n\n\t//unhook all processors\n\n\tforEachCpuPassive(debugger_removeHookForCurrentCPU, 0);\n\n\n\treturn TRUE;\n}\n\nint debugger_unsetGDBreakpoint(int breakpointnr)\n{\n\tint result=DebuggerState.breakpoint[breakpointnr].active;\n\tDebuggerState.breakpoint[breakpointnr].active=FALSE;\n\treturn result; //returns true if it was active\n}\n\nint debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl)\n/*\nWill register a specific breakpoint. If global debug is used it'll set this debug register accordingly\n*/\n{\n\t//DbgPrint(\"debugger_setGDBreakpoint(%d, %x, %d, %d)\\n\", breakpointnr, Address, bt, bl);\n\tDebuggerState.breakpoint[breakpointnr].active=TRUE;\n\tDebuggerState.breakpoint[breakpointnr].address=Address;\n\tDebuggerState.breakpoint[breakpointnr].breakType=bt;\n\tDebuggerState.breakpoint[breakpointnr].breakLength=bl;\n\treturn TRUE;\n}\n\nNTSTATUS debugger_waitForDebugEvent(ULONG timeout)\n{\n\tNTSTATUS r;\n\tLARGE_INTEGER wait;\n\n\t//DbgPrint(\"debugger_waitForDebugEvent with timeout of %d\\n\",timeout);\n\n\t//-10000000LL=1 second\n\t//-10000LL should be 1 millisecond\n\t//-10000LL\n\twait.QuadPart=-10000LL * timeout;\n\n\tif (timeout==0xffffffff) //infinite wait\n\t  r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, NULL);\n\telse\n\t  r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, &wait);\n\n\tif (r==STATUS_SUCCESS)\n\t\treturn r;\n\telse\n\t\treturn STATUS_UNSUCCESSFUL;\t\n}\n\nNTSTATUS debugger_continueDebugEvent(BOOL handled)\n/*\nOnly call this by one thread only, and only when there's actually a debug eevnt in progress\n*/\n{\n\t//DbgPrint(\"debugger_continueDebugEvent\\n\");\n\t\n\tDebuggerState.handledlastevent=handled;\n\tKeSetEvent(&debugger_event_WaitForContinue, 0,FALSE);\n\n\treturn STATUS_SUCCESS;\n}\n\nUINT_PTR *debugger_getLastStackPointer(void)\n{\n\t\n\treturn DebuggerState.LastStackPointer;\n}\n\n\nNTSTATUS debugger_getDebuggerState(PDebugStackState state)\n{\n\t//DbgPrint(\"debugger_getDebuggerState\\n\");\n\tstate->threadid=(UINT64)DebuggerState.LastThreadID;\n\tstate->causedbydbvm = (UINT64)DebuggerState.CausedByDBVM;\n\tif (DebuggerState.LastStackPointer)\n\t{\n\t\tstate->rflags=(UINT_PTR)DebuggerState.LastStackPointer[si_eflags];\n\t\tstate->rax=DebuggerState.LastStackPointer[si_eax];\n\t\tstate->rbx=DebuggerState.LastStackPointer[si_ebx];\n\t\tstate->rcx=DebuggerState.LastStackPointer[si_ecx];\n\t\tstate->rdx=DebuggerState.LastStackPointer[si_edx];\n\t\tstate->rsi=DebuggerState.LastStackPointer[si_esi];\n\t\tstate->rdi=DebuggerState.LastStackPointer[si_edi];\n\t\tstate->rbp=DebuggerState.LastStackPointer[si_ebp];\n\n\t\t\n\n\t#ifdef AMD64\n\t\t//fill in the extra registers\n\t\tstate->r8=DebuggerState.LastStackPointer[si_r8];\n\t\tstate->r9=DebuggerState.LastStackPointer[si_r9];\n\t\tstate->r10=DebuggerState.LastStackPointer[si_r10];\n\t\tstate->r11=DebuggerState.LastStackPointer[si_r11];\n\t\tstate->r12=DebuggerState.LastStackPointer[si_r12];\n\t\tstate->r13=DebuggerState.LastStackPointer[si_r13];\n\t\tstate->r14=DebuggerState.LastStackPointer[si_r14];\n\t\tstate->r15=DebuggerState.LastStackPointer[si_r15];\t\n\t\tmemcpy(state->fxstate, (void *)&DebuggerState.LastStackPointer[si_xmm], 512);\n\t#endif\t\t\n\t\t\n\t\t\n\n\n\t\t//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow\n\t\tif ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment\n\t\t{\n\t\t\t//priv level change, so the stack info was pushed as well\n\t\t\tstate->rsp=DebuggerState.LastStackPointer[si_esp]; \n\t\t\tstate->ss=DebuggerState.LastStackPointer[si_ss];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//kernelmode stack, yeah, it's really useless here since changing it here only means certain doom, but hey...\n\t\t\tstate->rsp=(UINT_PTR)(DebuggerState.LastStackPointer)-4;\n\t\t\tstate->ss=getSS();; //unchangeble by the user\n\t\t}\n\n\t\t\n\t\tstate->rip=DebuggerState.LastStackPointer[si_eip];\n\t\tstate->cs=DebuggerState.LastStackPointer[si_cs];\n\t\tstate->ds=DebuggerState.LastStackPointer[si_ds];\n\t\tstate->es=DebuggerState.LastStackPointer[si_es];\n\t#ifdef AMD64\n\t\tstate->fs=0;\n\t\tstate->gs=0;\n\t#else\n\t\tstate->fs=DebuggerState.LastStackPointer[si_fs];\n\t\tstate->gs=DebuggerState.LastStackPointer[si_gs];\n\t#endif\n\n\t\tstate->dr0=DebuggerState.LastRealDebugRegisters[0];\n\t\tstate->dr1=DebuggerState.LastRealDebugRegisters[1];\n\t\tstate->dr2=DebuggerState.LastRealDebugRegisters[2];\n\t\tstate->dr3=DebuggerState.LastRealDebugRegisters[3];\n\t\tstate->dr6=DebuggerState.LastRealDebugRegisters[4];\n\t\tstate->dr7=DebuggerState.LastRealDebugRegisters[5];\n\n\t\t /*if (DebuggerState.storeLBR)\n\t\t{\n\t\t\t//DbgPrint(\"Copying the LBR stack to usermode\\n\");\n\t\t\t//DbgPrint(\"storeLBR_max=%d\\n\", DebuggerState.storeLBR_max);\n\n\t\t\n\t\t\tfor (state->LBR_Count=0; state->LBR_Count<DebuggerState.storeLBR_max; state->LBR_Count++ )\n\t\t\t{\n\t\t\t\t//DbgPrint(\"DebuggerState.LastLBRStack[%d]=%x\\n\", state->LBR_Count, DebuggerState.LastLBRStack[state->LBR_Count]);\n\t\t\t\tstate->LBR[state->LBR_Count]=DebuggerState.LastLBRStack[state->LBR_Count];\n\t\t\t\tif (state->LBR[state->LBR_Count]==0) //no need to copy once a 0 has been reached\n\t\t\t\t\tbreak;\t\t\t\t\n\t\t\t}\n\t\t}\n\t\telse*/\n\t\t\tstate->LBR_Count=0;\n\n\n\t\treturn STATUS_SUCCESS;\n\t}\n\telse\n\t{\n\t\t//DbgPrint(\"debugger_getDebuggerState was called while DebuggerState.LastStackPointer was still NULL\");\n\t\treturn STATUS_UNSUCCESSFUL;\n\t}\n}\n\nNTSTATUS debugger_setDebuggerState(PDebugStackState state)\n{\n\tif (DebuggerState.LastStackPointer)\n\t{\n\t\tDebuggerState.LastStackPointer[si_eflags]=(UINT_PTR)state->rflags;\n\n\t\t//DbgPrint(\"have set eflags to %x\\n\",DebuggerState.LastStackPointer[si_eflags]);\n\n\n\t\tDebuggerState.LastStackPointer[si_eax]=(UINT_PTR)state->rax;\n\t\tDebuggerState.LastStackPointer[si_ebx]=(UINT_PTR)state->rbx;\n\t\tDebuggerState.LastStackPointer[si_ecx]=(UINT_PTR)state->rcx;\n\t\tDebuggerState.LastStackPointer[si_edx]=(UINT_PTR)state->rdx;\n\t\t\n\t\tDebuggerState.LastStackPointer[si_esi]=(UINT_PTR)state->rsi;\n\t\tDebuggerState.LastStackPointer[si_edi]=(UINT_PTR)state->rdi;\n\t\t\n\t\tDebuggerState.LastStackPointer[si_ebp]=(UINT_PTR)state->rbp;\n\n\t\t//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow\n\t\tif ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment\n\t\t{\n\t\t\t//priv level change, so the stack info was pushed as well\n\t\t\tDebuggerState.LastStackPointer[si_esp]=(UINT_PTR)state->rsp;\n\t\t\t//don't mess with ss\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//no change in kernelmode allowed\t\t\n\t\t}\n\n\t\t\n\t\tDebuggerState.LastStackPointer[si_eip]=(UINT_PTR)state->rip;\n\t\tDebuggerState.LastStackPointer[si_cs]=(UINT_PTR)state->cs;\n\t\tDebuggerState.LastStackPointer[si_ds]=(UINT_PTR)state->ds;\n\t\tDebuggerState.LastStackPointer[si_es]=(UINT_PTR)state->es;\n\t#ifndef AMD64\n\t\tDebuggerState.LastStackPointer[si_fs]=(UINT_PTR)state->fs;\n\t\tDebuggerState.LastStackPointer[si_gs]=(UINT_PTR)state->gs;\n\t#else //don't touch fs or gs in 64-bit\n\t\tDebuggerState.LastStackPointer[si_r8]=(UINT_PTR)state->r8;\n\t\tDebuggerState.LastStackPointer[si_r9]=(UINT_PTR)state->r9;\n\t\tDebuggerState.LastStackPointer[si_r10]=(UINT_PTR)state->r10;\n\t\tDebuggerState.LastStackPointer[si_r11]=(UINT_PTR)state->r11;\n\t\tDebuggerState.LastStackPointer[si_r12]=(UINT_PTR)state->r12;\n\t\tDebuggerState.LastStackPointer[si_r13]=(UINT_PTR)state->r13;\n\t\tDebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14;\n\t\tDebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15;\n\t\tmemcpy((void *)&DebuggerState.LastStackPointer[si_xmm], state->fxstate, 512);\n\t#endif\n\t\t\n\n\n\t\tif (!DebuggerState.globalDebug)\n\t\t{\n\t\t\t//no idea why someone would want to use this method, but it's in (for NON globaldebug only)\n\n\t\t\t//updating this array too just so the user can see it got executed. (it eases their state of mind...)\n\t\t\tDebuggerState.LastRealDebugRegisters[0]=(UINT_PTR)state->dr0; \n\t\t\tDebuggerState.LastRealDebugRegisters[1]=(UINT_PTR)state->dr1;\n\t\t\tDebuggerState.LastRealDebugRegisters[2]=(UINT_PTR)state->dr2;\n\t\t\tDebuggerState.LastRealDebugRegisters[3]=(UINT_PTR)state->dr3;\n\t\t\tDebuggerState.LastRealDebugRegisters[4]=(UINT_PTR)state->dr6;\n\t\t\tDebuggerState.LastRealDebugRegisters[5]=(UINT_PTR)state->dr7;\n\n\t\t\t//no setting of the DebugRegs here\n\n\t\t}\n\t}\n\telse\n\t{\n\t\t//DbgPrint(\"debugger_setDebuggerState was called while DebuggerState.LastStackPointer was still NULL\");\n\t\treturn STATUS_UNSUCCESSFUL;\n\t}\n\n\treturn STATUS_SUCCESS;\n}\n\nint breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs, UINT_PTR *LBR_Stack, int causedbyDBVM)\n//Notice: This routine is called when interrupts are enabled and the GD bit has been set if globaL DEBUGGING HAS BEEN USED\n//Interrupts are enabled and should be at passive level, so taskswitching is possible\n{\n\tNTSTATUS r=STATUS_UNSUCCESSFUL;\n\tint handled=0; //0 means let the OS handle it\n\tLARGE_INTEGER timeout;\n\ttimeout.QuadPart=-100000;\n\t\n\t\n\t\n\t//DbgPrint(\"breakpointHandler for kernel breakpoints\\n\");\n\n#ifdef AMD64\n\t//DbgPrint(\"cs=%x ss=%x ds=%x es=%x fs=%x gs=%x\\n\",getCS(), getSS(), getDS(), getES(), getFS(), getGS());\n\n\t//DbgPrint(\"fsbase=%llx gsbase=%llx gskernel=%llx\\n\", readMSR(0xc0000100), readMSR(0xc0000101), readMSR(0xc0000102));\n\n\t//DbgPrint(\"rbp=%llx\\n\", getRBP());\n\n\t//DbgPrint(\"gs:188=%llx\\n\", __readgsqword(0x188));\n\t//DbgPrint(\"causedbyDBVM=%d\\n\", causedbyDBVM);\n#endif\n\t\n\tif (KeGetCurrentIrql()==0)\n\t{\n\t\t//crititical section here\n\t\tif ((stackpointer[si_cs] & 3)==0)\n\t\t{\n\t\t\t//DbgPrint(\"Going to wait in a kernelmode routine\\n\");\n\t\t}\n\n\t\n\t\t//block other threads from breaking until this one has been handled\n\t\twhile (r != STATUS_SUCCESS)\n\t\t{\n\t\t\tr=KeWaitForSingleObject(&debugger_event_CanBreak,Executive, KernelMode, FALSE, NULL);\n\t\t\t//check r and handle specific events\n\n\t\t\t//DbgPrint(\"Woke up. r=%x\\n\",r);\n\t\t\t\t\n\t\t}\n\n\t\tif ((stackpointer[si_cs] & 3)==0)\n\t\t{\n\t\t\t//DbgPrint(\"Woke up in a kernelmode routine\\n\");\n\t\t}\n\t\t\n\n\t\t//We're here, let's notify the usermode debugger of our situation\n\t\t//first store the stackpointer so it can be manipulated externally\n\t\tDebuggerState.LastStackPointer=stackpointer;\n\t\tDebuggerState.LastRealDebugRegisters=currentdebugregs;\t\t\n\t\t/*DebuggerState.LastLBRStack=LBR_Stack;*/\n\t\tDebuggerState.LastThreadID=PsGetCurrentThreadId();\n\t\tDebuggerState.CausedByDBVM = causedbyDBVM;\n\t\t\n\n\n \n\n\n\t\t//notify usermode app that this thread has halted due to a debug event\n\t\t\n\t\tKeSetEvent(&debugger_event_WaitForDebugEvent,0,FALSE);\n\n\n\t\t//wait for event from usermode that debgu event has been handled\n\t\t//KeWaitForSingleObject();\n\t\t//continue with state\n\n\t\twhile (1)\n\t\t{\n\n\n\t\t\t//LARGE_INTEGER wt;\n\t\t\tNTSTATUS s=STATUS_UNSUCCESSFUL;\n\t\t\t\n\t\t\t//wt.QuadPart=-10000000LL; \n\t\t\t//s=KeDelayExecutionThread(KernelMode, FALSE, &wt);\n\n\t\t\t//DbgPrint(\"Waiting...\\n\");\n\n\n\t\t\twhile (s != STATUS_SUCCESS)\n\t\t\t{\n\t\t\t\ts=KeWaitForSingleObject(&debugger_event_WaitForContinue, Executive, KernelMode, FALSE, NULL);\n\t\t\t\t//DbgPrint(\"KeWaitForSingleObject=%x\\n\",s);\t\t\n\t\t\t}\n\n\t\t\t\n\n\t\t\tif (s==STATUS_SUCCESS)\n\t\t\t{\n\t\t\t\tif (DebuggerState.handledlastevent)\n\t\t\t\t{\n\t\t\t\t\t//DbgPrint(\"handledlastevent=TRUE\");\n\t\t\t\t\thandled=1;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\thandled=0;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\t\n\t\t}\n\n\n\t\tDebuggerState.LastStackPointer=NULL; //NULL the stackpointer so routines know it should not be called\n\n\t\t//i'm done, let other threads catch it\n\t\tKeSetEvent(&debugger_event_CanBreak, 0, FALSE);\n\n\t\t//DbgPrint(\"Returning after a wait. handled=%d and eflags=%x\\n\",handled, stackpointer[si_eflags]);\n\t\tif ((stackpointer[si_cs] & 3)==0) //check rpl of cs\n\t\t{\n\t\t\t//DbgPrint(\"and in kernelmode\\n\");\n\t\t}\n\n\t\treturn handled;\n\t}\n\telse\n\t{\n\t\t//DbgPrint(\"Breakpoint wasn't at passive level. Screw this, i'm not going to break here\\n\");\n\t\t\n\t\treturn 1;\n\t}\n\n}\n\nint interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)\n{\n\tHANDLE CurrentProcessID=PsGetCurrentProcessId();\t\n\tUINT_PTR originaldr6=currentdebugregs[4];\n\tDebugReg6 _dr6=*(DebugReg6 *)&currentdebugregs[4];\n\n\tUINT_PTR LBR_Stack[16]; //max 16\n//\tDebugReg7 _dr7=*(DebugReg7 *)&currentdebugregs[5];\n\n\tint causedbyDBVM = vmxusable && vmx_causedCurrentDebugBreak();\n\n\t/*\n\tif (cpu_familyID==0x6)\n\t{\n\t\tif (DebuggerState.storeLBR)\n\t\t{\n\t\t\t//fetch the lbr stack\n\t\t\tint MSR_LASTBRANCH_TOS=0x1c9;\n\t\t\tint MSR_LASTBRANCH_0=0x40;\n\n\t\t\tint i;\n\t\t\tint count;\n\n\t\t\t\n\n\t\t\ti=(int)__readmsr(MSR_LASTBRANCH_TOS);\n\t\t\tcount=0;\n\t\t\twhile (count<DebuggerState.storeLBR_max)\n\t\t\t{\n\t\t\t\tUINT64 x;\n\t\t\t\tx=__readmsr(MSR_LASTBRANCH_0+i);\n\t\t\t\tLBR_Stack[count]=(UINT_PTR)x;\n\t\t\t\t__writemsr(MSR_LASTBRANCH_0+i,0); //it has been read out, so can be erased now\n\n\t\t\t\tcount++;\n\t\t\t\ti++;\n\t\t\t\ti=i % DebuggerState.storeLBR_max;\t\t\t\t\n\t\t\t}\n\t\t}\n\t}\n\t*/\n\t\n\n\t//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]));\n\t\n\t//check if this break should be handled or not\n\t\n\tif (DebuggerState.globalDebug)\n\t{\n\t\t//DbgPrint(\"DebuggerState.globalDebug=TRUE\\n\");\n\t\t//global debugging is being used\n\t\tif (_dr6.BD)\n\t\t{\n\t\t\t_dr6.BD = 0;\n\t\t\tdebugger_dr6_setValue(*(UINT_PTR *)&_dr6);\n\n\t\t    //The debug registers are being accessed, emulate it with DebuggerState.FakedDebugRegisterState[cpunr()].DRx\n\n\t\t\tif ((stackpointer[si_cs] & 3)==0)\n\t\t\t{\n\t\t\t\tint instructionPointer;\n\t#ifdef AMD64\n\t\t\t\tint prefixpointer;\n\t#endif\n\t\t\t\tint currentcpunr = cpunr();\n\t\t\t\tint debugregister;\n\t\t\t\tint generalpurposeregister;\n\t\t\t\tunsigned char *instruction = (unsigned char *)stackpointer[si_eip];\n\n\t\t\t\t//unset this flag in DR6\n\t\t\t\t_dr6.BD = 0;\n\t\t\t\tdebugger_dr6_setValue(*(UINT_PTR *)&_dr6);\n\n\t\t\t\tif (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)\n\t\t\t\t{\n\t\t\t\t\t((EFLAGS *)&stackpointer[si_eflags])->RF = 1; //repeat this instruction and don't break\n\t\t\t\t\treturn 2;\n\t\t\t\t}\n\n\n\t\t\t\t//DbgPrint(\"handler: Setting fake dr6 to %x\\n\",*(UINT_PTR *)&_dr6);\n\n\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR6 = *(UINT_PTR *)&_dr6;\n\n\t\t\t\tfor (instructionPointer = 0; instruction[instructionPointer] != 0x0f; instructionPointer++); //find the start of the instruction, skipping prefixes etc...\n\n\t\t\t\t//we now have the start of the instruction.\n\t\t\t\t//Find out which instruction it is, and which register is used\n\t\t\t\tdebugregister = (instruction[instructionPointer + 2] >> 3) & 7;\n\t\t\t\tgeneralpurposeregister = instruction[instructionPointer + 2] & 7;\n\n\t#ifdef AMD64\n\t\t\t\tfor (prefixpointer = 0; prefixpointer < instructionPointer; prefixpointer++)\n\t\t\t\t{\n\t\t\t\t\t//check for a REX.B prefix  (0x40  + 0x1 : 0x41)\n\t\t\t\t\tif ((instruction[prefixpointer] & 0x41) == 0x41)\n\t\t\t\t\t{\n\t\t\t\t\t\t//rex.b prefix is used, r8 to r15 are being accessed\n\t\t\t\t\t\tgeneralpurposeregister += 8;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t#endif\n\n\t\t\t\t//DbgPrint(\"debugregister=%d, generalpurposeregister=%d\\n\",debugregister,generalpurposeregister); \n\n\t\t\t\tif (instruction[instructionPointer + 1] == 0x21)\n\t\t\t\t{\n\t\t\t\t\tUINT_PTR drvalue = 0;\n\t\t\t\t\t//DbgPrint(\"read opperation\\n\");\n\t\t\t\t\t//21=read\n\t\t\t\t\tswitch (debugregister)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0:\n\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;\n\t\t\t\t\t\t//DbgPrint(\"Reading DR0 (returning %x real %x)\\n\", drvalue, currentdebugregs[0]); \n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 4:\n\t\t\t\t\tcase 6:\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;\n\t\t\t\t\t\t//DbgPrint(\"reading dr6 value:%x\\n\",drvalue);\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 5:\n\t\t\t\t\tcase 7:\n\t\t\t\t\t\tdrvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t//DbgPrint(\"Invalid debugregister\\n\");\n\t\t\t\t\t\tdrvalue = 0;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (generalpurposeregister)\n\t\t\t\t\t{\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\tstackpointer[si_eax] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tstackpointer[si_ecx] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tstackpointer[si_edx] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\tstackpointer[si_ebx] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 4:\n\t\t\t\t\t\tif ((stackpointer[si_cs] & 3) == 3)  //usermode dr access ?\n\t\t\t\t\t\t\tstackpointer[si_esp] = drvalue;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tstackpointer[si_stack_esp] = drvalue;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 5:\n\t\t\t\t\t\tstackpointer[si_ebp] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 6:\n\t\t\t\t\t\tstackpointer[si_esi] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 7:\n\t\t\t\t\t\tstackpointer[si_edi] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t#ifdef AMD64\n\t\t\t\t\tcase 8:\n\t\t\t\t\t\tstackpointer[si_r8] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 9:\n\t\t\t\t\t\tstackpointer[si_r9] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 10:\n\t\t\t\t\t\tstackpointer[si_r10] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 11:\n\t\t\t\t\t\tstackpointer[si_r11] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 12:\n\t\t\t\t\t\tstackpointer[si_r12] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 13:\n\t\t\t\t\t\tstackpointer[si_r13] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 14:\n\t\t\t\t\t\tstackpointer[si_r14] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase 15:\n\t\t\t\t\t\tstackpointer[si_r15] = drvalue;\n\t\t\t\t\t\tbreak;\n\n\n\t#endif\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tif (instruction[instructionPointer + 1] == 0x23)\n\t\t\t\t\t{\n\t\t\t\t\t\t//23=write\n\t\t\t\t\t\tUINT_PTR gpvalue = 0;\n\t\t\t\t\t\t//DbgPrint(\"Write operation\\n\");\n\t\t\t\t\t\tswitch (generalpurposeregister)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_eax];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_ecx];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_edx];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_ebx];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tif ((stackpointer[si_cs] & 3) == 3)\n\t\t\t\t\t\t\t\tgpvalue = stackpointer[si_esp];\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_ebp];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_esi];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_edi];\n\t\t\t\t\t\t\tbreak;\n\t#ifdef AMD64\n\t\t\t\t\t\tcase 8:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r8];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r9];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 10:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r10];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 11:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r11];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 12:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r12];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 13:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r13];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 14:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r14];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 15:\n\t\t\t\t\t\t\tgpvalue = stackpointer[si_r15];\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t//DbgPrint(\"Invalid register value\\n\");\n\t\t\t\t\t\t\tbreak;\n\t#endif\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t//gpvalue now contains the value to set the debug register\n\t\t\t\t\t\tswitch (debugregister)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t//DbgPrint(\"Writing DR0. Original value=%x new value=%x\\n\", currentdebugregs[0], gpvalue);\n\t\t\t\t\t\t\tdebugger_dr0_setValue(gpvalue);\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR0 = debugger_dr0_getValue();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tdebugger_dr1_setValue(gpvalue);\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR1 = debugger_dr1_getValue();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tdebugger_dr2_setValue(gpvalue);\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR2 = debugger_dr2_getValue();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tdebugger_dr3_setValue(gpvalue);\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR3 = debugger_dr3_getValue();\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t//DbgPrint(\"Setting dr6 to %x (was %x)\\n\", gpvalue, DebuggerState.FakedDebugRegisterState[cpunr()].DR6);\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t_dr6 = *(DebugReg6 *)&gpvalue;\n\n\t\t\t\t\t\t\t//if (_dr6.BD) DbgPrint(\"Some code wants to set the BD flag to 1\\n\");\n\t\t\t\t\t\t\t\n\n\n\n\t\t\t\t\t\t\tdebugger_dr6_setValue(gpvalue);\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();\n\n\t\t\t\t\t\t\tif (_dr6.BD)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t_dr6.BD = 0;\n\t\t\t\t\t\t\t\tdebugger_dr6_setValue(gpvalue);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\t//make sure it doesn't set the GD flag here\n\t\t\t\t\t\t\t//DbgPrint(\"DR7 write\\n\");\n\n\t\t\t\t\t\t\t//if (generalpurposeregister == 15)\n\t\t\t\t\t\t\t//{\n\t\t\t\t\t\t\t//\twhile (1); //patchguard\n\t\t\t\t\t\t\t//}\n\n\t\t\t\t\t\t\t//if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)\n\t\t\t\t\t\t\t//{\n\t\t\t\t\t\t\t\t//\tDbgPrint(\"Was in epilogue\\n\");\n\t\t\t\t\t\t\t//}\n\n\t\t\t\t\t\t\t//check for invalid bits and raise a GPF if invalid\n\n\n\t\t\t\t\t\t\tgpvalue = (gpvalue | 0x400) & (~(1 << 13)); //unset the GD value\n\n\t\t\t\t\t\t\t//gpvalue=0xf0401;\n\t\t\t\t\t\t\tdebugger_dr7_setValueDword(gpvalue);\n\n\t\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR7 = debugger_dr7_getValueDword();\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//DbgPrint(\"Some unknown instruction accessed the debug registers?\\n\");\n\t\t\t\t\t\t//if (CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)\n\t\t\t\t\t\t//\tDbgPrint(\"Happened inside the target process\\n\");\n\n\t\t\t\t\t\t//DbgPrint(\"interrupt1_handler dr6=%x (original=%x) dr7=%d\\n\",_dr6, originaldr6, _dr7);\n\t\t\t\t\t\t//DbgPrint(\"eip=%x\\n\",stackpointer[si_eip]);\n\t\t\t\t\t}\n\n\t\t\t\t//adjust eip to after this instruction\n\t\t\t\tstackpointer[si_eip] += instructionPointer + 3; //0f xx /r\n\n\t\t\t\treturn 1; //don't tell windows about it\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//DbgPrint(\"DR6.BD == 1 in USERMODE! WTF\\n\");\n\t\t\t\t_dr6.BD = 0;\n\t\t\t\tdebugger_dr6_setValue(*(UINT_PTR *)&_dr6);\n\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\tif (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\n\t{\n\t\n\t\tif ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))\n\t\t{\n\t\t\t((PEFLAGS)&stackpointer[si_eflags])->TF = 1;\n\t\t\t((PEFLAGS)&stackpointer[si_eflags])->RF = 1;\n\t\t\tdebugger_dr6_setValue(0xffff0ff0);\n\t\t\treturn 1;\n\t\t}\n\n\t\tDebuggerState.isSteppingTillClear = FALSE;\t\n\t}\n\n\t\n\tif (DebuggerState.isDebugging)\n\t{\n\t\t//DbgPrint(\"DebuggerState.isDebugging\\n\");\n\t\t//check if this should break\n\t\tif (CurrentProcessID == (HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)\n\t\t{\n\t\t\tUINT_PTR originaldebugregs[6];\n\t\t\tUINT64 oldDR7 = getDR7();\n\n\n\t\t\tif ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))\n\t\t\t{\n\t\t\t\t//There's no way to display the state to the usermode part of CE\n\t\t\t\t//DbgPrint(\"int1 at unstoppable location\");\n\t\t\t\tif (!KernelCodeStepping)\n\t\t\t\t{\n\t\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->TF = 0; //just give up stepping\n\t\t\t\t//\tDbgPrint(\"Quitting this\");\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//\tDbgPrint(\"Stepping until valid\\n\");\n\t\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->TF = 1; //keep going until a valid state\n\t\t\t\t\tDebuggerState.isSteppingTillClear = TRUE; //Just in case a taskswitch happens right after enabling passive level with interrupts\n\t\t\t\t}\n\n\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->RF = 1;\n\t\t\t\tdebugger_dr6_setValue(0xffff0ff0);\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tDebuggerState.isSteppingTillClear = FALSE;\n\n\n\n\t\t\t//DbgPrint(\"CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID\\n\");\n\n\t\t\tif (DebuggerState.globalDebug)\n\t\t\t{\n\t\t\t\toriginaldebugregs[0] = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;\n\t\t\t\toriginaldebugregs[1] = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;\n\t\t\t\toriginaldebugregs[2] = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;\n\t\t\t\toriginaldebugregs[3] = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;\n\t\t\t\toriginaldebugregs[4] = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;\n\t\t\t\toriginaldebugregs[5] = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;\n\t\t\t}\n\n\t\t\t//DbgPrint(\"BP in target process\\n\");\n\n\t\t\t//no extra checks if it's caused by the debugger or not. That is now done in the usermode part\n\t\t\t//if (*(PEFLAGS)(&stackpointer[si_eflags]).IF)\t\n/*\n\t\t\tif (((PEFLAGS)&stackpointer[si_eflags])->IF==0)\n\t\t\t{\n\t\t\t\t//DbgPrint(\"Breakpoint while interrupts are disabled: %x\\n\",stackpointer[si_eip]);\n\t\t\t\t//An breakpoint happened while IF was 0. Step through the code untill IF is 1\n\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->RF=1;\n\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->TF=1; //keep going until IF=1\n\t\t\t\tDbgPrint(\"IF==0\\n\");\n\t\t\t\treturn 1; //don't handle it but also don't tell windows\n\t\t\t}*/\n\n\t\t\t//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...\n\n\n\n\t\t\tif (DebuggerState.globalDebug)\n\t\t\t{\n\t\t\t\t//enable the GD flag for taskswitches that will occur as soon as interrupts are enabled\n\t\t\t\t//this also means: DO NOT EDIT THE DEBUG REGISTERS IN GLOBAL DEBUG MODE at this point. Only in the epilogue\n\n\t\t\t\tif (!DebuggerState.stoppingTheDebugger) //This is set when the driver is unloading. So do NOT set it back then\n\t\t\t\t\tdebugger_dr7_setGD(DebuggerState.globalDebug);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//unset ALL debug registers before enabling taskswitching. Just re-enable it when back when interrupts are disabled again\n\t\t\t\tdebugger_dr7_setValueDword(0x400);\n\t\t\t\tdebugger_dr0_setValue(0);\n\t\t\t\tdebugger_dr1_setValue(0);\n\t\t\t\tdebugger_dr2_setValue(0);\n\t\t\t\tdebugger_dr3_setValue(0);\n\t\t\t\tdebugger_dr6_setValue(0xffff0ff0);\n\t\t\t}\n\n\t\t\t//start the windows taskswitching mode\n\n\t\t\t//if (1) return 1;\n\n\t\t\t//save the state of the thread to a place that won't get overwritten\n\n\t\t\t//todo: breaks 32-bit\n\t\t\t//int i;\n\t\t\tBOOL NeedsToGrowStackList = FALSE;\n\t\t\tPSavedStack SelectedStackEntry = NULL;\n\t\t\t/*\n\t\t\tcsEnter(&StacksCS);\n\t\t\tfor (i = 0; i < StackCount; i++)\n\t\t\t{\n\t\t\t\tif (Stacks[i]->inuse == FALSE)\n\t\t\t\t{\n\t\t\t\t\tSelectedStackEntry = Stacks[i];\n\t\t\t\t\tSelectedStackEntry->inuse = TRUE;\n\t\t\t\t\tRtlCopyMemory(SelectedStackEntry->stacksnapshot, stackpointer, 600 * 8);\n\n\t\t\t\t\tif (i > StackCount / 2)\n\t\t\t\t\t\tNeedsToGrowStackList = TRUE;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcsLeave(&StacksCS);\n\n\t\t\tenableInterrupts();\n\n\t\t\t//grow stack if needed\n\n\t\t\tif (NeedsToGrowStackList)\n\t\t\t\tdebugger_growstack();\n\t\t*/\n\n\t\t\t{\n\t\t\t\tint rs=1;\t\n\n\t\t\t\t//DbgPrint(\"calling breakpointHandler_kernel\\n\");\n\n\t\t\t\tif (SelectedStackEntry == NULL) //fuck\n\t\t\t\t\trs = breakpointHandler_kernel(stackpointer, currentdebugregs, LBR_Stack, causedbyDBVM);\n\t\t\t\telse\n\t\t\t\t\trs = breakpointHandler_kernel((UINT_PTR *)(SelectedStackEntry->stacksnapshot), currentdebugregs, LBR_Stack, causedbyDBVM);\n\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t//DbgPrint(\"After handler\\n\");\n/*\n\t\t\t\tif (SelectedStackEntry)  //restore the stack\n\t\t\t\t{\n\t\t\t\t\tRtlCopyMemory(stackpointer, SelectedStackEntry->stacksnapshot, 600 * 8);\n\t\t\t\t\tSelectedStackEntry->inuse = FALSE;\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\t\n\t\t\t\t//DbgPrint(\"rs=%d\\n\",rs);\n\n\n\t\t\t\tdisableInterrupts();\n\n\t\t\t\t//restore the \n\n\n\t\t\t\t//we might be on a different CPU now\n\t\t\t\tif (DebuggerState.globalDebug)\n\t\t\t\t{\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR0=originaldebugregs[0];\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR1=originaldebugregs[1];\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR2=originaldebugregs[2];\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR3=originaldebugregs[3];\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR6=originaldebugregs[4];\n\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].DR7=originaldebugregs[5];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t\n\t\t\t\t\t/*if (getDR7() != oldDR7)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Something changed DR7. old=%llx new=%llx\\n\",oldDR7, getDR7());\n\t\t\t\t\t}*/\n\n\t\t\t\t\t\n\t\t\t\t\t//set the debugregisters to what they where set to before taskswitching was enable\n\t\t\t\t\t//with global debug this is done elsewhere\n\t\t\t\t\tdebugger_dr0_setValue(currentdebugregs[0]);\n\t\t\t\t\tdebugger_dr1_setValue(currentdebugregs[1]);\n\t\t\t\t\tdebugger_dr2_setValue(currentdebugregs[2]);\n\t\t\t\t\tdebugger_dr3_setValue(currentdebugregs[3]);\n\t\t\t\t\tdebugger_dr6_setValue(currentdebugregs[4]);\n\n\t\t\t\t\tif ((currentdebugregs[5] >> 13) & 1)\n\t\t\t\t\t{\n\t\t\t\t\t//\tDbgPrint(\"WTF? GD is 1 in currentdebugregs[5]: %llx\\n\", currentdebugregs[5]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tdebugger_dr7_setValue(*(DebugReg7 *)&currentdebugregs[5]);\t\n\t\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\treturn rs;\n\t\t\t}\n\t\t}\n\t\telse \n\t\t{\n\t\t\t//DbgPrint(\"Not the debugged process (%x != %x)\\n\",CurrentProcessID,DebuggerState.debuggedProcessID );\n\t\t\t//check if this break is due to a breakpoint ce has set. (during global debug threadsurfing))\n\t\t\t//do that by checking if the breakpoint condition exists in the FAKE dr7 registers\n\t\t\t//if so, let windows handle it, if not, it is caused by ce, which then means, skip (so execute normally)\n\n\t\t\tif (DebuggerState.globalDebug)\n\t\t\t{\t\t\t\n\t\t\t\tDebugReg6 dr6=debugger_dr6_getValue();\n\t\t\t\tDebugReg7 dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;\n\n\t\t\t\t//real dr6\t\t//fake dr7\n\t\t\t\tif ((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\n\t\t\t\tif ((dr6.B1) && (!(dr7.L1 || dr7.G1))) { /*DbgPrint(\"setting RF because of B1\\n\");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //\t\t...\t\tDR1\t\t...\n\t\t\t\tif ((dr6.B2) && (!(dr7.L2 || dr7.G2))) { /*DbgPrint(\"setting RF because of B2\\n\");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //\t\t...\t\tDR2\t\t...\n\t\t\t\tif ((dr6.B3) && (!(dr7.L3 || dr7.G3))) { /*DbgPrint(\"setting RF because of B3\\n\");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; }  //\t\t...\t\tDR3\t\t...\n\t\t\t}\n\n\t\t\tif (causedbyDBVM)\n\t\t\t\treturn 1; //correct PA, bad PID, ignore BP\n\n\t\t\tif (DebuggerState.isSteppingTillClear) //shouldn't happen often\n\t\t\t{\n\t\t\t\t//DbgPrint(\"That thing that shouldn\\'t happen often happened\\n\");\n\t\t\t\t((PEFLAGS)&stackpointer[si_eflags])->TF = 0;\n\n\t\t\t\tDebuggerState.isSteppingTillClear = 0;\n\t\t\t\treturn 1; //ignore\n\t\t\t}\n\n\t\t\t//DbgPrint(\"Returning unhandled. DR6=%x\", debugger_dr6_getValueDword());\n\t\t\t\n\t\t\treturn 0; //still here, so let windows handle it\n\n\t\t}\n\t}\n\telse\n\t\treturn 0; //Let windows handle it\n\n\t//get the current processid\n\t//is it being debugged\n\t//if yes, check if the breakpoint is something done by me\n\t//if no, exit\n\t\n}\n\nint interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-bit stackpointer\n{\n\tUINT_PTR before;//,after;\n\tUINT_PTR currentdebugregs[6]; //used for determining if the current bp is caused by the debugger or not\n\tint handled=0; //if 0 at return, the interupt will be passed down to the operating system\n\tQWORD naddress;\n\t//DbgPrint(\"interrupt1_centry cpunr=%d esp=%x\\n\",cpunr(), getRSP());\n\n\t//bsod crashfix, but also disables kernelmode stepping\n\tIDT idt;\n\tGetIDT(&idt);\n\n\tnaddress = idt.vector[1].wLowOffset + (idt.vector[1].wHighOffset << 16);\n#ifdef AMD64\n\tnaddress += ((UINT64)idt.vector[1].TopOffset << 32);\n#endif\n\tstackpointer[si_errorcode] = (UINT_PTR)naddress; //the errorcode is used as address to call the original function if needed\n\t\t\n\n\n\t/*\n\tif (Int1JumpBackLocation.eip != naddress) //no, just fucking no (patchguard will replace all inthandlers with invalid ones and then touch dr7)\t\n\t{\n\t\t//todo: the usual, but make sure not to use dbgprint or anything that could trigger a software int\n\t\tif (DebuggerState.globalDebug)\n\t\t{\n\t\t\tdebugger_dr7_setGD(DebuggerState.globalDebug);\n\t\t\tstackpointer[si_eip] += 4;\n\t\t\treturn 1;\n\t\t}\n\t}\n\t*/\n\n\n\n\n\n\n\tbefore=getRSP();\n\n\t//Fetch current debug registers\n\tcurrentdebugregs[0]=debugger_dr0_getValue();\n\tcurrentdebugregs[1]=debugger_dr1_getValue();\n\tcurrentdebugregs[2]=debugger_dr2_getValue();\n\tcurrentdebugregs[3]=debugger_dr3_getValue();\n\tcurrentdebugregs[4]=debugger_dr6_getValueDword();\n\tcurrentdebugregs[5]=debugger_dr7_getValueDword();\n\n\n\thandled=interrupt1_handler(stackpointer, currentdebugregs);\n\n\t//epilogue:\n\t//At the end when returning:\n\t\n\t\n\n\t//\n\t//--------------------------------------------------------------------------\n\t//--------------EPILOGUE (AFTER HAVING HANDLED THE BREAKPOINT)--------------\n\t//--------------------------------------------------------------------------\n\t//\n\t\n\t\n\tdisableInterrupts(); //just making sure..\t\n\n\n\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;\n\tdebugger_dr7_setGD(0); //make sure the GD bit is disabled (int1 within int1, oooh the fun..., and yes, THIS itself will cause one too)\n\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1; //just be sure...\n\n\n\t//if (inthook_isDBVMHook(1))\n\t//{\n\t\t//update the int1 return address, could have been changed\n\t\t\n\n\t\t\n\n\t\t//DbgPrint(\"This was a dbvm hook. Changing if the interrupt return address is still valid\\n\");\n\n\t//\tInt1JumpBackLocation.cs=idt.vector[1].wSelector;\n\t//\tnaddress=idt.vector[1].wLowOffset+(idt.vector[1].wHighOffset << 16);\n#ifdef AMD64\n\t//\tnaddress+=((UINT64)idt.vector[1].TopOffset << 32);\t\t\n#endif\n\t   \n\n\n\t//}\n\t\n\n\tif (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))\n\t{\n\t\t//set the breakpoint in this thread. \t\t\n        DebugReg6 dr6=debugger_dr6_getValue();\n\t\t//DebugReg7 dr7=debugger_dr7_getValue();\n\n\t\tDebugReg6 _dr6=*(DebugReg6 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR6;\n        DebugReg7 _dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;\n\t\tint debugregister=0, breakpoint=0;\n\t\t\n\n\n        //first clear the DR6 bits caused by the debugger\n\n\t\tif (!handled)\n\t\t{\n\t\t\t//it's going to get sent to windows\n\t\t\tif (dr6.BD && _dr7.GD) _dr6.BD=1; //should already have been done, but what the heck...\n\t\t\tif (dr6.B0 && (_dr7.L0 || _dr7.G0)) _dr6.B0=1;\n\t\t\tif (dr6.B1 && (_dr7.L1 || _dr7.G1)) _dr6.B1=1;\n\t\t\tif (dr6.B2 && (_dr7.L2 || _dr7.G2)) _dr6.B2=1;\n\t\t\tif (dr6.B3 && (_dr7.L3 || _dr7.G3)) _dr6.B3=1;\n\n\t\t\t_dr6.BS=dr6.BS;\n\t\t\t_dr6.BT=dr6.BT;\n\t\t\t//DbgPrint(\"epilogue: Setting fake dr6 to %x (fake=%x)\\n\",*(DWORD *)&dr6, *(DWORD *)&_dr6);\n\t\t}\n\t\t\n\n\t\tdebugger_dr6_setValue(0xffff0ff0);\n\n\t\t\n\t\t//set the debug registers of active breakpoints. Doesn't have to be in the specified order. Just find an unused debug registers\n\t\t//check DebuggerState.FakedDebugRegisterState[cpunumber].DR7 for unused breakpoints\n\n\t\t//set state to what the guest thinks it is\n\t\tdebugger_dr0_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR0);\n\t\tdebugger_dr1_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR1);\n\t\tdebugger_dr2_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR2);\n\t\tdebugger_dr3_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR3);\n\t\tdebugger_dr6_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR6);\n\n\t\t\n\t\t\n\t\tfor (breakpoint=0; breakpoint<4; breakpoint++)\n\t\t{\n\t\t\t\n\t\t\tif (DebuggerState.breakpoint[breakpoint].active)\n\t\t\t{\n\t\t\t\t\n\t\t\t\tint foundone=0;\n\t\t\t//\tDbgPrint(\"Want to set breakpoint %d\\n\",breakpoint);\n\t\t\t\n\t\t\t\t\n\n\t\t\t\t//find a usable debugregister\n\t\t\t\twhile ((debugregister<4) && (foundone==0))\t\t\t\t\n\t\t\t\t{\n\t\t\t\t\n\t\t\t\t\tif (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue==0)\n\t\t\t\t\t{\n\t\t\t\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;\n\t\t\t\t\t}\n\t\t\t\t\t\n\n\t\t\t\t\t//check if this debugregister is usable\n\t\t\t\t\tif (((DebuggerState.FakedDebugRegisterState[cpunr()].DR7 >> (debugregister*2)) & 3)==0)  //DR7.Gx and DR7.Lx are 0\n\t\t\t\t\t{\n\t\t\t\t\t  //  DbgPrint(\"debugregister %d is free to be used\\n\",debugregister);\n\t\t\t\t\t\tfoundone=1;\n\t\t\t\t\t\t\n\t\t\t\t\t\t//set address\n\t\t\t\t\t\tswitch (debugregister)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcase 0:\t\n\t\t\t\t\t\t\t\tdebugger_dr0_setValue(DebuggerState.breakpoint[breakpoint].address);\n\t\t\t\t\t\t\t\t_dr7.L0=1;\n\t\t\t\t\t\t\t\t_dr7.LEN0=DebuggerState.breakpoint[breakpoint].breakLength;\n\t\t\t\t\t\t\t\t_dr7.RW0=DebuggerState.breakpoint[breakpoint].breakType;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdebugger_dr1_setValue(DebuggerState.breakpoint[breakpoint].address);\n\t\t\t\t\t\t\t\t_dr7.L1=1;\n\t\t\t\t\t\t\t\t_dr7.LEN1=DebuggerState.breakpoint[breakpoint].breakLength;\n\t\t\t\t\t\t\t\t_dr7.RW1=DebuggerState.breakpoint[breakpoint].breakType;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tdebugger_dr2_setValue(DebuggerState.breakpoint[breakpoint].address);\n\t\t\t\t\t\t\t\t_dr7.L2=1;\n\t\t\t\t\t\t\t\t_dr7.LEN2=DebuggerState.breakpoint[breakpoint].breakLength;\n\t\t\t\t\t\t\t\t_dr7.RW2=DebuggerState.breakpoint[breakpoint].breakType;\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tdebugger_dr3_setValue(DebuggerState.breakpoint[breakpoint].address);\n\t\t\t\t\t\t\t\t_dr7.L3=1;\n\t\t\t\t\t\t\t\t_dr7.LEN3=DebuggerState.breakpoint[breakpoint].breakLength;\n\t\t\t\t\t\t\t\t_dr7.RW3=DebuggerState.breakpoint[breakpoint].breakType;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\n\t\t\t\t\t}\n\n\t\t\t\t\tdebugregister++;\n\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t}\n\t\t\n\n\t\tdebugger_dr7_setValue(_dr7);\n\n\t\t//DbgPrint(\"after:\\n\");\n\n\t\t//DbgPrint(\"after fake DR0=%x real DR0=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR0, debugger_dr0_getValue());\n\t\t//DbgPrint(\"after fake DR1=%x real DR1=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR1, debugger_dr1_getValue());\n\t\t//DbgPrint(\"after fake DR2=%x real DR2=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR2, debugger_dr2_getValue());\n\t\t//DbgPrint(\"after fake DR3=%x real DR3=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR3, debugger_dr3_getValue());\n\t\t//DbgPrint(\"after fake DR6=%x real DR6=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR6, debugger_dr6_getValueDword());\n\t\t//DbgPrint(\"after fake DR7=%x real DR7=%x\\n\",DebuggerState.FakedDebugRegisterState[currentcpunr].DR7, debugger_dr7_getValueDword());\n\n\t}\n\telse\n\t{\n\t\t//not global debug, just clear all flags and be done with it\n\t\tif (handled)\n\t\t\tdebugger_dr6_setValue(0xffff0ff0);\n\t\n\t}\n\n\tdisableInterrupts();\n\n\n\tif (handled == 2)\n\t{\n\t\t//DbgPrint(\"handled==2\\n\");\t\t\n\t\thandled = 1; //epilogue = 1 Dr handler\n\t}\n\telse\n\t{\t\t\n\t\t//not handled by the epilogue set DR0, so the actual epilogue\n\t\t//DbgPrint(\"handled==1\\n\");\n\t\t\n\t\tif (DebuggerState.globalDebug)\n\t\t{\n\t\t\tDebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=0;\n\n\t\t\tif (!DebuggerState.stoppingTheDebugger)\n\t\t\t\tdebugger_dr7_setGD(DebuggerState.globalDebug); //set it back to 1, if not unloading\n\t\t}\n\t}\n\t//after=getRSP();\n\n\t//DbgPrint(\"before=%llx after=%llx\\n\",before,after);\n\n\t//DbgPrint(\"end of interrupt1_centry. eflags=%x\", stackpointer[si_eflags]);\n\n\t//if branch tracing set lbr back on (get's disabled on debug interrupts)\t\n\t/*\n\t  if (DebuggerState.storeLBR)\n\t    __writemsr(0x1d9, __readmsr(0x1d9) | 1);\n    */\n\t\t\n\n\n\n\treturn handled;\n}\n\n#ifndef AMD64\n_declspec( naked ) void interrupt1_asmentry( void )\n//This routine is called upon an interrupt 1, even before windows gets it\n{\n\t__asm{\n\t\t//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\n\t\t//meaning the setting of debug registers will have to be done with the changestate call\n\n\t\t//sub esp,4096\n\t\t//push [esp+4096+0+16] //optional ss\n\t\t//push [esp+4096+4+12] //optional esp\n\t\t//push [esp+4096+8+8] //eflags\n\t\t//push [esp+4096+12+4] //cs\n\t\t//push [esp+4096+16+0] //eip\n\n\t\tcld //reset the direction flag\n\t\t\n\t\t\n\t\t\n\t\t\n\n\n\n\t\t//save stack position\n\t\tpush 0 //push an errorcode on the stack so the stackindex can stay the same\n\t\tpush ebp\n\t\tmov ebp,esp\n\n\t\t//save state\n\t\tpushad\n\t\txor eax,eax\n\t\tmov ax,ds\n\t\tpush eax\n\n\t\tmov ax,es\n\t\tpush eax\n\n\t\tmov ax,fs\n\t\tpush eax\n\n\t\tmov ax,gs\n\t\tpush eax\n\n\t\t//save fpu state\n\t\t//save sse state\n\t\t\n\t\tmov ax,0x23 //0x10 should work too, but even windows itself is using 0x23\n\t\tmov ds,ax\n\t\tmov es,ax\n\t\tmov gs,ax\n\t\tmov ax,0x30\n\t\tmov fs,ax\n\n\t\t\n\t\t\n\n\t\tpush ebp\n\t\tcall interrupt1_centry\n\n\t\tcmp eax,1\t//set flag\n\n\t\t//restore state\n\t\tpop gs\n\t\tpop fs\n\t\tpop es\n\t\tpop ds\n\t\tpopad\n\n\t\tpop ebp\t\t\n\n\t\tje skip_original_int1\n\t\t\n\t\tadd esp,4 //undo errorcode push (add effects eflags, so set it at both locations)\n\n\t\tjmp far [Int1JumpBackLocation]\n\nskip_original_int1:\n\t\tadd esp,4 //undo errorcode push\n\t\tiretd\n\t}\n}\n#endif\n"
  },
  {
    "path": "src/debugger.h",
    "content": "#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 threadid;  //\n\tUINT64 causedbydbvm;\n\tUINT64 rflags;\n\tUINT64 rax;//\n\tUINT64 rbx;\n\tUINT64 rcx;//\n\tUINT64 rdx;\n\tUINT64 rsi;//\n\tUINT64 rdi;\n\tUINT64 rbp;//\n\tUINT64 rsp;\n\tUINT64 rip;//\n\tUINT64 r8;\n\tUINT64 r9;//\n\tUINT64 r10;\n\tUINT64 r11;//\n\tUINT64 r12;\n\tUINT64 r13;//\n\tUINT64 r14;\n\tUINT64 r15;//\n\tUINT64 cs;\n\tUINT64 ds;//\n\tUINT64 es;\n\tUINT64 fs;//\n\tUINT64 gs;\n\tUINT64 ss;//\n\tUINT64 dr0;\n\tUINT64 dr1;//\n\tUINT64 dr2;\n\tUINT64 dr3;//\n\tUINT64 dr6;\n\tUINT64 dr7;//\n\tBYTE fxstate[512];\n\n\tUINT64 LBR_Count;\n\tUINT64 LBR[16];\n} DebugStackState, *PDebugStackState;\n#pragma pack()\n\n//stack index\n\ntypedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnReadsAndWrites=3} BreakType;\ntypedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/, bl_4byte=3} BreakLength;\n\nvoid debugger_initialize(void);\nvoid debugger_shutdown(void);\nint debugger_initHookForCurrentCPU(void);\nint debugger_setGlobalDebugState(BOOL state);\nvoid debugger_setStoreLBR(BOOL state);\n\nint debugger_startDebugging(DWORD debuggedProcessID);\nint debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl);\nint debugger_unsetGDBreakpoint(int breakpointnr);\nvoid debugger_touchDebugRegister(UINT_PTR param);\nint debugger_stopDebugging(void);\nNTSTATUS debugger_waitForDebugEvent(ULONG timeout);\nNTSTATUS debugger_continueDebugEvent(BOOL handled);\nUINT_PTR *debugger_getLastStackPointer(void);\nNTSTATUS debugger_getDebuggerState(PDebugStackState state);\nNTSTATUS debugger_setDebuggerState(PDebugStackState state);\n\nvoid GetDebuggerInfo(void);\nVOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2);\n\n#endif"
  },
  {
    "path": "src/deepkernel.c",
    "content": "#pragma warning( disable: 4100 4103)\n\n#include \"deepkernel.h\"\n#include \"DBKFunc.h\"\n#include <windef.h>\n\n#include \"vmxhelper.h\"\n\n\nBOOLEAN MakeWritableKM(PVOID StartAddress,UINT_PTR size)\n{\n#ifndef AMD64\n\tUINT_PTR PTE,PDE;\n\tstruct PTEStruct *x;\n\tUINT_PTR CurrentAddress=(UINT_PTR)StartAddress;\t\n\n\twhile (CurrentAddress<((UINT_PTR)StartAddress+size))\n\t{\n\t\t//find the PTE or PDE of the selected address\n\t\tPTE=(UINT_PTR)CurrentAddress;\n\t\tPTE=PTE/0x1000*PTESize+0xc0000000;\n\n\t\tPTE=(UINT_PTR)StartAddress;\n\t\tPTE=PTE/0x1000*PTESize+0xc0000000;\n\n    \t//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)\n\t    PDE=PTE/0x1000*PTESize+0xc0000000; //same formula\n\n\t\tx=(PVOID)PDE;\n\t\tif ((x->P==0) && (x->A2==0))\n\t\t{\n\t\t\tCurrentAddress+=PAGE_SIZE_LARGE;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (x->PS==1)\n\t\t{\n\t\t\t//big page, no pte\n\t\t\tx->RW=1;\n\t\t\tCurrentAddress+=PAGE_SIZE_LARGE;\n\t\t\tcontinue;\n\t\t}\n\n\t\tCurrentAddress+=0x1000;\n\t\tx=(PVOID)PTE;\n\t\tif ((x->P==0) && (x->A2==0))\n\t\t\tcontinue; //see for explenation the part of the PDE\n\n\t\tx->RW=1;\n\t}\n\n\treturn TRUE;\n#else\n\treturn FALSE;\n#endif\n}\n\nBOOLEAN MakeWritable(PVOID StartAddress,UINT_PTR size,BOOLEAN usecopyonwrite)\n{\n#ifndef AMD64\n\tstruct PTEStruct *x;\n\tunsigned char y;\n\tUINT_PTR CurrentAddress=(UINT_PTR)StartAddress;\t\n\n\t//Makes usermode <0x80000000 writable\n\tif (((UINT_PTR)StartAddress>=0x80000000) || ((UINT_PTR)StartAddress+size>=0x80000000)) \n\t\treturn MakeWritableKM(StartAddress,size); //safety check: don't do kernelmemory with this routine\n\n\t//4kb pages (assumption, I know, but thats the system i'm working with)\n\t//PTE/0x1000*4+0xc0000000;\n\n\twhile (CurrentAddress<((UINT_PTR)StartAddress+size))\n\t{\n\t\t__try\n\t\t{\n\t\t\ty=*(PCHAR)CurrentAddress; //page it in if it wasn't loaded already (BSOD if kernelmode address)\n\t\t\tx=(PVOID)(CurrentAddress/0x1000*PTESize+0xc0000000);\n\t\t\tif (x->RW==0) //if it's read only then\n\t\t\t{\n\t\t\t\tif (usecopyonwrite)\n                    x->A1=1;  //set the copy-on-write bit to 1\n\t\t\t\telse\n\t\t\t\t\tx->RW=1; //just writable\n\t\t\t}\n\t\t}\n\t\t__except(1)\n\t\t{\n\t\t\t//ignore and continue\n\t\t}\t\n\n        CurrentAddress+=0x1000;\n\t}\t\n\n\treturn TRUE;\n#else\n\treturn FALSE;\n#endif\n}\n\n\n//this unit will contain the functions and other crap used by the hider function\nBOOLEAN CheckImageName(IN PUNICODE_STRING FullImageName, IN char* List,int listsize)\n{\n#ifndef AMD64\n\t/*\n\tpre:List has been initialized and all entries are UPPERCASE. Each entry is seperated\n\t    by a 0-marker so just setting the pointer ro the start and doing a compare will work\n\n\t*/\n\tANSI_STRING tempstring;\n\tint i;\n\n\tDbgPrint(\"Checking this image name...\\n\");\n\tRtlZeroMemory(&tempstring,sizeof(ANSI_STRING));\n\tif (RtlUnicodeStringToAnsiString(&tempstring,FullImageName,TRUE)== STATUS_SUCCESS)\n\t{\n\t\tchar *p;\n\t\tINT_PTR modulesize;\n\t\t__try\n\t\t{\n\t\t\tRtlUpperString(&tempstring,&tempstring);\n\n\t\t\tp=List;\n\t\n\t\t\tfor (i=0;i<listsize;i++)\n\t\t\t{\n\t\t\t\tif (List[i]=='\\0')\n\t\t\t\t{\n\t\t\t\t\tmodulesize=i-(INT_PTR)(p-List);\n\t\t\t\t\tif (modulesize>=0)\n\t\t\t\t\t{\t\n\t\t\t\t\t\tDbgPrint(\"Checking %s with %s\\n\",&tempstring.Buffer[tempstring.Length-modulesize],p);\n\n\t\t\t\t\t\tif ((tempstring.Length>=modulesize) && (strcmp(p,&tempstring.Buffer[tempstring.Length-modulesize])==0))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t//we have a match!!!\n\t\t\t\t\t\t\tDbgPrint(\"It's a match with %s\\n\",p);\n\t\t\t\t\t\t\treturn TRUE;\t\n\t\t\t\t\t\t}\t\t\t\t\t\t\n\t\n\t\t\t\t\t}\n\t\t\t\t\tp=&List[i+1];\n\t\t\t\t}\n\t\n\t\t\t}\n\t\t\n\t\t\t\n\t\t}\n\t\t__finally\n\t\t{\n\t\t\tRtlFreeAnsiString(&tempstring);\t\n\t\t}\n\t}\n\n\tDbgPrint(\"No match\\n\");\n#endif\n\treturn FALSE;\n\n}\n\nVOID LoadImageNotifyRoutine(IN PUNICODE_STRING  FullImageName, IN HANDLE  ProcessId, IN PIMAGE_INFO  ImageInfo)\n{\n\t\t\n}\n"
  },
  {
    "path": "src/deepkernel.h",
    "content": "#include <ntifs.h>\n#include <windef.h>\n\n\nVOID LoadImageNotifyRoutine(IN PUNICODE_STRING  FullImageName, IN HANDLE  ProcessId, IN PIMAGE_INFO  ImageInfo);\nBOOLEAN MakeWritable(PVOID StartAddress,UINT_PTR size,BOOLEAN usecopyonwrite);\n\nBOOLEAN\t\tImageNotifyRoutineLoaded;\nchar*\t\tModuleList;\nint\t\t\tModuleListSize;\nULONG\t\tSize;\n\nUINT_PTR\tActiveLinkOffset;\nUINT_PTR\tProcessNameOffset;\nUINT_PTR\tDebugportOffset;\nUINT_PTR\tPIDOffset;\n\n"
  },
  {
    "path": "src/extradefines.h",
    "content": "/*#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\t\t\t\tUCHAR\n#define UINT\t\t\t\t\t\t\tULONG\n#define FILE_DEVICE_UNKNOWN             0x00000022\n#define IOCTL_UNKNOWN_BASE              FILE_DEVICE_UNKNOWN*/\n\nNTKERNELAPI\nNTSTATUS\nObOpenObjectByName(\n    IN POBJECT_ATTRIBUTES ObjectAttributes,\n    IN POBJECT_TYPE ObjectType,\n    IN KPROCESSOR_MODE AccessMode,\n    IN OUT PACCESS_STATE PassedAccessState OPTIONAL,\n    IN ACCESS_MASK DesiredAccess OPTIONAL,\n    IN OUT PVOID ParseContext OPTIONAL,\n    OUT PHANDLE Handle\n    );\n"
  },
  {
    "path": "src/extraimports.h",
    "content": "NTSYSAPI\nBOOLEAN\nKeAddSystemServiceTable(\n    IN PULONG_PTR Base,\n    IN PULONG Count OPTIONAL,\n    IN ULONG Limit,\n    IN PUCHAR Number,\n    IN ULONG Index\n    );\n\n\n"
  },
  {
    "path": "src/interruptHook.c",
    "content": "#pragma warning( disable: 4103)\n\n#include \"ntifs.h\"\n#include <windef.h>\n\n#include \"DBKFunc.h\"\n#include \"vmxhelper.h\"\n\n#include \"interruptHook.h\"\n\n//this sourcefile only so no need to worry about it being modified by out of context code\nstruct \n{\n\tint hooked;\n\tint dbvmInterruptEmulation; //if used, originalCS and originalEIP are ignored and the current IDT data is used to resume the interrupt, currently only for interrupt 1 and 14\n\tWORD originalCS;\n\tULONG_PTR originalEIP;\n} InterruptHook[256]; \n\n\nWORD inthook_getOriginalCS(unsigned char intnr)\n{\n\treturn InterruptHook[intnr].originalCS;\n}\n\nULONG_PTR inthook_getOriginalEIP(unsigned char intnr)\n{\n\treturn InterruptHook[intnr].originalEIP;\n}\n\nint inthook_isHooked(unsigned char intnr)\n{\n\tif (InterruptHook[intnr].hooked)\n\t{\n\t\t//todo: add a check to see if the hook is still present. if not, return false and update the hooked value\n\t\treturn TRUE;\n\t} else return FALSE;\n}\n\nint inthook_isDBVMHook(unsigned char intnr)\n{\n\treturn InterruptHook[intnr].dbvmInterruptEmulation;\n}\n\nint inthook_UnhookInterrupt(unsigned char intnr)\n{\n\tif (InterruptHook[intnr].hooked)\n\t{\n\t\t//it's hooked, try to unhook\n\t\tDbgPrint(\"cpu %d : interrupt %d is hooked\\n\",cpunr(),intnr);\n\t\tif (InterruptHook[intnr].dbvmInterruptEmulation)\n\t\t{\n\t\t\tif (intnr==1)\n\t\t\t\tvmx_redirect_interrupt1(virt_differentInterrupt, 1, 0, 0);\n\t\t\telse if (intnr==3)\n\t\t\t\tvmx_redirect_interrupt3(virt_differentInterrupt, 3, 0, 0); \n\t\t\telse\n\t\t\t\tvmx_redirect_interrupt14(virt_differentInterrupt, 14, 0, 0); \n\n\t\t\treturn TRUE; //that's all we need\n\t\t}\n\n\t\t//still here so not a dbvm hook, unhook the old way and hope nothing has interfered\n\n\t\t{\n\t\t\tINT_VECTOR newVector;\n\t\t\t\n\t\t\t\n\t\t\t//newVector.bUnused=0;\n\t\t\t/*\n\t\t\tnewVector.gatetype=6; //interrupt gate\n\t\t\tnewVector.gatesize=1; //32-bit\n\t\t\tnewVector.zero=0;\n\t\t\tnewVector.DPL=0;\n\t\t\tnewVector.P=1;\n\t\t\t*/\n\t\t\tnewVector.wHighOffset=(WORD)((DWORD)(InterruptHook[intnr].originalEIP >> 16));\n\t\t\tnewVector.wLowOffset=(WORD)InterruptHook[intnr].originalEIP;\n\t\t\tnewVector.wSelector=(WORD)InterruptHook[intnr].originalCS;\n\n#ifdef AMD64\n\t\t\tnewVector.TopOffset=(InterruptHook[intnr].originalEIP >> 32);\n\t\t\tnewVector.Reserved=0;\n#endif\n\n\t\t\t{\n\t\t\t\tIDT idt;\t\n\t\t\t\tGetIDT(&idt);\n\n\t\t\t\t\n\t\t\t\tnewVector.bAccessFlags=idt.vector[intnr].bAccessFlags;\n\n\t\t\t\tdisableInterrupts();\n\t\t\t\tidt.vector[intnr]=newVector;\n\t\t\t\tenableInterrupts();\t\t\t\t\n\t\t\t}\n\n\t\t\tDbgPrint(\"Restored\\n\");\n\t\t}\n\t}\n\n\treturn TRUE;\n}\n\nint inthook_HookInterrupt(unsigned char intnr, int newCS, ULONG_PTR newEIP, PJUMPBACK jumpback)\n{\n\tIDT idt;\t\n\tGetIDT(&idt);\n\tDbgPrint(\"inthook_HookInterrupt for cpu %d (vmxusable=%d)\\n\",cpunr(), vmxusable);\n#ifdef AMD64\n\tDbgPrint(\"interrupt %d newCS=%x newEIP=%llx jumpbacklocation=%p\\n\",intnr, newCS, newEIP, jumpback);\n#else\n\tDbgPrint(\"interrupt %d newCS=%x newEIP=%x jumpbacklocation=%p\\n\",intnr, newCS, newEIP, jumpback);\n#endif\n\n\tDbgPrint(\"InterruptHook[%d].hooked=%d\\n\", intnr, InterruptHook[intnr].hooked);\n\n\tif (!InterruptHook[intnr].hooked)\n\t{\n\t\t//new hook, so save the originals\n\t\tInterruptHook[intnr].originalCS=idt.vector[intnr].wSelector;\n\t\tInterruptHook[intnr].originalEIP=idt.vector[intnr].wLowOffset+(idt.vector[intnr].wHighOffset << 16);\n#ifdef AMD64\n\t\tInterruptHook[intnr].originalEIP|=(UINT64)((UINT64)idt.vector[intnr].TopOffset << 32);\n#endif\n\t}\n\n\tif (jumpback)\n\t{\n\t\tjumpback->cs=InterruptHook[intnr].originalCS;\n\t\tjumpback->eip=InterruptHook[intnr].originalEIP;\n\t}\n\n\tDbgPrint(\"vmxusable=%d\\n\", vmxusable);\n\n\tif (vmxusable && ((intnr==1) || (intnr==3) || (intnr==14)) )\n\t{\t\n\t\tDbgPrint(\"VMX Hook path\\n\");\n\t\t\n\t\tswitch (intnr)\n\t\t{\n\t\t\tcase 1:\n\t\t\t\tvmx_redirect_interrupt1(virt_emulateInterrupt, 0, newCS, newEIP);\n\t\t\t\tbreak;\n\n\t\t\tcase 3:\n\t\t\t\tvmx_redirect_interrupt3(virt_emulateInterrupt, 0, newCS, newEIP);\n\t\t\t\tbreak;\n\n\t\t\tcase 14:\n\t\t\t\tvmx_redirect_interrupt14(virt_emulateInterrupt, 0, newCS, newEIP);\n\t\t\t\tbreak;\n\t\t}\n\n\t\tInterruptHook[intnr].dbvmInterruptEmulation=1;\n\t}\n\telse\n\t{\n\t\t\n\n\t\t//old fashioned hook\n\t\tINT_VECTOR newVector;\n#ifdef AMD64\n\t\tif (intnr<32)\n\t\t{\n\t\t\tDbgPrint(\"64-bit: DBVM is not loaded and a non dbvm hookable interrupt is being hooked that falls below 32\\n\");\n\t\t\treturn FALSE;\n\t\t}\n#endif\n\n\n\t\tDbgPrint(\"sizeof newVector=%d\\n\",sizeof(INT_VECTOR));\n\t\t\n\t\t\n\t\tnewVector.wHighOffset=(WORD)((DWORD)(newEIP >> 16));\n\t\tnewVector.wLowOffset=(WORD)newEIP;\n\t\tnewVector.wSelector=(WORD)newCS;\n\t\tnewVector.bUnused=0;\n\t\tnewVector.bAccessFlags=idt.vector[intnr].bAccessFlags; //don't touch accessflag, the default settings are good (e.g: int3,4 and 8 have dpl=3)\n\n#ifdef AMD64\n\t\tnewVector.TopOffset=(newEIP >> 32);\n\t\tnewVector.Reserved=0;\n#endif\n\n\t\tdisableInterrupts(); //no kernelmode taskswitches please\n\t\tidt.vector[intnr]=newVector;\n\t\tenableInterrupts();\t\n\n\t\tInterruptHook[intnr].dbvmInterruptEmulation=0;\n\n\t\tDbgPrint(\"int %d will now go to %x:%p\\n\",intnr, newCS, newEIP);\n\n\t}\n\n\n\tInterruptHook[intnr].hooked=1;\n\treturn TRUE;\n}\n\n"
  },
  {
    "path": "src/interruptHook.h",
    "content": "#ifndef INTERRUPTHOOK_H\n#define INTERRUPTHOOK_H\n\n#include <windef.h>\n\n//assuming the standard interrupt hook routine is used this stackindex will be valid\n#ifdef AMD64\ntypedef enum {si_eax=0, si_ebx=1, si_ecx=2, si_edx=3, si_esi=4, si_edi=5, si_ebp=6, si_stack_esp=7, si_r8=8, si_r9=9, si_r10=10, si_r11=11, si_r12=12, si_r13=13, si_r14=14, si_r15=15, si_es=16, si_ds=17, si_stack_ss=18, si_xmm=19, si_errorcode=19+(4096/8)+(512/8), si_eip=20+(4096/8) + (512 / 8), si_cs=21+(4096/8) + (512 / 8), si_eflags=22+(4096/8) + (512 / 8), si_esp=23+(4096/8) + (512 / 8), si_ss=24+(4096/8) + (512 / 8)} stackindex;\n#else\ntypedef enum {si_gs=-12, si_fs=-11, si_es=-10, si_ds=-9, si_edi=-8, si_esi=-7, si_stack_ebp=-6, si_stack_esp=-5, si_ebx=-4, si_edx=-3, si_ecx=-2, si_eax=-1, si_ebp=0, si_errorcode=1, si_eip=2, si_cs=3, si_eflags=4, si_esp=5, si_ss=6} stackindex;\n#endif\n\n\n\n#pragma pack(1) //allignment of 1 byte\ntypedef struct tagINT_VECTOR\n{\n\tWORD\twLowOffset;\n\tWORD\twSelector;\n\tBYTE\tbUnused;\n\tBYTE    bAccessFlags;\n\t\n\t/*\n\tunsigned gatetype  : 3; //101=Task, 110=interrupt, 111=trap\n\tunsigned gatesize  : 1; //1=32bit, 0=16bit\n\tunsigned zero      : 1;\n\tunsigned DPL       : 2;\n\tunsigned P         : 1;\n\t*/\n\tWORD\twHighOffset;\n#ifdef AMD64\n\tDWORD\tTopOffset;\n\tDWORD\tReserved;\n#endif\n} INT_VECTOR, *PINT_VECTOR;\n#pragma pack()\n\n#pragma pack(2) //allignemnt of 2 byte\ntypedef struct tagIDT\n{    \n    WORD wLimit;\n\tPINT_VECTOR vector;\n} IDT, *PIDT;\n#pragma pack()\n\n\n#ifdef AMD64\ntypedef\n#pragma pack(1) //allignemnt of 1 byte\nstruct\n{    \n\tUINT64 eip;\n\tWORD cs;\n} JUMPBACK, *PJUMPBACK;\n#pragma pack()\n#else\ntypedef\n#pragma pack(1) //allignemnt of 1 byte\nstruct\n{    \n\tDWORD eip;\n\tWORD cs;\n} JUMPBACK, *PJUMPBACK;\n#pragma pack()\n#endif\n\n\nint inthook_HookInterrupt(unsigned char intnr, int newCS, ULONG_PTR newEIP, PJUMPBACK jumpback);\nint inthook_UnhookInterrupt(unsigned char intnr);\nint inthook_isHooked(unsigned char intnr);\nint inthook_isDBVMHook(unsigned char intnr);\nULONG_PTR inthook_getOriginalEIP(unsigned char intnr);\nWORD inthook_getOriginalCS(unsigned char intnr);\n\n\n\n\n#endif"
  },
  {
    "path": "src/memscan.c",
    "content": "#pragma warning( disable: 4100 4103 4146 4213)\n\n#include \"ntifs.h\"\n#include <windef.h>\n#ifdef CETC\n#include \"tdiwrapper.h\"\n#include \"kfiles.h\"\n#endif\n#include \"memscan.h\"\n#include \"DBKFunc.h\"\n\n#include \"vmxhelper.h\"\n#include \"vmxoffload.h\" //PTE structs\n#include \"noexceptions.h\"\n/*#include \"deepkernel.h\"\n*/\n\nUINT_PTR KnownPageTableBase = 0;\n\nvoid VirtualAddressToIndexes(QWORD address, int *pml4index, int *pagedirptrindex, int *pagedirindex, int *pagetableindex)\n/*\n* Returns the indexes for the given address  (ia32e)\n*/\n{\n\tif (PTESize == 8)\n\t{\n\t\t*pml4index = (address >> 39) & 0x1ff;\n\t\t*pagedirptrindex = (address >> 30) & 0x1ff;\n\t\t*pagedirindex = (address >> 21) & 0x1ff;\n\t\t*pagetableindex = (address >> 12) & 0x1ff;\n\t}\n\telse\n\t{\n\t\t*pml4index = 0;\n\t\t*pagedirptrindex = 0;\n\t\t*pagedirindex = (address >> 22) & 0x3ff;\n\t\t*pagetableindex = (address >> 12) & 0x3ff;\n\t}\n}\n\nQWORD IndexesToVirtualAddress(int pml4index, int pagedirptrindex, int pagedirindex, int pagetableindex, int offset)\n{\n\tQWORD r;\n#ifndef AMD64\n\tif (PTESize == 8)\n\t{\n#endif\n\t\tr = ((QWORD)pml4index & 0x1ff) << 39;\n\n\t\tif (pml4index >= 256)\n\t\t\tr = r | 0xFFFF000000000000ULL;\n\n\t\tr |= ((QWORD)pagedirptrindex & 0x1ff) << 30;\n\t\tr |= ((QWORD)pagedirindex & 0x1ff) << 21;\n\t\tr |= ((QWORD)pagetableindex & 0x1ff) << 12;\n\t\tr |= offset & 0xfff;\n\n\t\t\n#ifndef AMD64\n\t}\n\telse\n\t{\n\t\tr |= (pagedirindex & 0x3ff) << 22;\n\t\tr |= (pagetableindex & 0x3ff) << 12;\n\t\tr |= offset & 0xfff;\n\t}\n#endif\n\n\treturn r;\n\n}\n\n#ifndef AMD64\nvoid VirtualAddressToPageEntries32(DWORD address, PPDE *pagedirentry, PPTE *pagetableentry)\n{\n\tDWORD PTE = address;\n\tUINT_PTR PTB = (DWORD)getPageTableBase();\n\tPTE = PTE >> 12;\n\tPTE = PTE * 4;\n\tPTE = PTE + PTB;\n\t*pagetableentry = (PPTE)PTE;\n\n\tUINT_PTR PDE = PTE;\n\tPDE = PDE & 0x0000ffffffffffffULL;\n\tPDE = PDE >> 12;\n\tPDE = PDE * 4;\n\tPDE = PDE + PTB;\n\t*pagedirentry = (PPDE)PDE;\t\n}\n#endif\n\nvoid VirtualAddressToPageEntries64(QWORD address, PPDPTE_PAE *pml4entry, PPDPTE_PAE *pagedirpointerentry, PPDE_PAE *pagedirentry, PPTE_PAE *pagetableentry)\n{\n\tQWORD PTE = address;\n\n\tQWORD PTB=getPageTableBase();\n\n\tPTE = PTE & 0x0000ffffffffffffULL;\n\tPTE = PTE >> 12;\n\tPTE = PTE * 8;\n\tPTE = PTE + PTB;\n\t*pagetableentry = (PPTE_PAE)(UINT_PTR)PTE;\n\n\t//*pagetableentry = (PPTE_PAE)((((QWORD)address & 0x0000ffffffffffffull) >> 12)*8) + 0xfffff80000000000ULL;\n\n\tQWORD PDE = PTE;\n\tPDE = PDE & 0x0000ffffffffffffULL;\n\tPDE = PDE >> 12;\n\tPDE = PDE * 8;\n\tPDE = PDE + PTB;\n\t*pagedirentry = (PPDE_PAE)(UINT_PTR)PDE;\n\n\n\t//*pagedirentry = (PPDE_PAE)((((QWORD)*pagetableentry & 0x0000ffffffffffffull )>> 12)*8) + 0xfffff80000000000ULL;\n\n\tQWORD PDPTR = PDE;\n\tPDPTR = PDPTR & 0x0000ffffffffffffULL;\n\tPDPTR = PDPTR >> 12;\n\tPDPTR = PDPTR * 8;\n\tPDPTR = PDPTR + PTB;\n\t*pagedirpointerentry = (PPDPTE_PAE)(UINT_PTR)PDPTR;\n\n\t//*pagedirpointerentry = (PPDPTE_PAE)((((QWORD)*pagedirentry & 0x0000ffffffffffffull )>> 12)*8) + 0xfffff80000000000ULL;\n#ifdef AMD64\n\tQWORD PML4 = PDPTR;\n\tPML4 = PML4 & 0x0000ffffffffffffULL;\n\tPML4 = PML4 >> 12;\n\tPML4 = PML4 * 8;\n\tPML4 = PML4 + PTB;\n\t*pml4entry = (PPDPTE_PAE)PML4;\n#else\n\t*pml4entry = NULL;\n#endif\n}\n\nBOOLEAN IsAddressSafe(UINT_PTR StartAddress)\n{\n\t#ifdef AMD64\n\t//cannonical check. Bits 48 to 63 must match bit 47\n\tUINT_PTR toppart=(StartAddress >> 47);\n\tif (toppart & 1)\n\t{\n\t\t//toppart must be 0x1ffff\n\t\tif (toppart != 0x1ffff)\n\t\t\treturn FALSE;\n\t}\n\telse\n\t{\n\t\t//toppart must be 0\n\t\tif (toppart != 0)\n\t\t\treturn FALSE;\n\n\t}\n\n\t#endif\n\n\t//return TRUE;\n\tif (loadedbydbvm)\n\t{\n\t\tBYTE x=0;\n\t\tUINT_PTR lasterror;\n\t\tdisableInterrupts();\n\t\tvmx_disable_dataPageFaults();\n\n\t\tx=*(volatile BYTE *)StartAddress;\n\n\t\tvmx_enable_dataPageFaults();\n\t\tlasterror=vmx_getLastSkippedPageFault();\n\t\tenableInterrupts();\n\n\t\tDbgPrint(\"IsAddressSafe dbvm-mode: lastError=%p\\n\", lasterror);\n\t\t\n\t\tif (lasterror) return FALSE;\t\t\n\t}\n\n\n\t{\n#ifdef AMD64\n\t\tUINT_PTR kernelbase=0x7fffffffffffffffULL;\n\n\t\t\n\t\tif (StartAddress<kernelbase)\n\t\t\treturn TRUE;\n\t\telse\n\t\t{\n\t\t\tPHYSICAL_ADDRESS physical;\n\t\t\tphysical.QuadPart=0;\n\t\t\tphysical=MmGetPhysicalAddress((PVOID)StartAddress);\n\t\t\treturn (physical.QuadPart!=0);\n\t\t}\n#else\n\t/*\tMDL x;\n\n\t\t\n\t\tMmProbeAndLockPages(&x,KernelMode,IoModifyAccess);\n\n\n\t\tMmUnlockPages(&x);\n\t\t*/\n\t\tULONG kernelbase=0x7ffe0000;\n\n\t\tif ((!HiddenDriver) && (StartAddress<kernelbase))\n\t\t\treturn TRUE;\n\n\t\t{\n\t\t\tUINT_PTR PTE,PDE;\n\t\t\tstruct PTEStruct *x;\n\t\t\t\n\t\t\t/*\n\t\t\tPHYSICAL_ADDRESS physical;\n\t\t\tphysical=MmGetPhysicalAddress((PVOID)StartAddress);\n\t\t\treturn (physical.QuadPart!=0);*/\n\n\n\t\t\tPTE=(UINT_PTR)StartAddress;\n\t\t\tPTE=PTE/0x1000*PTESize+0xc0000000;\n\n    \t\t//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)\n\t\t\tPDE=PTE/0x1000*PTESize+0xc0000000; //same formula\n\n\t\t\tx=(PVOID)PDE;\n\t\t\tif ((x->P==0) && (x->A2==0))\n\t\t\t{\n\t\t\t\t//Not present or paged, and since paging in this area isn't such a smart thing to do just skip it\n\t\t\t\t//perhaps this is only for the 4 mb pages, but those should never be paged out, so it should be 1\n\t\t\t\t//bah, I've got no idea what this is used for\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (x->PS==1)\n\t\t\t{\n\t\t\t\t//This is a 4 MB page (no pte list)\n\t\t\t\t//so, (startaddress/0x400000*0x400000) till ((startaddress/0x400000*0x400000)+(0x400000-1) ) ) is specified by this page\n\t\t\t}\n\t\t\telse //if it's not a 4 MB page then check the PTE\n\t\t\t{\n\t\t\t\t//still here so the page table directory agreed that it is a usable page table entry\n\t\t\t\tx=(PVOID)PTE;\n\t\t\t\tif ((x->P==0) && (x->A2==0))\n\t\t\t\t\treturn FALSE; //see for explenation the part of the PDE\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t} \n#endif\n\t}\n\n}\n\nUINT_PTR getPEThread(UINT_PTR threadid)  \n{\t\n    //UINT_PTR *threadid;\n\tPETHREAD selectedthread;\n\tUINT_PTR result=0;\n\t\n\t\n\n\tif (PsLookupThreadByThreadId((PVOID)(UINT_PTR)threadid,&selectedthread)==STATUS_SUCCESS)\n\t{\n\t\tresult=(UINT_PTR)selectedthread;\n\t\tObDereferenceObject(selectedthread);\n\t}\n\n\treturn result;\n}\n\nBOOLEAN WriteProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer)\n{\n\tPEPROCESS selectedprocess=PEProcess;\n\tKAPC_STATE apc_state;\n\tNTSTATUS ntStatus=STATUS_UNSUCCESSFUL;\n\t\t\n\tif (selectedprocess==NULL)\n\t{\n\t\t//DbgPrint(\"WriteProcessMemory:Getting PEPROCESS\\n\");\n        if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))\n\t\t   return FALSE; //couldn't get the PID\n\n\t\t//DbgPrint(\"Retrieved peprocess\");  \n\t}\n\n\t//selectedprocess now holds a valid peprocess value\n\t__try\n\t{\n\t\tRtlZeroMemory(&apc_state,sizeof(apc_state));\t\t\t\t\t\n\n    \tKeAttachProcess((PEPROCESS)selectedprocess);\t\t\t\t\n\n        __try\n        {\n\t\t\tchar* target;\n\t\t\tchar* source;\n\t\t\tunsigned int i;\t\n\n\t\t\t//DbgPrint(\"Checking safety of memory\\n\");\n\n\t\t\tif ((IsAddressSafe((UINT_PTR)Address)) && (IsAddressSafe((UINT_PTR)Address+Size-1)))\n\t\t\t{\t\t\t\n\n\t    \t\t//still here, then I gues it's safe to read. (But I can't be 100% sure though, it's still the users problem if he accesses memory that doesn't exist)\n\t\t\t\tBOOL disabledWP = FALSE;\n\n\t\t\t\ttarget=Address;\n\t\t\t\tsource=Buffer;\n\n\t\t\t\tif ((loadedbydbvm) || (KernelWritesIgnoreWP))  //add a extra security around it as the PF will not be handled\n\t\t\t\t{\n\t\t\t\t\tdisableInterrupts();\n\n\t\t\t\t\tif (loadedbydbvm)\n\t\t\t\t\t\tvmx_disable_dataPageFaults();\n\n\t\t\t\t\tif (KernelWritesIgnoreWP)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Disabling CR0.WP\");\n\t\t\t\t\t\tsetCR0(getCR0() & (~(1 << 16))); //disable the WP bit\t\t\t\t\t\n\t\t\t\t\t\tdisabledWP = TRUE;\t\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t\tif ((!loadedbydbvm) && ((KernelWritesIgnoreWP) || ((UINT_PTR)target >= 0x8000000000000000ULL)))\n\t\t\t\t{\n\t\t\t\t\ti = NoExceptions_CopyMemory(target, source, Size);\n\t\t\t\t\tif (i != (int)Size)\n\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\telse\n\t\t\t\t\t\tntStatus = STATUS_SUCCESS;\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tRtlCopyMemory(target, source, Size);\n\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t   \n\t\t\t\tif ((loadedbydbvm) || (disabledWP))\n\t\t\t\t{\n\t\t\t\t\tUINT_PTR lastError=0;\n\n\t\t\t\t\tif (disabledWP)\n\t\t\t\t\t{\t\t\t\t\t\t\n\t\t\t\t\t\tsetCR0(getCR0() | (1 << 16));\n\t\t\t\t\t\tDbgPrint(\"Enabled CR0.WP\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (loadedbydbvm)\n\t\t\t\t\t{\n\t\t\t\t\t\tlastError = vmx_getLastSkippedPageFault();\n\t\t\t\t\t\tvmx_enable_dataPageFaults();\n\t\t\t\t\t}\n\n\t\t\t\t\tenableInterrupts();\n\n\t\t\t\t\tDbgPrint(\"lastError=%p\\n\", lastError);\n\t\t\t\t\tif (lastError)\n\t\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t\n\t\t}\n\t\t__finally\n\t\t{\n\t\t\tKeDetachProcess();\n\t\t}\n\t}\t\t\t\n\t__except(1)\n\t{\n\t\t//DbgPrint(\"Error while writing\\n\");\n\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t}\n\t\n\tif (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference\n\t\tObDereferenceObject(selectedprocess);\n\n\treturn NT_SUCCESS(ntStatus);\n}\n\n\nBOOLEAN ReadProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer)\n{\n\tPEPROCESS selectedprocess=PEProcess;\n\t//KAPC_STATE apc_state;\n\tNTSTATUS ntStatus=STATUS_UNSUCCESSFUL;\n\n\tif (PEProcess==NULL)\n\t{\n\t\tif (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))\n\t\t   return FALSE; //couldn't get the PID\n \n\t}\n\n\t//selectedprocess now holds a valid peprocess value\n\t__try\n\t{\n    \tKeAttachProcess((PEPROCESS)selectedprocess);\n\n\n\n        __try\n        {\n\t\t\tchar* target;\n\t\t\tchar* source;\n\t\t\tint i;\n\n\t\t\n\t\t\tif ((IsAddressSafe((UINT_PTR)Address)) && (IsAddressSafe((UINT_PTR)Address+Size-1)))\n\t\t\t{\n\t\t\t\t\n\n\n\t\t\t\ttarget=Buffer;\n\t\t\t\tsource=Address;\n\n\t\t\t\tif (loadedbydbvm) //add a extra security around it\n\t\t\t\t{\n\t\t\t\t\tdisableInterrupts();\n\t\t\t\t\tvmx_disable_dataPageFaults();\n\t\t\t\t}\n\n\t\t\t\n\t\t\t\tif ((loadedbydbvm) || ((UINT_PTR)source < 0x8000000000000000ULL))\n\t\t\t\t{\n\t\t\t\t\tRtlCopyMemory(target, source, Size);\n\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ti=NoExceptions_CopyMemory(target, source, Size);\n\t\t\t\t\tif (i != (int)Size)\n\t\t\t\t\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t\t\t\t\telse\n\t\t\t\t\t\tntStatus = STATUS_SUCCESS;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t\n\n\t\t\t\tif (loadedbydbvm)\n\t\t\t\t{\n\t\t\t\t\tUINT_PTR lastError;\n\t\t\t\t\tlastError=vmx_getLastSkippedPageFault();\n\t\t\t\t\tvmx_enable_dataPageFaults();\n\n\t\t\t\t\tenableInterrupts();\n\n\t\t\t\t\tDbgPrint(\"lastError=%p\\n\", lastError);\n\t\t\t\t\tif (lastError)\n\t\t\t\t\t\tntStatus=STATUS_UNSUCCESSFUL;\n\t\t\t\t}\n\n\t\t\t\t\n\t\t\t}\n\t\t\t\t\n\t\t}\n\t\t__finally\n\t\t{\n\n\t\t\tKeDetachProcess();\n\t\t}\n\t}\t\t\t\n\t__except(1)\n\t{\n\t\t//DbgPrint(\"Error while reading: ReadProcessMemory(%x,%p, %p, %d, %p\\n\", PID, PEProcess, Address, Size, Buffer);\n\n\t\tntStatus = STATUS_UNSUCCESSFUL;\n\t}\n\t\n\tif (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference\n\t\tObDereferenceObject(selectedprocess);\n\n\treturn NT_SUCCESS(ntStatus);\n}\n\nUINT64 maxPhysAddress = 0;\nUINT64 getMaxPhysAddress(void)\n{\n\tif (maxPhysAddress==0)\t\t\t\n\t{\n\t\tint physicalbits;\n\t\tDWORD r[4];\n\t\t__cpuid(r, 0x80000008);\n\n\t\t//get max physical address\n\t\tphysicalbits = r[0] & 0xff;\n\n\t\tmaxPhysAddress = 0xFFFFFFFFFFFFFFFFULL;\n\t\tmaxPhysAddress = maxPhysAddress >> physicalbits; //if physicalbits==36 then maxPhysAddress=0x000000000fffffff\n\t\tmaxPhysAddress = ~(maxPhysAddress << physicalbits); //<< 36 = 0xfffffff000000000 .  after inverse : 0x0000000fffffffff\t\t\n\t}\n\t\n\treturn maxPhysAddress;\n}\n\n\nNTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, void *output)\n{\n\tHANDLE\t\t\tphysmem;\n\tUNICODE_STRING\tphysmemString;\n\tOBJECT_ATTRIBUTES attributes;\n\tWCHAR\t\t\tphysmemName[] = L\"\\\\device\\\\physicalmemory\";\n\tUCHAR*\t\t\tmemoryview;\n\tNTSTATUS\t\tntStatus = STATUS_UNSUCCESSFUL;\n\tPMDL\t\t\toutputMDL;\n\n\tDbgPrint(\"ReadPhysicalMemory(%p, %d, %p)\", startaddress, bytestoread, output);\n\n\tif (((UINT64)startaddress > getMaxPhysAddress()) || ((UINT64)startaddress + bytestoread > getMaxPhysAddress()))\n\t{\n\t\tDbgPrint(\"Invalid physical address\\n\");\n\t\treturn ntStatus;\n\t}\n\t\n\toutputMDL = IoAllocateMdl(output, (ULONG)bytestoread, FALSE, FALSE, NULL);\n\t__try\n\t{\n\t\tMmProbeAndLockPages(outputMDL, KernelMode, IoWriteAccess);\n\t}\n\t__except (1)\n\t{\n\t\tIoFreeMdl(outputMDL);\n\t\treturn STATUS_UNSUCCESSFUL;\n\t}\n\n\t__try\n\t{\n\t\tRtlInitUnicodeString( &physmemString, physmemName );\t\n\n\t\tInitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );\t\n\t\tntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );\n\t\tif (ntStatus==STATUS_SUCCESS)\n\t\t{\n\t\t\t//hey look, it didn't kill it\n\t\t\tSIZE_T length;\n\t\t\tPHYSICAL_ADDRESS\tviewBase;\n\t\t\tUINT_PTR offset;\n\t\t\tUINT_PTR toread;\n\n\t\t\tviewBase.QuadPart = (ULONGLONG)(startaddress);\t\t\t\t\t\n\t\t\t\n\t\t\tlength=0x2000;//pinp->bytestoread; //in case of a overlapping region\n\t\t\ttoread=bytestoread;\n\n\t\t\tmemoryview=NULL;\n\n\t\t\tDbgPrint(\"ReadPhysicalMemory:viewBase.QuadPart=%x\", viewBase.QuadPart); \n\n\n\t\t\tntStatus=ZwMapViewOfSection(\n\t\t\t\tphysmem,  //sectionhandle\n\t\t\t\tNtCurrentProcess(), //processhandle (should be -1)\n\t\t\t\t&memoryview, //BaseAddress\n\t\t\t\t0L, //ZeroBits\n\t\t\t\tlength, //CommitSize\n\t\t\t\t&viewBase, //SectionOffset\n\t\t\t\t&length, //ViewSize\n\t\t\t\tViewShare,\n\t\t\t\t0,\n\t\t\t\tPAGE_READWRITE);\n\n\t\t\tif ((ntStatus == STATUS_SUCCESS) && (memoryview!=NULL))\n\t\t\t{\n\t\t\t\tif (toread > length)\n\t\t\t\t\ttoread = length;\n\n\t\t\t\tif (toread)\n\t\t\t\t{\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\n\t\t\t\t\t\toffset = (UINT_PTR)(startaddress)-(UINT_PTR)viewBase.QuadPart;\n\n\t\t\t\t\t\tif (offset + toread > length)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Too small map\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tRtlCopyMemory(output, &memoryview[offset], toread);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tZwUnmapViewOfSection(NtCurrentProcess(), memoryview);\n\t\t\t\t\t}\n\t\t\t\t\t__except (1)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Failure mapping physical memory\");\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDbgPrint(\"ReadPhysicalMemory error:ntStatus=%x\", ntStatus); \n\t\t\t}\n\n\t\t\tZwClose(physmem);\n\t\t};\n\t}\n\t__except(1)\n\t{\n\t\tDbgPrint(\"Error while reading physical memory\\n\");\n\t}\n\n\tMmUnlockPages(outputMDL);\n\tIoFreeMdl(outputMDL);\n\treturn ntStatus;\n}\n\nUINT_PTR SignExtend(UINT_PTR a)\n{\n#ifdef AMD64\n\tif ((a >> 47)==1)\n\t\treturn a | 0xFFFF000000000000ULL; //add sign extended bits\n\telse\n\t\treturn a;\n#else\n\treturn a;\n#endif\n}\n\n\nUINT_PTR getPageTableBase()\n{\n#if (NTDDI_VERSION >= NTDDI_VISTA)\n\tif (KnownPageTableBase==0)\n\t{\n\t\tRTL_OSVERSIONINFOW v;\n\t\tv.dwOSVersionInfoSize = sizeof(v);\n\t\tif (RtlGetVersion(&v))\n\t\t{\n\t\t\tDbgPrint(\"RtlGetVersion failed\");\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ((v.dwMajorVersion >= 10) && (v.dwBuildNumber >= 14393))\n\t\t{\n\t\t\tPHYSICAL_ADDRESS a;\n\t\t\tPVOID r;\n\t\t\ta.QuadPart = getCR3() & 0xFFFFFFFFFFFFF000ULL;\n\t\t\tr = MmGetVirtualForPhysical(a); //if this stops working, look for CR3 in the pml4 table\n\n\t\t\tKnownPageTableBase = ((UINT_PTR)r) & 0xFFFFFF8000000000ULL;\n\n\t\t\tMAX_PTE_POS = (UINT_PTR)((QWORD)KnownPageTableBase + 0x7FFFFFFFF8ULL);\n\t\t\tMAX_PDE_POS = (UINT_PTR)((QWORD)KnownPageTableBase + 0x7B7FFFFFF8ULL);\n\t\t\n\n\t\t}\n\t\telse\n\t\t\tKnownPageTableBase=PAGETABLEBASE;\n\n\t\tDbgPrint(\"PageTableBase at %p\\n\", KnownPageTableBase);\n\t}\t\n\n\treturn KnownPageTableBase;\n#else\n\treturn PAGETABLEBASE;\n#endif\n\n}\n\ntypedef void PRESENTPAGECALLBACK(UINT_PTR StartAddress, UINT_PTR EndAddress, struct PTEStruct *pageEntry);\nBOOL walkPagingLayout(PEPROCESS PEProcess, UINT_PTR MaxAddress, PRESENTPAGECALLBACK OnPresentPage)\n{\n#ifdef AMD64\n\tUINT_PTR pagebase = getPageTableBase();\n#else\n\tUINT_PTR pagebase = PAGETABLEBASE;\n#endif\n\n\tif (pagebase == 0)\n\t\treturn FALSE;\n\n\tif (OnPresentPage == NULL)\n\t\treturn FALSE;\n\n\t__try\n\t{\n\t\tKeAttachProcess((PEPROCESS)PEProcess);\n\t\t__try\n\t\t{\n\t\t\tUINT_PTR currentAddress = 0; //start from address 0\n\t\t\tUINT_PTR lastAddress = 0;\n\t\t\tstruct PTEStruct *PPTE, *PPDE, *PPDPE, *PPML4E;\n\n\t\t\twhile ((currentAddress < MaxAddress) && (lastAddress<=currentAddress) )\n\t\t\t{\n\t\t\t\t//DbgPrint(\"currentAddress=%p\\n\", currentAddress);\n\t\t\t\tlastAddress = currentAddress;\n\n\t\t\t\t\n\t\t\t\t(UINT_PTR)PPTE = (UINT_PTR)(((currentAddress & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase);\n\t\t\t\t(UINT_PTR)PPDE = (UINT_PTR)((((UINT_PTR)PPTE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;\n\t\t\t\t(UINT_PTR)PPDPE = (UINT_PTR)((((UINT_PTR)PPDE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;\n\t\t\t\t(UINT_PTR)PPML4E = (UINT_PTR)((((UINT_PTR)PPDPE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;\n\t\t\t\tif (PTESize == 8)\n\t\t\t\t\t(UINT_PTR)PPDPE = ((((UINT_PTR)PPDE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;\n\t\t\t\telse\n\t\t\t\t\t(UINT_PTR)PPDPE = 0;\n\n#ifdef AMD64\n\t\t\t\t(UINT_PTR)PPML4E = ((((UINT_PTR)PPDPE) & 0xFFFFFFFFFFFFULL) >> 12) *PTESize + pagebase;\n#else\n\t\t\t\t(UINT_PTR)PPML4E = 0;\n#endif\n\n\t\n#ifdef AMD64\n\t\t\t\tif ((PPML4E) && (PPML4E->P == 0))\n\t\t\t\t{\n\t\t\t\t\tcurrentAddress &= 0xffffff8000000000ULL;\n\t\t\t\t\tcurrentAddress += 0x8000000000ULL;\t\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n#endif\n\n\t\t\t\tif ((PPDPE) && (PPDPE->P == 0))\n\t\t\t\t{\t\t\n\t\t\t\t\tcurrentAddress &= 0xffffffffc0000000ULL;\n\t\t\t\t\tcurrentAddress += 0x40000000;\t\t\t\t\t\t\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (PPDPE->PS) //some systems have 1GB page support. But not sure windows uses these\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"----->%llx is a 1GB range\", currentAddress);\n\t\t\t\t\tOnPresentPage(currentAddress, currentAddress + 0x40000000 - 1, PPDPE);\n\t\t\t\t\tcurrentAddress += 0x40000000;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (PPDE->P == 0)\n\t\t\t\t{\n\t\t\t\t\n\t\t\t\t\tif (PAGE_SIZE_LARGE == 0x200000)\n\t\t\t\t\t\tcurrentAddress &= 0xffffffffffe00000ULL;\n\t\t\t\t\telse\n\t\t\t\t\t\tcurrentAddress &= 0xffffffffffc00000ULL;\n\n\t\t\t\t\tcurrentAddress += PAGE_SIZE_LARGE;\t\t\t\n\t\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (PPDE->PS)\n\t\t\t\t{\n\t\t\t\t\tOnPresentPage(currentAddress, currentAddress + PAGE_SIZE_LARGE-1, PPDE);\t\t\t\t\t\n\t\t\t\t\tcurrentAddress += PAGE_SIZE_LARGE;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (PPTE->P == 0)\n\t\t\t\t{\t\t\n\t\t\t\t\n\t\t\t\t\tcurrentAddress &= 0xfffffffffffff000ULL;\n\t\t\t\t\tcurrentAddress += 0x1000;\n\t\t\t\t\t\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tOnPresentPage(currentAddress, currentAddress + 0xfff, PPTE);\t\t\t\t\n\t\t\t\tcurrentAddress += 0x1000;\n\t\t\t}\n\n\t\t}\n\t\t__finally\n\t\t{\n\t\t\tKeDetachProcess();\n\t\t}\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"Excepion while walking the paging layout\\n\");\n\t\treturn FALSE;\n\t}\n\n\treturn TRUE;\n}\n\n\n\n\nPPENTRY AccessedList = NULL;\nint AccessedListSize;\n\nvoid CleanAccessedList()\n{\t\n\tPPENTRY e = AccessedList;\n\tPPENTRY previous;\n\t//DbgPrint(\"Cleaning list\");\n\n\twhile (e)\n\t{\n\t\tprevious = e;\n\t\te = e->Next;\n\t\tExFreePool(previous);\n\t}\n\n\tAccessedList = NULL;\n\tAccessedListSize = 0;\n}\n\t\n\nvoid StoreAccessedRanges(UINT_PTR StartAddress, UINT_PTR EndAddress, struct PTEStruct *pageEntry)\n{\n\tif (pageEntry->A)\n\t{\t\t\n\t\tif ((AccessedList) && (AccessedList->Range.EndAddress == StartAddress - 1)) //group\n\t\t\tAccessedList->Range.EndAddress = EndAddress;\n\t\telse\n\t\t{\n\t\t\t//insert\n\t\t\tPPENTRY e;\n\t\t\te = ExAllocatePool(PagedPool, sizeof(PENTRY));\n\t\t\te->Range.StartAddress = StartAddress;\n\t\t\te->Range.EndAddress = EndAddress;\n\t\t\te->Next = AccessedList;\n\n\t\t\tAccessedList = e;\n\t\t\tAccessedListSize++;\n\t\t}\n\n\t\t\n\t}\n}\n\n\nint enumAllAccessedPages(PEPROCESS PEProcess)\n{\n#ifdef AMD64\n\tUINT_PTR MaxAddress = 0x80000000000ULL;\n#else\n\tUINT_PTR MaxAddress = 0x80000000;\n#endif\n\n\tCleanAccessedList();\n\n\tif (walkPagingLayout(PEProcess, MaxAddress, StoreAccessedRanges))\n\t{\n\t\t//DbgPrint(\"AccessedListSize=%d\\n\", AccessedListSize);\n\t\treturn AccessedListSize*sizeof(PRANGE);\n\t}\n\telse\n\t\treturn 0;\n}\n\nint getAccessedPageList(PPRANGE List, int ListSizeInBytes)\n{\n\tPPENTRY e = AccessedList;\n\tint maxcount = ListSizeInBytes / sizeof(PRANGE);\n\tint i = 0;\n\n//\tDbgPrint(\"getAccessedPageList\\n\");\n\n\twhile (e)\n\t{\n\t\tif (i >= maxcount)\n\t\t{\n\t\t\t//DbgPrint(\"%d>=%d\", i, maxcount);\n\t\t\tbreak;\n\t\t}\n\n\t\t//DbgPrint(\"i=%d  (%p -> %p)\\n\", i, e->Range.StartAddress, e->Range.EndAddress);\n\t\tList[i] = e->Range;\n\t\te = e->Next;\n\n\t\ti++;\n\t}\n\n\tCleanAccessedList();\n\n\treturn i*sizeof(PRANGE);\n}\n\n\nvoid MarkPageAsNotAccessed(UINT_PTR StartAddress, UINT_PTR EndAddress, struct PTEStruct *pageEntry)\n{\n\tpageEntry->A = 0;\n}\n\nNTSTATUS markAllPagesAsNeverAccessed(PEPROCESS PEProcess)\n{\n#ifdef AMD64\n\tUINT_PTR MaxAddress = 0x80000000000ULL;\t\n#else\n\tUINT_PTR MaxAddress = 0x80000000;\n#endif\n\n\tif (walkPagingLayout(PEProcess, MaxAddress, MarkPageAsNotAccessed))\n\t\treturn STATUS_SUCCESS;\n\telse\n\t\treturn STATUS_UNSUCCESSFUL;\n\n}\n\n\n\nUINT_PTR FindFirstDifferentAddress(QWORD address, DWORD *protection)\n//scans the pagetable system for the first fully present entry\n//returns 0 when there is no other present address\n{\n\tint i,ri;\n\tint pml4index, pagedirpointerindex, pagedirindex, pagetableindex;\n\tVirtualAddressToIndexes(address, &pml4index, &pagedirpointerindex, &pagedirindex, &pagetableindex);\n#ifndef AMD64\n\tif (PTESize == 8)\n#endif\n\t{\n\t\tPPDPTE_PAE pml4entry, pagedirpointerentry;\n\t\tPPDE_PAE pagedirentry;\n\t\tPPTE_PAE pagetableentry;\n\t\t*protection = 0;\n\n\t\t//scan till present or end of memory\n\t\twhile (1)\n\t\t{\n\t\t\tVirtualAddressToPageEntries64(address, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);\n\t\t\tVirtualAddressToIndexes(address, &pml4index, &pagedirpointerindex, &pagedirindex, &pagetableindex);\n\n\t\t\tif (*protection == 0)\n\t\t\t{\n\t\t\t\t//get the initial protection\n\t\t\t\tif ((((pml4entry) && (pml4entry->P)) || (pml4entry == NULL)) && (pagedirpointerentry->P) && (pagedirentry->P) && ((pagedirentry->PS) || (pagetableentry->P)))\n\t\t\t\t{\n\t\t\t\t\tif (pagedirentry->PS)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pagedirentry->RW)\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READWRITE;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READ;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pagetableentry->RW)\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READWRITE;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READ;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t*protection = PAGE_NOACCESS;\n\t\t\t}\n\n#ifdef AMD64\t\t\t\n\t\t\tif (pml4entry->P == 0)\n\t\t\t{\n\t\t\t\t//unreadable at PML4 level\n\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn address;\n\n\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\tpagedirindex = 0;\n\t\t\t\tpagetableindex = 0;\n\n\t\t\t\tfor (ri=1, i = pml4index + 1; i < 512; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif ((ri >= 512) || (ri < 0))\n\t\t\t\t\t\tDbgBreakPointWithStatus(ri);\n\t\t\t\t\t\t\n\t\t\t\t\tif (pml4entry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid PML4 entry\n\t\t\t\t\t\t//scan for a valid pagedirpointerentry\n\t\t\t\t\t\tpml4index = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tVirtualAddressToPageEntries64(address, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pml4entry->P == 0)\n\t\t\t{\n\t\t\t\t//nothing readable found\n\t\t\t\treturn 0;\n\t\t\t}\n#endif\t\n\n\t\t\tif (pagedirpointerentry->P == 0)\n\t\t\t{\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tpagedirindex = 0;\n\t\t\t\tpagetableindex = 0;\n\n\t\t\t\tfor (ri=1, i = pagedirpointerindex + 1; i < 512; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif ((ri >= 512) || (ri < 0))\n\t\t\t\t\t\tDbgBreakPointWithStatus(ri);\n\n\t\t\t\t\tif (pagedirpointerentry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid pagedirpointerentry\n\t\t\t\t\t\tpagedirpointerindex = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tVirtualAddressToPageEntries64(address, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pagedirpointerentry->P == 0)\n\t\t\t\t{\n#ifdef AMD64\n\t\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\t\tpml4index++;\n\t\t\t\t\tif (pml4index >= 512) return 0; //end of the list\n\n\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\tcontinue; //try the next PML4 entry\n#else\n\t\t\t\t\t//nothing readable found\n\t\t\t\t\treturn 0;\n#endif\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pagedirentry->P == 0)\n\t\t\t{\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tpagetableindex = 0;\n\t\t\t\tfor (ri=1, i = pagedirindex + 1; i < 512; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif ((ri >= 512) || (ri < 0))\n\t\t\t\t\t\tDbgBreakPointWithStatus(ri);\n\n\t\t\t\t\tif (pagedirentry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid pagedirentry\n\t\t\t\t\t\tpagedirindex = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tVirtualAddressToPageEntries64(address, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pagedirentry->P == 0)\n\t\t\t\t{\n\t\t\t\t\tpagedirindex = 0;\n\t\t\t\t\tpagedirpointerindex++;\n\t\t\t\t\tif (pagedirpointerindex >= 512)\n\t\t\t\t\t{\n\t\t\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\t\t\tpml4index++;\n\t\t\t\t\t\tif (pml4index >= 512) return 0; //end of the list\n\t\t\t\t\t}\n\n\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\tcontinue; //try the next pagedirpointer entry\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (pagedirentry->PS)\n\t\t\t{\n\t\t\t\tif (*protection == PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tif ((pagedirentry->RW) && (*protection != PAGE_EXECUTE_READWRITE))\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\t//go to the next one\n\t\t\t\tpagedirindex++;\n\t\t\t\tif (pagedirindex >= 512)\n\t\t\t\t{\n\t\t\t\t\tpagedirindex = 0;\n\t\t\t\t\tpagedirpointerindex++;\n\t\t\t\t\tif (pagedirpointerindex >= 512)\n\t\t\t\t\t{\n\t\t\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\t\t\tpml4index++;\n\t\t\t\t\t\tif (pml4index >= 512)\n\t\t\t\t\t\t\treturn 0; //end of the list\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\n\t\t\tif (pagetableentry->P == 0)\n\t\t\t{\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tfor (ri=1, i = pagetableindex + 1; i < 512; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif ((ri >= 512) || (ri < 0))\n\t\t\t\t\t\tDbgBreakPointWithStatus(ri);\n\n\t\t\t\t\tif (pagetableentry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid pagetable entry\n\t\t\t\t\t\tpagetableindex = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tVirtualAddressToPageEntries64(address, &pml4entry, &pagedirpointerentry, &pagedirentry, &pagetableentry);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pagetableentry->P == 0)\n\t\t\t\t{\n\t\t\t\t\tpagetableindex = 0;\n\t\t\t\t\tpagedirindex++;\n\t\t\t\t\tif (pagedirindex >= 512)\n\t\t\t\t\t{\n\t\t\t\t\t\tpagedirindex = 0;\n\t\t\t\t\t\tpagedirpointerindex++;\n\t\t\t\t\t\tif (pagedirpointerindex >= 512)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\t\t\t\tpml4index++;\n\t\t\t\t\t\t\tif (pml4index >= 512)\n\t\t\t\t\t\t\t\treturn 0; //end of the list\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t\t\t\tcontinue; //try the next pagedir entry\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//still here so a present page\n\t\t\tif (*protection == PAGE_NOACCESS)\n\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\tif ((pagetableentry->RW) && (*protection != PAGE_EXECUTE_READWRITE))\n\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t//next entry\n\t\t\tpagetableindex++;\n\t\t\tif (pagetableindex >= 512)\n\t\t\t{\n\t\t\t\tpagetableindex = 0;\n\t\t\t\tpagedirindex++;\n\t\t\t\tif (pagedirindex >= 512)\n\t\t\t\t{\n\t\t\t\t\tpagedirindex = 0;\n\t\t\t\t\tpagedirpointerindex++;\n\t\t\t\t\tif (pagedirpointerindex >= 512)\n\t\t\t\t\t{\n\t\t\t\t\t\tpagedirpointerindex = 0;\n\t\t\t\t\t\tpml4index++;\n\t\t\t\t\t\tif (pml4index >= 512)\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\t\t}\n\t}\n#ifndef AMD64\n\telse\n\t{\n\t\tPPDE pagedirentry;\n\t\tPPTE pagetableentry;\n\t\twhile (1)\n\t\t{\n\t\t\tVirtualAddressToPageEntries32((UINT_PTR)address, &pagedirentry, &pagetableentry);\n\t\t\tVirtualAddressToIndexes((UINT_PTR)address, &pml4index, &pagedirpointerindex, &pagedirindex, &pagetableindex);\n\n\t\t\tif (*protection == 0)\n\t\t\t{\n\t\t\t\t//get the initial protection\n\t\t\t\tif ((pagedirentry->P) && ((pagedirentry->PS) || (pagetableentry->P)))\n\t\t\t\t{\n\t\t\t\t\tif (pagedirentry->PS)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pagedirentry->RW)\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READWRITE;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READ;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tif (pagetableentry->RW)\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READWRITE;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\t*protection = PAGE_EXECUTE_READ;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\t*protection = PAGE_NOACCESS;\n\t\t\t}\n\n\t\t\tif (pagedirentry->P == 0)\n\t\t\t{\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tpagetableindex = 0;\n\t\t\t\tfor (ri=1, i = pagedirindex + 1; i < 1024; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif (pagedirentry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid pagedirentry\n\t\t\t\t\t\tpagedirindex = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(0, 0, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tVirtualAddressToPageEntries32((UINT_PTR)address, &pagedirentry, &pagetableentry);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pagedirentry->P == 0)\n\t\t\t\t\treturn 0; //end of the list\n\t\t\t}\n\n\t\t\tif (pagedirentry->PS)\n\t\t\t{\n\t\t\t\tif (*protection == PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tif ((pagedirentry->RW) && (*protection != PAGE_EXECUTE_READWRITE))\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\t//go to the next one\n\t\t\t\tpagedirindex++;\n\t\t\t\tif (pagedirindex >= 1024)\n\t\t\t\t\treturn 0;\n\t\t\t\t\n\t\t\t\taddress = IndexesToVirtualAddress(0, 0, pagedirindex, pagetableindex, 0);\n\t\t\t}\n\n\n\t\t\tif (pagetableentry->P == 0)\n\t\t\t{\n\t\t\t\tif (*protection != PAGE_NOACCESS)\n\t\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t\tfor (ri=1, i = pagetableindex + 1; i < 1024; i++, ri++)\n\t\t\t\t{\n\t\t\t\t\tif (pagetableentry[ri].P)\n\t\t\t\t\t{\n\t\t\t\t\t\t//found a valid pagetable entry\n\t\t\t\t\t\tpagetableindex = i;\n\t\t\t\t\t\taddress = IndexesToVirtualAddress(0, 0, pagedirindex, pagetableindex, 0);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (pagetableentry->P == 0)\n\t\t\t\t{\n\t\t\t\t\tpagetableindex = 0;\n\t\t\t\t\tpagedirindex++;\n\t\t\t\t\tif (pagedirindex >= 1024)\n\t\t\t\t\t\treturn 0;\n\n\t\t\t\t\taddress = IndexesToVirtualAddress(0, 0, pagedirindex, pagetableindex, 0);\n\t\t\t\t\tcontinue; //try the next pagedir entry\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//still here so a present page\n\t\t\tif (*protection == PAGE_NOACCESS)\n\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\tif ((pagetableentry->RW) && (*protection != PAGE_EXECUTE_READWRITE))\n\t\t\t\treturn (UINT_PTR)address;\n\n\t\t\t//next entry\n\t\t\tpagetableindex++;\n\t\t\tif (pagetableindex >= 1024)\n\t\t\t{\n\t\t\t\tpagetableindex = 0;\n\t\t\t\tpagedirindex++;\n\t\t\t\tif (pagedirindex >= 1024)\n\t\t\t\t\treturn 0;\t\t\t\t\n\t\t\t}\n\t\t\taddress = IndexesToVirtualAddress(pml4index, pagedirpointerindex, pagedirindex, pagetableindex, 0);\n\n\t\t}\n\n\t}\n#endif\t\n}\n\n\nBOOLEAN GetMemoryRegionData(DWORD PID,PEPROCESS PEProcess, PVOID mempointer,ULONG *regiontype, UINT_PTR *memorysize,UINT_PTR *baseaddress)\n{\n\tUINT_PTR CurrentAddress;\n\tKAPC_STATE apc_state;\n\tPEPROCESS selectedprocess=PEProcess;\n\n\tif (getPageTableBase() == 0)\n\t{\n\t\tDbgPrint(\"GetMemoryRegionData failed because pagebase == 0\");\n\t\treturn FALSE;\n\t}\n\n\tif (PEProcess==NULL)\n\t{\n        if (!NT_SUCCESS(PsLookupProcessByProcessId((PVOID)(UINT_PTR)PID,&selectedprocess)))\n\t\t   return FALSE; //couldn't get the PID\n\t}\n\n\t*baseaddress=(UINT_PTR)mempointer & (UINT_PTR)(~0xfff);\n\t*memorysize=0;\n\t*regiontype=0;\n\t//switch context to the target process\n\n\tRtlZeroMemory(&apc_state,sizeof(apc_state));\n\n\t__try\n\t{\n\t\tKeAttachProcess((PEPROCESS)selectedprocess);\n\t\t__try\n\t\t{\n\t\t\tCurrentAddress=FindFirstDifferentAddress(*baseaddress, regiontype);\n\t\t\t*memorysize = CurrentAddress-*baseaddress;\t\t\t\n\t\t}\n\t\t__finally\n\t\t{\n\t\t\tKeDetachProcess();\n\t\t\tif (PEProcess==NULL) //no valid peprocess was given so I made a reference, so lets also dereference\n\t\t\t\tObDereferenceObject(selectedprocess);\n\t\t}\n\t}\n\t__except(1)\n\t{\n\t\tDbgPrint(\"Exception in GetMemoryRegionData\\n\");\n\t\tDbgPrint(\"mempointer=%p\",mempointer);\n\t}\n\n\treturn 0; \n}"
  },
  {
    "path": "src/memscan.h",
    "content": "#include <windef.h>\n\n#ifdef AMD64\n#define PAGETABLEBASE 0xfffff68000000000ULL\n//win10 1607 it's random\n#else\n#define PAGETABLEBASE 0xc0000000\n#endif\n\ntypedef struct _ADDRESSENTRY {\nDWORD Address;\nBYTE  size;\nBOOLEAN frozen;\nPVOID frozendata;\n} ADDRESSENTRY;\n\ntypedef struct _MEMREGION //only holds regions that are allowed\n{\n\tDWORD BaseAddress;\n\tDWORD Size;\n} MEMREGION;\n\n\ntypedef struct _MEMSCANOPTIONS\n{\nBYTE ShowAsSigned; //obsolete (clientside now)\nBYTE BinariesAsDecimal; //obsolete (clientside now)\nWORD max;\nDWORD buffersize;\nBYTE skip_page_no_cache; //hmmmm\nBYTE UseDebugRegs;\nBYTE UseDBKQueryMemoryRegion; //always true\nBYTE UseDBKReadWriteMemory; //always true\nBYTE UseDBKOpenProcess; //always true\n} MEMSCANOPTIONS;\nMEMSCANOPTIONS MemscanOptions;\n\ntypedef struct _SCANDATA {\nPEPROCESS process;\nDWORD Start;\nDWORD Stop;\nBYTE Vartype;\nBYTE Scantype;\nBYTE ScanOptions;\nBYTE scanvaluelength;\nchar *scanvalue;\nBOOLEAN scanning;\nBOOLEAN ThreadActive;\n} SCANDATA;\n\nSCANDATA CurrentScan;\n\t\t\t\t\t  \ntypedef struct\n{\n\tUINT64 StartAddress;\n\tUINT64 EndAddress;\n} PRANGE, *PPRANGE;\n\ntypedef struct\n{\n\tPRANGE Range;\n\tvoid *Next;\n} PENTRY, *PPENTRY;\n\n#ifdef CETC\nBOOLEAN FirstScan(PEPROCESS ActivePEPROCESS, DWORD start,DWORD stop,BYTE vartype,BYTE scantype,BYTE scanvaluesize,char *scanvalue,BYTE ScanOptions);\n#endif\n\nNTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, void *output);\nBOOLEAN ReadProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer);\nBOOLEAN WriteProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DWORD Size, PVOID Buffer);\nBOOLEAN IsAddressSafe(UINT_PTR StartAddress);\nBOOLEAN GetMemoryRegionData(DWORD PID,PEPROCESS PEProcess, PVOID mempointer,ULONG *regiontype, UINT_PTR *memorysize,UINT_PTR *baseaddress);\nNTSTATUS markAllPagesAsNeverAccessed(PEPROCESS PEProcess);\nint enumAllAccessedPages(PEPROCESS PEProcess);\nint getAccessedPageList(PPRANGE List, int ListSizeInBytes);\n\nUINT_PTR getPageTableBase();\n\nUINT_PTR getPEThread(UINT_PTR threadid);\n\nADDRESSENTRY *AddressList;\nunsigned int AddressListSize;\nunsigned int AddressListEntries;\nKSPIN_LOCK AddressListSpinlock;\n\nPVOID FrozenData; //holds the buffer of all frozen data records\nint FrozenDataSize;\nLARGE_INTEGER FreezeInterval;\nHANDLE addressfile;\nHANDLE valuefile;\n\nBOOLEAN HiddenDriver;\n\n\n//scanoptions\n#define SO_FASTSCAN\t\t(0x1)\n#define SO_HEXADECIMAL\t(0x2)\n#define SO_READONLY\t\t(0x4)\n#define SO_FINDONLYONE\t(0x8)\n#define SO_ISBINARY\t\t(0x10)\n#define SO_UNICODE\t\t(0x20)\n\n//scantype\n#define  ST_Exact_value\t\t\t0\n#define  ST_Increased_value\t\t1\n#define  ST_Increased_value_by\t2\n#define  ST_Decreased_value\t\t3\n#define  ST_Decreased_value_by\t4\n#define  ST_Changed_value\t\t5\n#define  ST_Unchanged_value\t\t6\n#define  ST_Advanced_Scan\t\t7\n#define  ST_String_Scan\t\t\t8\n#define  ST_SmallerThan\t\t\t9\n#define  ST_BiggerThan\t\t\t10\n#define  ST_Userdefined\t\t\t11\n\n//scanerrors\n#define SE_IncorrectType -1\n#define SE_NotSupported -2\n#define SE_NoMemoryFound -3"
  },
  {
    "path": "src/noexceptions.c",
    "content": "#include \"noexceptions.h\"\n\nint MaxCPUCount;\n\n\nPCPUSTATE cpustate = NULL;\n\n#ifdef AMD64\nextern void NoException14(void); //declared in debuggera.asm\nextern int ExceptionlessCopy_Internal(PVOID destination, PVOID source, int size);\n#else\nextern void __cdecl NoException14(void); //declared in debuggera.asm\nextern int __cdecl ExceptionlessCopy_Internal(PVOID destination, PVOID source, int size);\n#endif\n\n#if (NTDDI_VERSION < NTDDI_VISTA)\nint KeQueryActiveProcessorCount(PVOID x)\n{\n\tint cpucount=0;\n\tKAFFINITY cpus = KeQueryActiveProcessors();\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t\tcpucount++;\n\n\t\tcpus = cpus / 2;\n\t}\n\n\treturn cpucount;\n}\n#endif\n\n\nBOOL NoExceptions_Enter()\n{\n\tKIRQL old;\n\tint i;\n\tint cpunr;\n\n\t//DbgPrint(\"NoExceptions_Enter\");\n\n\t__try\n\t{\n\t\tif (cpustate == NULL)\n\t\t{\n\t\t\t//initialize the list\n\t\t\tMaxCPUCount = (int)KeQueryActiveProcessorCount(NULL);\n\t\t\tcpustate = ExAllocatePool(NonPagedPool, MaxCPUCount*sizeof(CPUSTATE));\n\n\t\t\tif (cpustate)\n\t\t\t{\n\t\t\t\tRtlZeroMemory(cpustate, MaxCPUCount*sizeof(CPUSTATE));\n\t\t\t\tfor (i = 0; i < MaxCPUCount; i++)\n\t\t\t\t{\n\t\t\t\t\tcpustate[i].NoExceptionVectorList = ExAllocatePool(NonPagedPool, 256 * sizeof(INT_VECTOR));\n\t\t\t\t\tif (cpustate[i].NoExceptionVectorList)\n\t\t\t\t\t{\n\t\t\t\t\t\tRtlZeroMemory(cpustate[i].NoExceptionVectorList, 256 * sizeof(INT_VECTOR));\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//alloc failed, cleanup and quit\n\t\t\t\t\t\tint j;\n\t\t\t\t\t\tfor (j = i - 1; j >= 0; j--)\n\t\t\t\t\t\t\tExFreePool(cpustate[j].NoExceptionVectorList);\n\n\t\t\t\t\t\tcpustate = NULL;\n\t\t\t\t\t\treturn FALSE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t\treturn FALSE;\n\t\t}\n\n\t\t//DbgPrint(\"cpustate setup here\");\n\n\t\tKeRaiseIrql(HIGH_LEVEL, &old);\n\t\tcpunr = KeGetCurrentProcessorNumber();\n\n\t\tcpustate[cpunr].entryIRQL = old;\n\n\t\t\n\n\t\t\n\n\t\tif (cpustate[cpunr].OriginalIDT.wLimit == 0)\n\t\t{\n\t\t\t//initialize this\n\n\t\t\tUINT_PTR newAddress;\n\t\t\t__sidt(&cpustate[cpunr].OriginalIDT);\n\t\t\t\n\t\t\tRtlCopyMemory(cpustate[cpunr].NoExceptionVectorList, cpustate[cpunr].OriginalIDT.vector, cpustate[cpunr].OriginalIDT.wLimit + 1);\t\t\t\t\n\n\t\t\t//DbgPrint(\"idt. Limit=%d Vector=%p\", (int)cpustate[cpunr].OriginalIDT.wLimit, cpustate[cpunr].OriginalIDT.vector);\n\n\t\t\t//hook cpustate[cpunr].NoExceptionVectorList[0-15]\n\t\t\t//DbgPrint(\"\")\n\n\t\t\tnewAddress = (UINT_PTR)NoException14;\n\n\t\t\tcpustate[cpunr].NoExceptionVectorList[14].wHighOffset = (WORD)((DWORD)(newAddress >> 16));\n\t\t\tcpustate[cpunr].NoExceptionVectorList[14].wLowOffset = (WORD)newAddress;\n\n#ifdef AMD64\n\t\t\tcpustate[cpunr].NoExceptionVectorList[14].TopOffset = (newAddress >> 32);\n\t\t\tcpustate[cpunr].NoExceptionVectorList[14].Reserved = 0;\n#endif\n\n\n\t\t\t\t/*\n\t\t\t\tnewVector.wHighOffset=(WORD)((DWORD)(newEIP >> 16));\n\t\t\t\tnewVector.wLowOffset=(WORD)newEIP;\n\t\t\t\tnewVector.wSelector=(WORD)newCS;\n\t\t\t\tnewVector.bUnused=0;\n\t\t\t\tnewVector.bAccessFlags=idt.vector[intnr].bAccessFlags; //don't touch accessflag, the default settings are good (e.g: int3,4 and 8 have dpl=3)\n\n\t\t\t\t#ifdef AMD64\n\t\t\t\tnewVector.TopOffset=(newEIP >> 32);\n\t\t\t\tnewVector.Reserved=0;\n\t\t\t\t#endif\n\t\t\t\t*/\n\n\n\t\t\tcpustate[cpunr].ModdedIDT = cpustate[cpunr].OriginalIDT;\n\t\t\tcpustate[cpunr].ModdedIDT.vector = cpustate[cpunr].NoExceptionVectorList;\n\t\t\t\n\n\t\t\t\n\t\t};\n\n#ifdef AMD64\n\t\t_disable();\n#else\n\t\t__asm{\n\t\t\tcli\n\t\t}\n#endif\n\t\t__lidt(&cpustate[cpunr].ModdedIDT);\n\t\n\n\t\t\n\t\treturn TRUE;\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"Exception during NoExceptions_Enter. Figures\");\n\t}\n\n\t\n\t//KeGetCurrentProcessorNumber()\n\t//hadError = FALSE;\n\n\treturn FALSE;\n}\n\nint NoExceptions_CopyMemory(PVOID Destination, PVOID Source, int size)\n{\n\tBOOL EnteredNoExceptions = FALSE;\n\tint r;\n\t\n\tif (KeGetCurrentIrql() <= DISPATCH_LEVEL)\n\t{\n\t\t//DbgPrint(\"calling NoExceptions_Enter\");\n\t\tEnteredNoExceptions = NoExceptions_Enter();\n\t\tif (EnteredNoExceptions == FALSE)\n\t\t\treturn 0;\n\t}\n\t\n\tr = ExceptionlessCopy_Internal(Destination, Source, size);\n\n\t\n\t\n\tif (EnteredNoExceptions)\n\t{\n\t\t//DbgPrint(\"calling NoExceptions_Leave\");\n\t\tNoExceptions_Leave();\n\t}\n\n\n\treturn r;\n}\n\nvoid NoExceptions_Leave()\n{\n\t\n\tint cpunr = KeGetCurrentProcessorNumber();\n\n\t//restore the IDT\n\t__lidt(&cpustate[cpunr].OriginalIDT);\n#ifdef AMD64\t\n\t_enable();\n#else\n\t__asm{\n\t\tsti\n\t}\n#endif\n\tKeLowerIrql(cpustate[cpunr].entryIRQL);\n}\n\nvoid NoExceptions_Cleanup()\n{\n\tif (cpustate)\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < MaxCPUCount; i++)\n\t\t{\n\t\t\tif (cpustate[i].NoExceptionVectorList)\n\t\t\t{\n\t\t\t\tExFreePool(cpustate[i].NoExceptionVectorList);\n\t\t\t\tcpustate[i].NoExceptionVectorList = NULL;\n\t\t\t}\n\t\t}\n\n\t\tExFreePool(cpustate);\n\t}\n\t\t\n\n}\n\n\n\n"
  },
  {
    "path": "src/noexceptions.h",
    "content": "#ifndef NOEXCEPTIONS_H\n#define NOEXCEPTIONS_H\n\n/*\nWill be responsible for temporarily switching out the IDT of the curent CPU with one that doesn't call windows functions on errors\n*/\n#include <ntifs.h>\n#include <wdm.h>\n#include <windef.h>\n\n#include \"interruptHook.h\"\n#include \"dbkfunc.h\"\n\n\ntypedef struct\n{\n\tKIRQL entryIRQL;\n\tPINT_VECTOR NoExceptionVectorList; //list pointing to an idt table with hooked ints\n\tIDT OriginalIDT;\t\n\tIDT ModdedIDT;\n} CPUSTATE, *PCPUSTATE;\n\nBOOL NoExceptions_Enter();\nint  NoExceptions_CopyMemory(PVOID Destination, PVOID Source, int size);\nvoid NoExceptions_Leave();\n\nvoid NoExceptions_Cleanup();\n\nvoid NoException14_ErrorHandler();\n\n#endif\n"
  },
  {
    "path": "src/processlist.c",
    "content": "#pragma warning( disable: 4100 4103 4706)\n\n#include \"ntifs.h\"\n#include \"processlist.h\"\n#include \"threads.h\"\n#include \"memscan.h\"\n\n#include \"ultimap2.h\"\n\nPRTL_GENERIC_TABLE InternalProcessList = NULL;\n\nPEPROCESS WatcherProcess = NULL;\nBOOLEAN ProcessWatcherOpensHandles = TRUE;\n\n\n\nRTL_GENERIC_COMPARE_RESULTS NTAPI ProcessListCompare(__in struct _RTL_GENERIC_TABLE *Table, __in PProcessListData FirstStruct, __in PProcessListData SecondStruct)\n{\n\t//DbgPrint(\"ProcessListCompate\");\n\n\tif (FirstStruct->ProcessID  == SecondStruct->ProcessID)\n\t\treturn GenericEqual;\n\telse\n\t{\n\t\tif (SecondStruct->ProcessID < FirstStruct->ProcessID)\n\t\t\treturn GenericLessThan;\n\t\telse\n\t\t\treturn GenericGreaterThan;\n\t}\n}\n\nPVOID NTAPI ProcessListAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in CLONG ByteSize)\n{\n\tPVOID r=ExAllocatePool(PagedPool, ByteSize);\n\tRtlZeroMemory(r, ByteSize);\n\n\t//DbgPrint(\"ProcessListAlloc %d\",(int)ByteSize);\n\treturn r;\n}\n\nVOID NTAPI ProcessListDealloc(__in struct _RTL_GENERIC_TABLE *Table, __in __drv_freesMem(Mem) __post_invalid PVOID Buffer)\n{\n\t//DbgPrint(\"ProcessListDealloc\");\n\tExFreePool(Buffer);\n}\n\n\nVOID GetThreadData(IN PDEVICE_OBJECT  DeviceObject, IN PVOID  Context)\n{\n\tstruct ThreadData *tempThreadEntry;\n\tPETHREAD selectedthread;\n\tHANDLE tid;\n\tLARGE_INTEGER Timeout;\n\tPKAPC AP;\n\ttempThreadEntry=Context;\n\t\n\n\tDbgPrint(\"Gathering PEThread thread\\n\");\n\n\tTimeout.QuadPart = -1;\n\tKeDelayExecutionThread(KernelMode, TRUE, &Timeout);\n\n\tselectedthread=NULL;\n\n\tif (ExAcquireResourceSharedLite(&ProcesslistR, TRUE))\n\t{\n\n\t\ttid = tempThreadEntry->ThreadID;\n\t\tAP = &tempThreadEntry->SuspendApc;\n\t\tPsLookupThreadByThreadId((PVOID)tid, &selectedthread);\n\n\t\tif (selectedthread)\n\t\t{\n\t\t\tDbgPrint(\"PEThread=%p\\n\", selectedthread);\n\t\t\tKeInitializeApc(AP,\n\t\t\t\t(PKTHREAD)selectedthread,\n\t\t\t\t0,\n\t\t\t\t(PKKERNEL_ROUTINE)Ignore,\n\t\t\t\t(PKRUNDOWN_ROUTINE)NULL,\n\t\t\t\t(PKNORMAL_ROUTINE)SuspendThreadAPCRoutine,\n\t\t\t\tKernelMode,\n\t\t\t\tNULL);\n\n\t\t\tObDereferenceObject(selectedthread);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Failed getting the pethread.\\n\");\n\t\t}\n\t}\n\tExReleaseResourceLite(&ProcesslistR);\n}\n\nVOID CreateThreadNotifyRoutine(IN HANDLE  ProcessId,IN HANDLE  ThreadId,IN BOOLEAN  Create)\n{\n\tif (KeGetCurrentIrql()==PASSIVE_LEVEL)\n\t{\n\t\t/*if (DebuggedProcessID==(ULONG)ProcessId)\n\t\t{\n\t\t//\tPsSetContextThread (bah, xp only)\n\t\t}*/\n\n\t\tif (ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE))\n\t\t{\n\t\t\tif (ThreadEventCount < 50)\n\t\t\t{\n\t\t\t\tThreadEventData[ThreadEventCount].Created = Create;\n\t\t\t\tThreadEventData[ThreadEventCount].ProcessID = (UINT_PTR)ProcessId;\n\t\t\t\tThreadEventData[ThreadEventCount].ThreadID = (UINT_PTR)ThreadId;\n\n\t\t\t\t/*\tif (Create)\n\t\t\t\t\t\tDbgPrint(\"Create ProcessID=%x\\nThreadID=%x\\n\",(UINT_PTR)ProcessId,(UINT_PTR)ThreadId);\n\t\t\t\t\t\telse\n\t\t\t\t\t\tDbgPrint(\"Destroy ProcessID=%x\\nThreadID=%x\\n\",(UINT_PTR)ProcessId,(UINT_PTR)ThreadId);\n\t\t\t\t\t\t*/\n\n\t\t\t\tThreadEventCount++;\n\t\t\t}\n\t\t}\n\t\tExReleaseResourceLite(&ProcesslistR);\n\n\t\tKeSetEvent(ThreadEvent, 0, FALSE);\n\t\tKeClearEvent(ThreadEvent);\n\t}\n}\n\nVOID CreateProcessNotifyRoutine(IN HANDLE  ParentId, IN HANDLE  ProcessId, IN BOOLEAN  Create)\n{\n\tPEPROCESS CurrentProcess = NULL;\n\tHANDLE ProcessHandle = 0;\n\t/*\n\tif (PsSuspendProcess)\n\t{\n\t\tDbgPrint(\"Suspending process %d\", PsGetCurrentThreadId());\n\t\tPsSuspendProcess(PsGetCurrentProcess());\n\t\tDbgPrint(\"After PsGetCurrentProcess()\");\n\t}\n*/\n\t\n\t\n\tif (KeGetCurrentIrql()==PASSIVE_LEVEL)\n\t{\n\t\tstruct ProcessData *tempProcessEntry;\n\n\t\t//aquire a spinlock\n\t\tif (ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE))\n\t\t{\n\n\t\t\tif (PsLookupProcessByProcessId((PVOID)ProcessId, &CurrentProcess) != STATUS_SUCCESS)\n\t\t\t{\n\t\t\t\tExReleaseResourceLite(&ProcesslistR);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ((ProcessWatcherOpensHandles) && (WatcherProcess))\n\t\t\t{\n\t\t\t\t\n\t\t\t\t\n\t\t\t\tif (Create)\n\t\t\t\t{\n\t\t\t\t\t//Open a handle to this process\n\n\t\t\t\t\t/*\n\t\t\t\t\t\t\n\t\t\t\t\tHANDLE ph = 0;\n\t\t\t\t\tNTSTATUS r = ObOpenObjectByPointer(CurrentProcess, 0, NULL, PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, &ph);\n\n\t\t\t\t\tDbgPrint(\"CreateProcessNotifyRoutine: ObOpenObjectByPointer=%x  ph=%x\", r, ph);\n\t\t\t\t\tr = ZwDuplicateObject(ZwCurrentProcess(), ph, WatcherHandle, &ProcessHandle, PROCESS_ALL_ACCESS, 0, DUPLICATE_CLOSE_SOURCE);\n\n\t\t\t\t\tDbgPrint(\"CreateProcessNotifyRoutine: ZwDuplicateObject=%x (handle=%x)\", r, ProcessHandle);\n\t\t\t\t\t*/\n\t\t\t\t\t\t\n\t\t\t\t\tKAPC_STATE oldstate;\n\n\t\t\t\t\t\t\n\t\t\t\t\tKeStackAttachProcess((PKPROCESS)WatcherProcess, &oldstate);\t\t\t\t\t\t\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\t\t\t\t\t\t__try\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tObOpenObjectByPointer(CurrentProcess, 0, NULL, PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, &ProcessHandle);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t__except (1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Exception during ObOpenObjectByPointer\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t__finally\n\t\t\t\t\t{\n\t\t\t\t\t\tKeUnstackDetachProcess(&oldstate);\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\n\t\t\t\tif (InternalProcessList == NULL)\n\t\t\t\t{\n\t\t\t\t\tInternalProcessList = ExAllocatePool(PagedPool, sizeof(RTL_GENERIC_TABLE));\n\t\t\t\t\tif (InternalProcessList)\n\t\t\t\t\t\tRtlInitializeGenericTable(InternalProcessList, ProcessListCompare, ProcessListAlloc, ProcessListDealloc, NULL);\n\t\t\t\t}\n\n\t\t\t\tif (InternalProcessList)\n\t\t\t\t{\n\t\t\t\t\tProcessListData d, *r;\n\n\t\t\t\t\td.ProcessID = ProcessId;\n\t\t\t\t\td.PEProcess = CurrentProcess;\n\t\t\t\t\td.ProcessHandle = ProcessHandle;\n\n\t\t\t\t\tr = RtlLookupElementGenericTable(InternalProcessList, &d);\n\n\t\t\t\t\tif (Create)\n\t\t\t\t\t{\n\t\t\t\t\t\t//add it to the list\n\t\t\t\t\t\tBOOLEAN newElement = FALSE;\n\t\t\t\t\t\tif (r) //weird\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Duplicate PID detected...\");\n\t\t\t\t\t\t\tRtlDeleteElementGenericTable(InternalProcessList, r);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tr = RtlInsertElementGenericTable(InternalProcessList, &d, sizeof(d), &newElement);\n\n\n\t\t\t\t\t\tDbgPrint(\"Added handle %x for pid %d to the list (newElement=%d r=%p)\", (int)(UINT_PTR)d.ProcessHandle, (int)(UINT_PTR)d.ProcessID, newElement, r);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//remove it from the list (if it's there)\n\t\t\t\t\t\tDbgPrint(\"Process %d destruction. r=%p\", (int)(UINT_PTR)d.ProcessID, r);\n\t\t\t\t\t\tif (r)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"Process that was in the list has been closed\");\n\t\t\t\t\t\t\t//if (r->ProcessHandle)\n\t\t\t\t\t\t\t//\tZwClose(r->ProcessHandle);\n\n\t\t\t\t\t\t\t//RtlDeleteElementGenericTable(InternalProcessList, r);\n\t\t\t\t\t\t\tr->Deleted = 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (CurrentProcess == WatcherProcess)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"CE Closed\");\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t//ZwClose(WatcherHandle);\n\n\t\t\t\t\t\t\tCleanProcessList(); //CE closed\n\t\t\t\t\t\t\tWatcherProcess = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\n\t\t\t//fill in a processcreateblock with data\n\t\t\tif (ProcessEventCount < 50)\n\t\t\t{\n\t\t\t\tProcessEventdata[ProcessEventCount].Created = Create;\n\t\t\t\tProcessEventdata[ProcessEventCount].ProcessID = (UINT_PTR)ProcessId;\n\t\t\t\tProcessEventdata[ProcessEventCount].PEProcess = (UINT_PTR)CurrentProcess;\n\t\t\t\tProcessEventCount++;\n\t\t\t}\n\n\t\t\t//if (!HiddenDriver)\n\t\t\tif (FALSE) //moved till next version\n\t\t\t{\n\t\t\t\tif (Create)\n\t\t\t\t{\n\n\t\t\t\t\t//allocate a block of memory for the processlist\n\n\t\t\t\t\ttempProcessEntry = ExAllocatePool(PagedPool, sizeof(struct ProcessData));\n\t\t\t\t\ttempProcessEntry->ProcessID = ProcessId;\n\t\t\t\t\ttempProcessEntry->PEProcess = CurrentProcess;\n\t\t\t\t\ttempProcessEntry->Threads = NULL;\n\n\t\t\t\t\tDbgPrint(\"Allocated a process at:%p\\n\", tempProcessEntry);\n\n\t\t\t\t\tif (!processlist)\n\t\t\t\t\t{\n\t\t\t\t\t\tprocesslist = tempProcessEntry;\n\t\t\t\t\t\tprocesslist->next = NULL;\n\t\t\t\t\t\tprocesslist->previous = NULL;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\ttempProcessEntry->next = processlist;\n\t\t\t\t\t\ttempProcessEntry->previous = NULL;\n\t\t\t\t\t\tprocesslist->previous = tempProcessEntry;\n\t\t\t\t\t\tprocesslist = tempProcessEntry;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t//find this process and delete it\n\t\t\t\t\ttempProcessEntry = processlist;\n\t\t\t\t\twhile (tempProcessEntry)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (tempProcessEntry->ProcessID == ProcessId)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tint i;\n\t\t\t\t\t\t\tif (tempProcessEntry->next)\n\t\t\t\t\t\t\t\ttempProcessEntry->next->previous = tempProcessEntry->previous;\n\n\t\t\t\t\t\t\tif (tempProcessEntry->previous)\n\t\t\t\t\t\t\t\ttempProcessEntry->previous->next = tempProcessEntry->next;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tprocesslist = tempProcessEntry->next;\t//it had no previous entry, so it's the root\n\n\n\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tif (tempProcessEntry->Threads)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstruct ThreadData *tempthread,*tempthread2;\n\t\t\t\t\t\t\tKIRQL OldIrql2;\n\n\t\t\t\t\t\t\ttempthread=tempProcessEntry->Threads;\n\t\t\t\t\t\t\ttempthread2=tempthread;\n\n\t\t\t\t\t\t\tDbgPrint(\"Process ended. Freeing threads\\n\");\n\n\t\t\t\t\t\t\twhile (tempthread)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttempthread=tempthread->next;\n\t\t\t\t\t\t\tDbgPrint(\"Free thread %p (next thread=%p)\\n\",tempthread2,tempthread);\n\t\t\t\t\t\t\tExFreePool(tempthread2);\n\t\t\t\t\t\t\ttempthread2=tempthread;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t\tExFreePool(tempProcessEntry);*/\n\n\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\t\ttempProcessEntry = processlist;\n\t\t\t\t\t\t\twhile (tempProcessEntry)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\t\ttempProcessEntry = tempProcessEntry->next;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tDbgPrint(\"There are %d processes in the list\\n\", i);\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttempProcessEntry = tempProcessEntry->next;\n\t\t\t\t\t}\n\n\n\t\t\t\t}\n\n\t\t\t}\n\t\t}\n\t\tExReleaseResourceLite(&ProcesslistR);\n\n\t\tif (CurrentProcess!=NULL)\n\t\t\tObDereferenceObject(CurrentProcess);\n\n\t\t//signal process event (if there's one waiting for a signal)\n\t\tif (ProcessEvent)\n\t\t{\n\t\t\tKeSetEvent(ProcessEvent, 0, FALSE);\n\t\t\tKeClearEvent(ProcessEvent);\n\t\t}\n\t}\n}\n\nVOID CreateProcessNotifyRoutineEx(IN HANDLE  ParentId, IN HANDLE  ProcessId, __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo)\n{\n\tDbgPrint(\"CreateProcessNotifyRoutineEx\");\n\tCreateProcessNotifyRoutine(ParentId, ProcessId, CreateInfo!=NULL);\n}\n\nHANDLE GetHandleForProcessID(IN HANDLE ProcessID)\n{\n\tif (InternalProcessList)\n\t{\n\t\tProcessListData d, *r;\n\n\t\td.ProcessID = ProcessID;\n\t\tr = RtlLookupElementGenericTable(InternalProcessList, &d);\n\t\tif (r)\n\t\t{\n\t\t\tDbgPrint(\"Found a handle for PID %d (%x)\", (int)(UINT_PTR)ProcessID, (int)(UINT_PTR)r->ProcessHandle);\n\t\t\treturn r->ProcessHandle; // r->ProcessHandle;\n\t\t}\t\n\t}\t\n\n\treturn 0;\n}\n\nVOID CleanProcessList()\n{\n\tif (InternalProcessList)\n\t{\n\t\tPProcessListData li;\n\n\t\tif (ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE))\n\t\t{\n\t\t\tKAPC_STATE oldstate;\n\t\t\tBOOLEAN ChangedContext;\n\n\t\t\tif ((WatcherProcess) && (WatcherProcess != PsGetCurrentProcess()))\n\t\t\t{\t\t\t\t\n\t\t\t\tKeStackAttachProcess((PKPROCESS)WatcherProcess, &oldstate);\n\t\t\t\tChangedContext = TRUE;\n\t\t\t}\n\n\t\t\twhile (li = RtlGetElementGenericTable(InternalProcessList, 0))\n\t\t\t{\n\t\t\t\tif ((li->ProcessHandle) && (WatcherProcess))\n\t\t\t\t\tZwClose(li->ProcessHandle);\n\n\t\t\t\tRtlDeleteElementGenericTable(InternalProcessList, li);\n\t\t\t}\n\t\t\t\n\t\t\tExFreePool(InternalProcessList);\n\t\t\tInternalProcessList = NULL;\n\t\t}\n\t\tExReleaseResourceLite(&ProcesslistR);\n\t}\n\n}"
  },
  {
    "path": "src/processlist.h",
    "content": "#include <ntifs.h>\n#include \"extradefines.h\"\n#include \"extraimports.h\"\n\n\nVOID CreateProcessNotifyRoutine(IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create);\nVOID CreateProcessNotifyRoutineEx(IN HANDLE  ParentId, IN HANDLE  ProcessId, __in_opt PPS_CREATE_NOTIFY_INFO CreateInfo);\n\nstruct ThreadData\n{\n\tHANDLE ThreadID;\n\tPETHREAD PEThread;\n\tKAPC SuspendApc;\n\tKSEMAPHORE SuspendSemaphore; //why not mutex?\n\tint suspendcount;\n\tstruct ThreadData *previous;\n\tstruct ThreadData *next;\n};\n\ntypedef struct\n{\n\tHANDLE ProcessID;\n\tPEPROCESS PEProcess;\n\tHANDLE ProcessHandle;\n\tBOOLEAN Deleted;\n} ProcessListData, *PProcessListData;\n\n\nstruct ProcessData\n{\n    HANDLE ProcessID;\n\tPEPROCESS PEProcess;\n\tstruct ThreadData *Threads;\n\tstruct ProcessData *previous;\n\tstruct ProcessData *next;\n} *processlist;\n\ntypedef struct tagProcessEventData\n{\nUINT64 Created;\nUINT64 ProcessID;\nUINT64 PEProcess;\n} ProcessEventdta;\nProcessEventdta ProcessEventdata[50];\nUCHAR ProcessEventCount;\nPKEVENT ProcessEvent;\n//HANDLE  ProcessEventHandle;\n\nBOOLEAN CreateProcessNotifyRoutineEnabled;\nERESOURCE ProcesslistR;\n\n\nVOID CreateThreadNotifyRoutine(IN HANDLE ProcessId, IN HANDLE ThreadId, IN BOOLEAN Create);\ntypedef struct tagThreadEventData\n{\nBOOLEAN Created;\nUINT64 ProcessID;\nUINT64 ThreadID;\n} ThreadEventDta;\nThreadEventDta ThreadEventData[50];\nUCHAR ThreadEventCount;\nPKEVENT ThreadEvent;\n//HANDLE  ThreadEventHandle;\n\nextern HANDLE WatcherHandle;\nextern PEPROCESS WatcherProcess;\nextern BOOLEAN ProcessWatcherOpensHandles;\n\nBOOLEAN CreateThreadNotifyRoutineEnabled;\nVOID CleanProcessList();\nHANDLE GetHandleForProcessID(IN HANDLE ProcessID);"
  },
  {
    "path": "src/segmentinfo.asm",
    "content": "_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  mov ecx,[ebp+8] ;0=old ebp, 4=return address, 8=param1\n  lar eax,ecx\n  jnz getAccessRights_invalid\n\n  shr eax,8\n  and eax,0f0ffh\n\n  jmp getAccessRights_exit\n\n  \n  getAccessRights_invalid:\n  mov eax,010000h\n\ngetAccessRights_exit:\n  pop ecx\n  pop ebp\n  ret\n\nPUBLIC _getSegmentLimit@8\t\t\t\t\t\t\t\t\t\t\n_getSegmentLimit@8:\n  push ebp\n  mov ebp,esp  \n  push ecx\n\n  mov ecx,[ebp+8]\n  xor eax,eax\n  lsl eax,ecx\n\n  pop ecx\n  pop ebp\n  ret\n\n_TEXT   ENDS\n        END\n\n"
  },
  {
    "path": "src/threads.c",
    "content": "#pragma warning( disable: 4100 4103)\n\n#include \"threads.h\"\n#include \"processlist.h\"\n#include \"memscan.h\"\n\n/*\nNTSTATUS NTAPI PsGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode);\nNTSTATUS NTAPI PsSetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext, IN KPROCESSOR_MODE PreviousMode);\n\nNTSTATUS NTAPI DBKGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext)\n{\n\treturn PsGetContextThread(Thread, ThreadContext, KernelMode);\n}*/\n\nstruct ThreadData* GetThreaddata(ULONG threadid)\n{\n\tstruct ProcessData *tempProcessData;\n\tstruct ThreadData *tempThreadData;\n\n\t//PRE: Lock the list before calling this routine\n\ttempProcessData=processlist;\n\twhile (tempProcessData)\n\t{\n\t\ttempThreadData=tempProcessData->Threads;\n\t\twhile (tempThreadData)\n\t\t{\n\t\t\tif (tempThreadData->ThreadID==(HANDLE)(UINT_PTR)threadid)\n\t\t\t\treturn tempThreadData;\n\t\t\t\n\t\t\ttempThreadData=tempThreadData->next;\n\t\t}\n        \n\t\ttempProcessData=tempProcessData->next;\n\t}\n\n\treturn NULL;\n}\n\nvoid Ignore(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\t//ignore\n\treturn;\n}\n\nvoid SuspendThreadAPCRoutine(PVOID arg1, PVOID arg2, PVOID arg3)\n{\n\tLARGE_INTEGER Timeout;\n\tstruct ThreadData *x;\n\t//DbgPrint(\"Inside SuspendThreadAPCRoutine\\n\");\n\t   \n\t\n\tx=arg1;\n\n\t//DbgPrint(\"x=%p\",x);\n\tDbgPrint(\"Waiting...\\n\");\n\tTimeout.QuadPart = -999999999999999;\t\n\n\t\t\n\tKeWaitForSingleObject(&(x->SuspendSemaphore), Suspended, KernelMode, FALSE, NULL);\n\t//KeDelayExecutionThread(KernelMode, FALSE, &Timeout);\n\tDbgPrint(\"Resuming...\\n\");\n}\n\nvoid DBKSuspendThread(ULONG ThreadID)\n{\n\tstruct ThreadData *t_data;\n\n\n\tif (ExAcquireResourceSharedLite(&ProcesslistR, TRUE))\n\t{\n\t\tDbgPrint(\"Going to suspend this thread\\n\");\n\n\t\t//find the thread in the threadlist\n\n\n\t\t//find the threadid in the processlist\n\t\tt_data = GetThreaddata(ThreadID);\n\t\tif (t_data)\n\t\t{\n\t\t\tDbgPrint(\"Suspending thread....\\n\");\n\n\n\n\t\t\tif (!t_data->PEThread)\n\t\t\t{\n\t\t\t\t//not yet initialized\n\t\t\t\tt_data->PEThread = (PETHREAD)getPEThread(ThreadID);\n\t\t\t\tKeInitializeApc(&t_data->SuspendApc,\n\t\t\t\t\t(PKTHREAD)t_data->PEThread,\n\t\t\t\t\t0,\n\t\t\t\t\t(PKKERNEL_ROUTINE)Ignore,\n\t\t\t\t\t(PKRUNDOWN_ROUTINE)NULL,\n\t\t\t\t\t(PKNORMAL_ROUTINE)SuspendThreadAPCRoutine,\n\t\t\t\t\tKernelMode,\n\t\t\t\t\tt_data);\n\n\t\t\t}\n\t\t\tDbgPrint(\"x should be %p\", t_data);\n\t\t\tt_data->suspendcount++;\n\n\t\t\tif (t_data->suspendcount == 1) //not yet suspended so suspend it\n\t\t\t\tKeInsertQueueApc(&t_data->SuspendApc, t_data, t_data, 0);\n\t\t}\n\t\telse\n\t\t\tDbgPrint(\"Thread not found in the list\\n\");\n\t}\n\tExReleaseResourceLite(&ProcesslistR);\n}\n\nvoid DBKResumeThread(ULONG ThreadID)\n{\n\tstruct ThreadData *t_data;\n\n\n\tif (ExAcquireResourceSharedLite(&ProcesslistR, TRUE))\n\t{\n\n\t\tDbgPrint(\"Going to resume this thread\\n\");\n\n\t\t//find the thread in the threadlist\n\n\n\t\t//find the threadid in the processlist\n\t\tt_data = GetThreaddata(ThreadID);\n\t\tif (t_data)\n\t\t{\n\t\t\tif (t_data->suspendcount)\n\t\t\t{\n\t\t\t\tt_data->suspendcount--;\n\t\t\t\tif (!t_data->suspendcount) //suspendcount=0 so resume\n\t\t\t\t\tKeReleaseSemaphore(&t_data->SuspendSemaphore, 0, 1, FALSE);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tDbgPrint(\"Thread not found in the list\\n\");\n\t}\n\tExReleaseResourceLite(&ProcesslistR);\n\n}\n\nvoid DBKSuspendProcess(ULONG ProcessID)\n{\n\tstruct ThreadData *t_data=NULL;\n\tstruct ProcessData *tempProcessData=NULL;\n\n\n\tif (ExAcquireResourceSharedLite(&ProcesslistR, TRUE))\n\t{\n\n\n\t\tDbgPrint(\"Going to suspend this process\\n\");\n\n\t\t//find the process in the threadlist\n\n\t\ttempProcessData = processlist;\n\t\twhile (tempProcessData)\n\t\t{\n\t\t\tif (tempProcessData->ProcessID == (HANDLE)(UINT_PTR)ProcessID)\n\t\t\t{\n\t\t\t\tt_data = tempProcessData->Threads;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ttempProcessData = tempProcessData->next;\n\t\t}\n\n\t\tif (!t_data)\n\t\t{\n\t\t\tDbgPrint(\"This process was not found\\n\");\n\t\t\tExReleaseResourceLite(&ProcesslistR);\n\t\t\treturn; //no process found\n\t\t}\n\n\n\t\twhile (t_data)\n\t\t{\n\t\t\tDbgPrint(\"Suspending thread....\\n\");\n\n\t\t\tif (!t_data->PEThread)\n\t\t\t{\n\t\t\t\t//not yet initialized\n\t\t\t\tt_data->PEThread = (PETHREAD)getPEThread((UINT_PTR)t_data->ThreadID);\n\t\t\t\tKeInitializeApc(&t_data->SuspendApc,\n\t\t\t\t\t(PKTHREAD)t_data->PEThread,\n\t\t\t\t\t0,\n\t\t\t\t\t(PKKERNEL_ROUTINE)Ignore,\n\t\t\t\t\t(PKRUNDOWN_ROUTINE)NULL,\n\t\t\t\t\t(PKNORMAL_ROUTINE)SuspendThreadAPCRoutine,\n\t\t\t\t\tKernelMode,\n\t\t\t\t\tt_data);\n\n\t\t\t}\n\t\t\tDbgPrint(\"x should be %p\", t_data);\n\t\t\tt_data->suspendcount++;\n\n\t\t\tif (t_data->suspendcount == 1) //not yet suspended so suspend it\n\t\t\t\tKeInsertQueueApc(&t_data->SuspendApc, t_data, t_data, 0);\n\n\t\t\tt_data = t_data->next; //next thread\n\t\t}\n\t}\n\tExReleaseResourceLite(&ProcesslistR);\n\n}\n\nvoid DBKResumeProcess(ULONG ProcessID)\n{\n\tstruct ThreadData *t_data=NULL;\n\tstruct ProcessData *tempProcessData=NULL;\n\n\n\tif (ExAcquireResourceSharedLite(&ProcesslistR, TRUE))\n\t{\n\n\t\tDbgPrint(\"Going to suspend this process\\n\");\n\n\t\t//find the process in the threadlist\n\n\t\ttempProcessData = processlist;\n\t\twhile (tempProcessData)\n\t\t{\n\t\t\tif (tempProcessData->ProcessID == (HANDLE)(UINT_PTR)ProcessID)\n\t\t\t{\n\t\t\t\tt_data = tempProcessData->Threads;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ttempProcessData = tempProcessData->next;\n\t\t}\n\n\t\tif (!t_data)\n\t\t{\n\t\t\tDbgPrint(\"This process was not found\\n\");\n\t\t\tExReleaseResourceLite(&ProcesslistR);\n\t\t\treturn; //no process found\n\t\t}\n\n\n\t\twhile (t_data)\n\t\t{\n\t\t\tDbgPrint(\"Resuming thread....\\n\");\n\n\t\t\tif (t_data->suspendcount)\n\t\t\t{\n\t\t\t\tt_data->suspendcount--;\n\t\t\t\tif (!t_data->suspendcount) //suspendcount=0 so resume\n\t\t\t\t\tKeReleaseSemaphore(&t_data->SuspendSemaphore, 0, 1, FALSE);\n\t\t\t}\n\n\n\t\t\tt_data = t_data->next; //next thread\n\t\t}\n\t}\n\tExReleaseResourceLite(&ProcesslistR);\n}\n\n"
  },
  {
    "path": "src/threads.h",
    "content": "#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 Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2);\nvoid SuspendThreadAPCRoutine(PVOID arg1, PVOID arg2, PVOID arg3);\n\nvoid DBKSuspendThread(ULONG ThreadID);\nvoid DBKResumeThread(ULONG ThreadID);\n\nvoid DBKResumeProcess(ULONG ProcessID);\nvoid DBKSuspendProcess(ULONG ProcessID);\n\n\n\n//NTSTATUS NTAPI DBKGetContextThread(IN PETHREAD Thread, IN OUT PCONTEXT ThreadContext);\n\n#endif"
  },
  {
    "path": "src/ultimap.c",
    "content": "/*\nUltimap implements the recording of all the branches in the target process\nRequires dbvm for process selection\n*/\n\n#pragma warning( disable: 4100 4101 4213)\n\n#include <ntifs.h>\n#include \"ultimap.h\"\n#include \"vmxhelper.h\"\n#include \"DBKFunc.h\"\n#include <windef.h>\n\n#include \"ultimap2\\apic.h\"\n\n\nJUMPBACK perfmonJumpBackLocation;\n\n\n/*\n#ifdef AMD64\nvolatile PAPIC APIC_BASE=0; //(PAPIC)0xfffffffffffe0000;\n#else\nvolatile PAPIC APIC_BASE=0; //(PAPIC)0xfffe0000;\n#endif\n*/\n\nBOOL SaveToFile; //If set it will save the results to a file instead of sending a message to the usermode app that is watching the data\nHANDLE FileHandle;\n\nint MaxDataBlocks=1;\n\nKSEMAPHORE DataBlockSemaphore; //governs how many events can be active at a time\nFAST_MUTEX DataBlockMutex; //when a thread passes the semaphore this is used to pick a DataBlock\n\n\ntypedef struct\n{\n\tBOOL Available;\n\tPBTS Data;\n\tint DataSize;\n\tint CpuID;\n\tKEVENT DataReady;    \n} _DataBlock;\n\n_DataBlock *DataBlock;\nPVOID *DataReadyPointerList;\n\nint perfmon_interrupt_centry(void);\n\n/* use apic.* now\n#define MSR_IA32_APICBASE               0x0000001b\n\nvoid setup_APIC_BASE(void)\n{\n\tPHYSICAL_ADDRESS Physical_APIC_BASE;\n\tDbgPrint(\"Fetching the APIC base\\n\");\n\n\tPhysical_APIC_BASE.QuadPart=readMSR(MSR_IA32_APICBASE) & 0xFFFFFFFFFFFFF000ULL;\n\t\n\n\tDbgPrint(\"Physical_APIC_BASE=%p\\n\", Physical_APIC_BASE.QuadPart);\n\n\tAPIC_BASE = (PAPIC)MmMapIoSpace(Physical_APIC_BASE, sizeof(APIC), MmNonCached);\n\n\n    DbgPrint(\"APIC_BASE at %p\\n\", APIC_BASE);\n\n}\n\nvoid clean_APIC_BASE(void)\n{\n\tif (APIC_BASE)\n\t\tMmUnmapIoSpace((PVOID)APIC_BASE, sizeof(APIC));\n}*/\n\nvoid ultimap_flushBuffers_all(UINT_PTR param)\n{\n\tDbgPrint(\"Calling perfmon_interrupt_centry() manually\\n\");\n\tif (DS_AREA[cpunr()]) //don't call if ultimap has been disabled\n\t{\n\t\tperfmon_interrupt_centry();\n\t\tenableInterrupts(); //the handler disables it on exit so re-enable it\n\t}\n}\n\nvoid ultimap_flushBuffers(void)\n{\n\t//call this when the buffer of the current cpu needs to be flushed and handled\n\tint i;\n\tint count;\n\n\tDbgPrint(\"ultimap_flushBuffers\\n\");\n\n\t//what it does:\n\t//for each cpu emulate a \"buffer filled\" event.\n\t//the handler then copies all the current data to a temporary buffer and signals the worker thread to deal with it. If there is no available worker thread it waits\n\tforEachCpuPassive(ultimap_flushBuffers_all,0);\n\n\tDbgPrint(\"ultimap_flushBuffers_all has returned\\n\");\n\t//it returned and all worker thread are currently working on this data (it only returns when it has send a worker to work)\n\n\n\t//now wait for all workers to finish\n\t//do this by aquiring all semaphore slots and waiting for them to return again\n\t//forEachCpuPassive(ultimap_flushBuffers_all,0);\n\t//DbgPrint(\"ultimap_flushBuffers_all has returned a second time\\n\"); //this means that the previous blocks have been dealt with\n\n\n\t//actually... no, this is no guarantee. Now that the buffers are empty handling is so fast that while block 2,3,4,5 and 6 are still being handled block 1 can become available multiple times\n\t\n}\n\n\nNTSTATUS ultimap_continue(PULTIMAPDATAEVENT data)\n/*\nCalled from usermode to signal that the data has been handled\n*/\n{\n\tDbgPrint(\"ultimap_continue\\n\");\n\tMmUnmapLockedPages((PVOID)(UINT_PTR)data->Address, (PMDL)(UINT_PTR)data->Mdl);\n\tIoFreeMdl((PMDL)(UINT_PTR)data->Mdl);\n\n\tExFreePool((PVOID)(UINT_PTR)data->KernelAddress); //this memory is not needed anymore\n\n\n\tif (DataBlock)\n\t\tDataBlock[data->Block].Available=TRUE;\n\n\n\tKeReleaseSemaphore(&DataBlockSemaphore, 1, 1, FALSE); //Let the next block go through\n\tDbgPrint(\"Released semaphore\\n\");\n\treturn STATUS_SUCCESS;\t\n}\n\nNTSTATUS ultimap_waitForData(ULONG timeout, PULTIMAPDATAEVENT data)\n/*\nCalled from usermode to wait for data\n*/\n{\n\tNTSTATUS r;\n\tLARGE_INTEGER wait;\n\n\tPKWAIT_BLOCK waitblock;\n\n\tif (DataBlock)\n\t{\t\t\n\t\twaitblock=ExAllocatePool(NonPagedPool, MaxDataBlocks*sizeof(KWAIT_BLOCK));\n\n\n\t\twait.QuadPart=-10000LL * timeout;\n\n\t\t//Wait for the events in the list\n\t\t//If an event is triggered find out which one is triggered, then map that block into the usermode space and return the address and block\n\t\t//That block will be needed to continue\n\n\t\tif (timeout==0xffffffff) //infinite wait\n\t\t\tr=KeWaitForMultipleObjects(MaxDataBlocks, DataReadyPointerList, WaitAny, UserRequest, UserMode, TRUE, NULL, waitblock);\n\t\telse\n\t\t\tr=KeWaitForMultipleObjects(MaxDataBlocks, DataReadyPointerList, WaitAny, UserRequest, UserMode, TRUE, &wait, waitblock);\n\n\t\tExFreePool(waitblock);\t\n\n\t\tdata->Block=r-STATUS_WAIT_0;\n\n\t\tif (data->Block <= MaxDataBlocks)\n\t\t{\n\t\t\t//Map this block to usermode\n\t\t\t\n\n\t\t\tExAcquireFastMutex(&DataBlockMutex);\n\t\t\tif (DataBlock)\n\t\t\t{\n\t\t\t\tdata->KernelAddress=(UINT64)DataBlock[data->Block].Data;\n\t\t\t\tdata->Mdl=(UINT64)IoAllocateMdl(DataBlock[data->Block].Data, DataBlock[data->Block].DataSize, FALSE, FALSE, NULL);\n\t\t\t\tif (data->Mdl)\n\t\t\t\t{\n\t\t\t\t\tMmBuildMdlForNonPagedPool((PMDL)(UINT_PTR)data->Mdl);\n\n\t\t\t\t\tdata->Address=(UINT_PTR)MmMapLockedPagesSpecifyCache((PMDL)(UINT_PTR)data->Mdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority);\n\t\t\t\t\tif (data->Address)\n\t\t\t\t\t{\n\t\t\t\t\t\tdata->Size=DataBlock[data->Block].DataSize;\n\t\t\t\t\t\tdata->CpuID=DataBlock[data->Block].CpuID;\n\t\t\t\t\t\tr=STATUS_SUCCESS;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tr=STATUS_UNSUCCESSFUL;\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tr=STATUS_UNSUCCESSFUL;\n\t\t\t}\n\t\t\telse\n\t\t\t\tr=STATUS_UNSUCCESSFUL;\n\n\t\t\tExReleaseFastMutex(&DataBlockMutex);\n\n\t\t\treturn r;\t\n\t\t}\n\t\telse\n\t\t\treturn STATUS_UNSUCCESSFUL;\n\t\t\n\t}\n\telse\n\t\treturn STATUS_UNSUCCESSFUL;\n\n\n\t\n}\n\n/*\nvoid apic_clearPerfmon()\n{\n\tAPIC_BASE->LVT_Performance_Monitor.a = APIC_BASE->LVT_Performance_Monitor.a & 0xff;\n\tAPIC_BASE->EOI.a = 0;\n}\n*/\nvoid ultimap_cleanstate()\n{\n\tapic_clearPerfmon();\n}\n\nint perfmon_interrupt_centry(void)\n{\n\n\tKIRQL old = PASSIVE_LEVEL;\n\tint changedIRQL = 0;\n\t\n\tvoid *temp;\n\tint causedbyme=(DS_AREA[cpunr()]->BTS_IndexBaseAddress>=DS_AREA[cpunr()]->BTS_InterruptThresholdAddress);\n\tUINT_PTR blocksize;\n\t\n\tDbgPrint(\"perfmon_interrupt_centry\\n\", cpunr());\n\n\n\tif (causedbyme)\n\t\tultimap_cleanstate();\t\n\n\tblocksize=(UINT_PTR)(DS_AREA[cpunr()]->BTS_IndexBaseAddress-DS_AREA[cpunr()]->BTS_BufferBaseAddress);\n\t\n\t{\t\n\t\tif (KeGetCurrentIrql() < DISPATCH_LEVEL)\n\t\t{\n\t\t\t//When called by the pre-emptive caller\n\t\t\tchangedIRQL = 1;\n\t\t\told = KeRaiseIrqlToDpcLevel();\n\t\t}\n\n\n\t\tDbgPrint(\"Entry cpunr=%d\\n\", cpunr());\n\t\tDbgPrint(\"Entry threadid=%d\\n\", PsGetCurrentThreadId());\n\t\t\n\n\t\ttemp=ExAllocatePool(NonPagedPool, blocksize);\n\t\tif (temp)\n\t\t{\n\t\t\tRtlCopyMemory(temp, (PVOID *)(UINT_PTR)DS_AREA[cpunr()]->BTS_BufferBaseAddress, blocksize);\n\n\t\t\tDbgPrint(\"temp=%p\\n\", temp);\n\n\n\t\t\tDS_AREA[cpunr()]->BTS_IndexBaseAddress=DS_AREA[cpunr()]->BTS_BufferBaseAddress; //don't reset on alloc error\t\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"ExAllocatePool has failed\\n\");\n\t\t\tKeLowerIrql(old);\n\t\t\tdisableInterrupts();\n\t\t\treturn causedbyme;\n\t\t}\n\t\t\n\t\tif (changedIRQL)\n\t\t\tKeLowerIrql(old);\n\t\t//should be passive mode, taskswitches and cpu switches will happen now (When this returns, I may not be on the same interrupt as I was when I started)\n\n\n\t\tif (SaveToFile)\n\t\t{\n\t\t\tIO_STATUS_BLOCK iosb;\n\t\t\tNTSTATUS r;\n\n\t\t\t//Instead of sending the data to a usermode app it was chosen to store the data to a file for later usage\n\t\t\tDbgPrint(\"Writing buffer to disk\\n\");\t\t\t\n\t\t\tr=ZwWriteFile(FileHandle, NULL, NULL, NULL, &iosb,  temp, (ULONG)blocksize, NULL, NULL); \n\t\t\tDbgPrint(\"Done Writing. Result=%x\\n\", r);\t\t\t\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Waiting till there is a block free\\n\");\n\t\t\t//When all workers are busy do not continue\n\t\t\tif ((DataBlock) && (KeWaitForSingleObject(&DataBlockSemaphore, Executive, KernelMode, FALSE, NULL) == STATUS_SUCCESS))\n\t\t\t{\n\t\t\t\tint currentblock;\n\t\t\t\tint i;\n\n\t\t\t\t//Enter a critical section and choose a block\n\t\t\t\tDbgPrint(\"Acquired semaphore. Now picking a usable datablock\\n\");\n\n\t\t\t\t\n\t\t\t\tExAcquireFastMutex(&DataBlockMutex);\n\t\t\t\tDbgPrint(\"Acquired mutex. Looking for a Datablock that can be used\\n\");\n\n\t\t\t\tif (DataBlock)\n\t\t\t\t{\n\t\t\t\t\tcurrentblock=-1;\n\t\t\t\t\tfor (i=0; i< MaxDataBlocks; i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (DataBlock[i].Available) //look for a block that is set as available\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcurrentblock=i;\n\t\t\t\t\t\t\tDataBlock[currentblock].Available=FALSE; //not available anymore\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse currentblock=-1;\n\n\n\n\t\t\t\tif (currentblock>=0) \n\t\t\t\t{\t\t\t\t\t\n\t\t\t\t\tDbgPrint(\"Using datablock %d\\n\", currentblock);\n\t\t\t\t\tDataBlock[currentblock].Data=temp;\n\t\t\t\t\tDataBlock[currentblock].DataSize=(int)blocksize;\n\t\t\t\t\tDataBlock[currentblock].CpuID=cpunr();\n\t\t\t\t\t\n\t\t\t\t\tDbgPrint(\"Calling KeSetEvent/KeWaitForSingleObject\\n\");\n\t\t\t\t\tKeSetEvent(&DataBlock[currentblock].DataReady, 1, FALSE); //Trigger a worker thread to start working\t\t\t\t\t\n\t\t\t\t}\t\n\t\t\t\tExReleaseFastMutex(&DataBlockMutex);\n\t\t\t\t//DbgPrint(\"Released mutex\\n\");\n\t\t\t\t\n\n\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDbgPrint(\"if ((DataBlock) && (KeWaitForSingleObject(&DataBlockSemaphore, Executive, KernelMode, FALSE, NULL) == STATUS_SUCCESS)) failed\\n\");\n\t\t\t}\n\t\t\t\n\t\t}\n\n\n\t\t\n\n\n\t\t//and return to the caller process\n\t\tdisableInterrupts();\n\t\treturn causedbyme;\n\n\t}\t\n}\n\n\n#ifdef AMD64\nextern void perfmon_interrupt();\n#else\n_declspec( naked ) void perfmon_interrupt( void )\n{\n\t__asm{\n\t\tcld\n\n\t\tpush ebp\n\t\tmov ebp,esp\n\n\t\t//store state\n\t\tpushad\n\t\txor eax,eax\n\t\tmov ax,ds\n\t\tpush eax\n\n\t\tmov ax,es\n\t\tpush eax\n\n\t\tmov ax,fs\n\t\tpush eax\n\n\t\tmov ax,gs\n\t\tpush eax\n\n\t\tmov ax,0x23 //0x10 should work too, but even windows itself is using 0x23\n\t\tmov ds,ax\n\t\tmov es,ax\n\t\tmov gs,ax\n\t\tmov ax,0x30\n\t\tmov fs,ax\n\n\t\tcall perfmon_interrupt_centry\n\t\tcmp eax,1\t//set flag\n\n\n\t\t//restore state\n\t\tpop gs\n\t\tpop fs\n\t\tpop es\n\t\tpop ds\n\t\tpopad\n\n\t\tpop ebp\t\t\n\n\t\tje skip_original_perfmon\n\n\t\tjmp far [perfmonJumpBackLocation]\n\nskip_original_perfmon:\n\t\t// commented out: I don't think a APIC interrupt has an errorcode....  add esp,4 //undo errorcode push\n\t\tiretd\n\t}\n}\n#endif\n\nVOID ultimap_pause_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgumen1, IN PVOID SystemArgument2)\n{\n\tvmx_ultimap_pause();\n}\n\nvoid ultimap_pause(void)\n{\n\tforEachCpu(ultimap_pause_dpc, NULL, NULL, NULL, NULL);\n}\n\nVOID ultimap_resume_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgumen1, IN PVOID SystemArgument2)\n{\n\tvmx_ultimap_resume();\n}\n\nvoid ultimap_resume(void)\n{\n\tforEachCpu(ultimap_resume_dpc, NULL, NULL, NULL, NULL);\n}\n\nVOID ultimap_disable_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgumen1, IN PVOID SystemArgument2)\n{\n\tint i;\n\t//DbgPrint(\"ultimap_disable_dpc()\\n\");\n\n\tif (vmxusable)\n\t{\n\t\ti=vmx_ultimap_disable();\t\n\n\t\tif (DS_AREA[cpunr()])\n\t\t{\n\t\t\tExFreePool(DS_AREA[cpunr()]);\n\t\t\tDS_AREA[cpunr()]=NULL;\n\t\t}\n\t}\n}\n\n\n\nvoid ultimap_disable(void)\n{\n\tvoid *clear = NULL;\n\n\tif (DataBlock)\n\t{\n\t\tint i;\n\n\t\tforEachCpu(ultimap_disable_dpc, NULL, NULL, NULL, NULL);\n\n\t\tif (SaveToFile && FileHandle) \n\t\t{\t\t\n\t\t\tZwClose(FileHandle);\n\t\t\tFileHandle=NULL;\n\t\t}\n\n\t\t//all logging should have stopped now\n\t\t\n\t\t//Trigger all events waking up each thread that was waiting for the events\n\n\t\tExAcquireFastMutex(&DataBlockMutex);\n\n\t\tfor (i=0; i<MaxDataBlocks; i++)\n\t\t\tKeSetEvent(&DataBlock[i].DataReady,0, FALSE);\n\n\t\tExFreePool(DataBlock);\n\t\tDataBlock=NULL;\n\n\t\tif (DataReadyPointerList)\n\t\t{\n\t\t\tExFreePool(DataReadyPointerList);\n\t\t\tDataReadyPointerList=NULL;\t\t\n\t\t}\n\t\tExReleaseFastMutex(&DataBlockMutex);\n\n\t    HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), &clear); //unhook the perfmon interrupt\n\n\n\t}\n}\n\n\nVOID ultimap_setup_dpc(IN struct _KDPC *Dpc, IN PVOID  DeferredContext, IN PVOID  SystemArgument1, IN PVOID  SystemArgument2)\n/*\ninitializes ultimap. If the DS_AREA_SIZE is bigger than 0 it will allocate the required region (the usual option, but if not used it could be a LBR only thing)\nCall this for each processor\n*/\n{\n\tstruct\n\t{\n\t\tUINT64 cr3;\n\t\tUINT64 dbgctl_msr;\n\t\tint DS_AREA_SIZE;\n\t} *params;\n\n\tparams=DeferredContext;\n\n\tDS_AREA_SIZE=params->DS_AREA_SIZE;\n\tif (DS_AREA_SIZE == 0)\n\t{\n\t\tDbgPrint(\"DS_AREA_SIZE==0\\n\");\n\t\treturn;\n\t}\n\t\n\n\tDbgPrint(\"ultimap(%I64x, %I64x, %d)\", (UINT64)params->cr3, (UINT64)params->dbgctl_msr, params->DS_AREA_SIZE);\n\tDS_AREA[cpunr()]=NULL;\n\n\tif (params->DS_AREA_SIZE)\n\t{\n\t\tDS_AREA[cpunr()]=ExAllocatePool(NonPagedPool, params->DS_AREA_SIZE);\n\n\t\tif (DS_AREA[cpunr()] == NULL)\n\t\t{\n\t\t\tDbgPrint(\"ExAllocatePool failed\\n\");\n\t\t\treturn;\n\t\t}\n\n\t\tRtlZeroMemory(DS_AREA[cpunr()],  params->DS_AREA_SIZE);\n\n\t\tDbgPrint(\"DS_AREA[%d]=%p\", cpunr(), DS_AREA[cpunr()]);\n\n\t\t//Initialize the DS_AREA \n\n\t\tDS_AREA[cpunr()]->BTS_BufferBaseAddress=(QWORD)(UINT_PTR)DS_AREA[cpunr()]+sizeof(DS_AREA_MANAGEMENT);\n        DS_AREA[cpunr()]->BTS_BufferBaseAddress+=sizeof(BTS);\n\n        DS_AREA[cpunr()]->BTS_BufferBaseAddress-=DS_AREA[cpunr()]->BTS_BufferBaseAddress % sizeof(BTS);\n\n        DS_AREA[cpunr()]->BTS_IndexBaseAddress=DS_AREA[cpunr()]->BTS_BufferBaseAddress;\n        DS_AREA[cpunr()]->BTS_AbsoluteMaxAddress=(QWORD)(UINT_PTR)DS_AREA[cpunr()]+params->DS_AREA_SIZE-sizeof(BTS);\n        DS_AREA[cpunr()]->BTS_AbsoluteMaxAddress-=DS_AREA[cpunr()]->BTS_AbsoluteMaxAddress % sizeof(BTS);\n        DS_AREA[cpunr()]->BTS_AbsoluteMaxAddress++;\n\n        DS_AREA[cpunr()]->BTS_InterruptThresholdAddress=(DS_AREA[cpunr()]->BTS_AbsoluteMaxAddress-1) - 4*sizeof(BTS);\n\t}\n\t\n\n\tif (params->dbgctl_msr & (1 << 8))\n\t{\n\t\t//hook the perfmon interrupt. First get the interrupt assigned (usually 0xfe, but let's be sure and read it from the apic)\t\t\n\n\t\tint perfmonIVT=(APIC_BASE->LVT_Performance_Monitor.a) & 0xff;\n\n\t\tDbgPrint(\"APIC_BASE->LVT_Performance_Monitor.a=%x\\n\", APIC_BASE->LVT_Performance_Monitor.a);\n\t\tif (perfmonIVT==0) //if not setup at all then set it up now\n\t\t\tperfmonIVT=0xfe; \n\n\t\tAPIC_BASE->LVT_Performance_Monitor.a=perfmonIVT; //clear mask flag if it was set\n\n\t\tDbgPrint(\"APIC_BASE->LVT_Performance_Monitor.a=%x\\n\", APIC_BASE->LVT_Performance_Monitor.a);\n\n\t\n\t\t/*\n\n\t\tif (inthook_HookInterrupt((unsigned char)perfmonIVT, getCS(), (ULONG_PTR)perfmon_interrupt, &perfmonJumpBackLocation))\n\t\t\tDbgPrint(\"Interrupt hooked\\n\");\n\t\telse\n\t\t\tDbgPrint(\"Failed to hook interrupt\\n\");\n\t\t\t*/\n\n\t}\n\n\t//and finally activate the mapping\n\tif (vmxusable)\n\t{\n\t\tvmx_ultimap((UINT_PTR)params->cr3, params->dbgctl_msr, DS_AREA[cpunr()]);\n\t}\n\telse\n\t{\n\t\tDbgPrint(\"vmxusable is false. So no ultimap for you!!!\\n\");\n\t}\n}\n\nvoid ultimapapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\tEFLAGS e = getEflags();\n\tDbgPrint(\"ultimapapc call for cpu %d ( IF=%d IRQL=%d)\\n\", KeGetCurrentProcessorNumber(), e.IF, KeGetCurrentIrql());\n\tDbgPrint(\"SystemArgument1=%x\\n\", *(PULONG)SystemArgument1);\n\tDbgPrint(\"tid=%x\\n\", PsGetCurrentThreadId());\n\tDbgPrint(\"Apc=%p\\n\", Apc);\n}\n\nvoid ultimapapcnormal(PVOID arg1, PVOID arg2, PVOID arg3)\n{\n\tEFLAGS e = getEflags();\n\tDbgPrint(\"ultimapapcnormal call for cpu %d ( IF=%d IRQL=%d)\\n\", KeGetCurrentProcessorNumber(), e.IF, KeGetCurrentIrql());\n\tDbgPrint(\"tid=%x\\n\", PsGetCurrentThreadId());\n\n\tultimap_flushBuffers();\n\n\treturn;\n}\n\nKAPC      kApc[128];\nvolatile LONG apcnr = 0;\n\nvoid perfmon_hook(__in struct _KINTERRUPT *Interrupt, __in PVOID ServiceContext)\n{\t\n\t\n\tint i = InterlockedIncrement(&apcnr) % 128;\n\n\t\n\tEFLAGS e = getEflags();\n\tDbgPrint(\"permon_hook call for cpu %d ( IF=%d IRQL=%d)\\n\", KeGetCurrentProcessorNumber(), e.IF, KeGetCurrentIrql());\n\n\tDbgPrint(\"kApc=%p\\n\", &kApc);\n\n\n\t//switch buffer pointers\n\n\t//call DPC for ultimap for this cpu\n\n\n\t//todo: if this is buggy use a dpc instead to create the apc.  (slower)\n\tKeInitializeApc(&kApc[i],\n\t\t(PKTHREAD)PsGetCurrentThread(), \n\t\t0,\n\t\t(PKKERNEL_ROUTINE)ultimapapc,\n\t\tNULL,\n\t\t(PKNORMAL_ROUTINE)ultimapapcnormal,\n\t\tKernelMode,\n\t\t0\n\t\t);\n\n\tKeInsertQueueApc(&kApc[i], NULL, NULL, 0);\n\n\t\n\n\tDbgPrint(\"after KeInsertQueueApc\");\n\n\n\n\n\t//perfmon_interrupt_centry();\n\tultimap_cleanstate();\n\n\tDbgPrint(\"permon_return\");\n}\n\nvoid *pperfmon_hook = (void*)perfmon_hook;\n\nNTSTATUS ultimap(UINT64 cr3, UINT64 dbgctl_msr, int _DS_AREA_SIZE, BOOL savetofile, WCHAR *filename, int handlerCount)\n{\n\tstruct\n\t{\n\t\tUINT64 cr3;\n\t\tUINT64 dbgctl_msr;\n\t\tint DS_AREA_SIZE;\n\t} params;\n\tint i;\n\n\tif (handlerCount>64)\n\t\treturn STATUS_UNSUCCESSFUL;\n\n\n\n\t//create file\n\tSaveToFile=savetofile;\n\n\tif (SaveToFile)\n\t{\n\t\tUNICODE_STRING usFile;\t\n\t\tOBJECT_ATTRIBUTES oaFile;\n\t\tIO_STATUS_BLOCK iosb;\n\t\tNTSTATUS r;\n\n\t\tRtlInitUnicodeString(&usFile, filename);\n\t\tInitializeObjectAttributes(&oaFile,&usFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL,NULL);\n\n\t\tDbgPrint(\"Creating file %S\", usFile.Buffer);\n\n\t\tFileHandle=0;\n\t\tr=ZwCreateFile(&FileHandle,SYNCHRONIZE|FILE_READ_DATA|FILE_APPEND_DATA | GENERIC_ALL,&oaFile,&iosb,0,FILE_ATTRIBUTE_NORMAL,0,FILE_SUPERSEDE, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);\n\t\tDbgPrint(\"ZwCreateFile=%x\\n\", r);\n\n\n\t}\n\n\tMaxDataBlocks=handlerCount;\n\tKeInitializeSemaphore(&DataBlockSemaphore, MaxDataBlocks, MaxDataBlocks);\n\tExInitializeFastMutex(&DataBlockMutex);\n\n\t//Datablock inits\n\n\tDataBlock=ExAllocatePool(NonPagedPool, sizeof(_DataBlock) * MaxDataBlocks);\n\tDataReadyPointerList=ExAllocatePool(NonPagedPool, sizeof(PVOID) * MaxDataBlocks);\n\n\tRtlZeroMemory(DataBlock, sizeof(_DataBlock) * MaxDataBlocks);\n\tRtlZeroMemory(DataReadyPointerList, sizeof(PVOID) * MaxDataBlocks);\n\n\n\tif ((DataBlock) && (DataReadyPointerList))\n\t{\n\t\tNTSTATUS r;\n\n\n\t\tfor (i=0; i< MaxDataBlocks; i++)\n\t\t{\n\t\t\t//DataBlock[i]->\n\t\t\tDataBlock[i].Data=NULL;\n\n\t\t\tKeInitializeEvent(&DataBlock[i].DataReady, SynchronizationEvent , FALSE);\n\n\t\t\tDataBlock[i].Available=TRUE;\n\n\t\t\tDataReadyPointerList[i]=&DataBlock[i].DataReady;\n\t\t}\n\n\n\t\tparams.cr3=cr3;\n\t\tparams.dbgctl_msr=dbgctl_msr;\n\t\tparams.DS_AREA_SIZE=_DS_AREA_SIZE;\n\n\t\tr=HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), &pperfmon_hook); //hook the perfmon interrupt\n\n\t\tDbgPrint(\"HalSetSystemInformation returned %x\\n\", r);\n\n\t\tforEachCpu(ultimap_setup_dpc, &params, NULL, NULL, NULL);\n\t\treturn STATUS_SUCCESS;\n\t}\n\telse\n\t{\n\t\tDbgPrint(\"Failure allocating DataBlock and DataReadyPointerList\\n\");\n\t\treturn STATUS_MEMORY_NOT_ALLOCATED;\n\t}\n\n\t\n}"
  },
  {
    "path": "src/ultimap.h",
    "content": "#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#pragma pack(1)\n/*\ntypedef struct\n{\n  DWORD BTS_BufferBaseAddress;\n  DWORD BTS_IndexBaseAddress;\n  DWORD BTS_AbsoluteMaxAddress;\n  DWORD BTS_InterruptThresholdAddress;\n  DWORD PEBS_BufferBaseAddress;\n  DWORD PEBS_IndexBaseAddress;\n  DWORD PEBS_AbsoluteMaxAddress;\n  DWORD PEBS_InterruptThresholdAddress;\n  QWORD PEBS_CounterReset;\n  QWORD Reserved;\n  DWORD Reserved2;\n} DS_AREA_MANAGEMENT32,*PDS_AREA_MANAGEMENT32;\n*/\n\ntypedef struct\n{\n\n  QWORD BTS_BufferBaseAddress;\n  QWORD BTS_IndexBaseAddress;\n  QWORD BTS_AbsoluteMaxAddress;\n  QWORD BTS_InterruptThresholdAddress;\n  QWORD PEBS_BufferBaseAddress;\n  QWORD PEBS_IndexBaseAddress;\n  QWORD PEBS_AbsoluteMaxAddress;\n  QWORD PEBS_InterruptThresholdAddress;\n  QWORD PEBS_CounterReset;\n  QWORD Reserved;\n  QWORD Reserved2;\n} DS_AREA_MANAGEMENT64,*PDS_AREA_MANAGEMENT64;\n\ntypedef struct\n{\n\n  QWORD LastBranchFrom;\n  QWORD LastBranchTo;\n  QWORD Extra;\n} BTS,*PBTS;\n\n\n//#ifdef AMD64\t\ntypedef DS_AREA_MANAGEMENT64 DS_AREA_MANAGEMENT;\ntypedef PDS_AREA_MANAGEMENT64 PDS_AREA_MANAGEMENT;\n//#else\n//typedef DS_AREA_MANAGEMENT32 DS_AREA_MANAGEMENT;\t\n//typedef PDS_AREA_MANAGEMENT32 PDS_AREA_MANAGEMENT;\t\n//#endif\n\ntypedef struct\n{\n\tUINT64 DataReadyEvent;\n\tUINT64 DataHandledEvent;\n} ULTIMAPEVENT, *PULTIMAPEVENT;\n\ntypedef struct\n{\n\tUINT64 Address;\n\tUINT64 Size;\n\tUINT64 Block;\n\tUINT64 CpuID;\n\tUINT64 KernelAddress;\n\tUINT64 Mdl; //go ahead, scream\n} ULTIMAPDATAEVENT, *PULTIMAPDATAEVENT;\n\nNTSTATUS ultimap_continue(PULTIMAPDATAEVENT data);\nNTSTATUS ultimap_waitForData(ULONG timeout, PULTIMAPDATAEVENT data);\nNTSTATUS ultimap(UINT64 cr3, UINT64 dbgctl_msr, int _DS_AREA_SIZE, BOOL savetofile, WCHAR *filename, int handlerCount);\nvoid ultimap_pause();\nvoid ultimap_resume();\n\nvoid ultimap_disable(void);\nvoid ultimap_flushBuffers(void);\n\n\nPDS_AREA_MANAGEMENT DS_AREA[256]; //used to store the addresses. (reading the msr that holds the DS_AREA is impossible with dbvm active)\nint DS_AREA_SIZE;\n\n\n#pragma pack(pop)\n\n#endif"
  },
  {
    "path": "src/ultimap2/apic.c",
    "content": "#include <ntifs.h>\n\n#include \"apic.h\"\n#include <ntddk.h>\n#include \"..\\DBKFunc.h\"\n\n\n#define MSR_IA32_APICBASE               0x0000001b\n#define MSR_IA32_X2APIC_EOI\t\t\t\t0x80b\n#define MSR_IA32_X2APIC_LVT_PMI\t\t\t0x834\n\n\nvolatile PAPIC APIC_BASE;\n\nBOOL x2APICMode = FALSE;\n\n\nvoid apic_clearPerfmon()\n{\n\tif (x2APICMode)\n\t{\n\t\t__writemsr(MSR_IA32_X2APIC_LVT_PMI, (__readmsr(MSR_IA32_X2APIC_LVT_PMI) & (UINT64)0xff));\n\t\t__writemsr(MSR_IA32_X2APIC_EOI, 0);\n\t}\n\telse\n\t{\n\t\t//DbgPrint(\"Clear perfmon (APIC_BASE at %llx)\\n\", APIC_BASE);\n\t\t//DbgPrint(\"APIC_BASE->LVT_Performance_Monitor.a at %p\\n\", &APIC_BASE->LVT_Performance_Monitor.a);\n\t\t//DbgPrint(\"APIC_BASE->EOI.a at %p\\n\", &APIC_BASE->EOI.a);\n\n\t\t//DbgPrint(\"APIC_BASE->LVT_Performance_Monitor.a had value %x\\n\", APIC_BASE->LVT_Performance_Monitor.a);\n\t\t//DbgPrint(\"APIC_BASE->LVT_Performance_Monitor.b had value %x\\n\", APIC_BASE->LVT_Performance_Monitor.b);\n//\t\tDbgPrint(\"APIC_BASE->LVT_Performance_Monitor.c had value %x\\n\", APIC_BASE->LVT_Performance_Monitor.c);\n\t//\tDbgPrint(\"APIC_BASE->LVT_Performance_Monitor.d had value %x\\n\", APIC_BASE->LVT_Performance_Monitor.d);\n\n\t\tAPIC_BASE->LVT_Performance_Monitor.a = APIC_BASE->LVT_Performance_Monitor.a & 0xff;\n\t\tAPIC_BASE->EOI.a = 0;\n\t}\n}\n\n\nvoid setup_APIC_BASE(void)\n{\n\tPHYSICAL_ADDRESS Physical_APIC_BASE;\n\tUINT64 APIC_BASE_VALUE = readMSR(MSR_IA32_APICBASE);\n\tDbgPrint(\"Fetching the APIC base\\n\");\n\n\tPhysical_APIC_BASE.QuadPart = APIC_BASE_VALUE & 0xFFFFFFFFFFFFF000ULL;\n\n\n\tDbgPrint(\"Physical_APIC_BASE=%p\\n\", Physical_APIC_BASE.QuadPart);\n\n\tAPIC_BASE = (PAPIC)MmMapIoSpace(Physical_APIC_BASE, sizeof(APIC), MmNonCached);\n\n\n\tDbgPrint(\"APIC_BASE at %p\\n\", APIC_BASE);\n\n\tx2APICMode = (APIC_BASE_VALUE & (1 << 10))!=0;\n\tDbgPrint(\"x2APICMode=%d\\n\", x2APICMode);\n}\n\nvoid clean_APIC_BASE(void)\n{\n\tif (APIC_BASE)\n\t\tMmUnmapIoSpace((PVOID)APIC_BASE, sizeof(APIC));\n}\n"
  },
  {
    "path": "src/ultimap2/apic.h",
    "content": "#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\tDWORD d;\n} UINT128;\n\ntypedef volatile struct {\n\tUINT128 Reserved1;\n\tUINT128 Reserved2;\n\tUINT128 LocalAPIC_ID;\n\tUINT128 LocalAPIC_Version;\n\tUINT128 Reserved3;\n\tUINT128 Reserved4;\n\tUINT128 Reserved5;\n\tUINT128 Reserved6;\n\tUINT128 Task_Priority;\n\tUINT128 Arbritation_Priority;\n\tUINT128 Processor_Priority;\n\tUINT128 EOI;\n\tUINT128 Reserved7;\n\tUINT128 Logical_Destination;\n\tUINT128 Destination_Format;\n\tUINT128 Spurious_Interrupt_Vector;\n\tUINT128 In_Service[8];\n\tUINT128 Trigger_Mode[8];\n\tUINT128 Interrupt_Request[8];\n\tUINT128 Error_Status;\n\tUINT128 Reserved8[7];\n\tUINT128 Interrupt_Command_Low32Bit;\n\tUINT128 Interrupt_Command_High32Bit;\n\tUINT128 LVT_Timer;\n\tUINT128 LVT_Thermal_Sensor;\n\tUINT128 LVT_Performance_Monitor;\n\tUINT128 LVT_LINT0;\n\tUINT128 LVT_LINT1;\n\tUINT128 LVT_Error;\n\tUINT128 Initial_Count;\n\tUINT128 Current_Count;\n\tUINT128 Reserved9[4];\n\tUINT128 Divide_Configuration;\n\tUINT128 Reserved10;\n} APIC, *PAPIC;\n\nextern volatile PAPIC APIC_BASE;\n\n\nvoid apic_clearPerfmon();\nvoid setup_APIC_BASE(void);\nvoid clean_APIC_BASE(void);\n\n#endif"
  },
  {
    "path": "src/ultimap2.c",
    "content": "#pragma warning( disable: 4100 4706)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include <minwindef.h>\n#include <wdm.h>\n#include <windef.h>\n\n#include \"Ntstrsafe.h\"\n#include \"DBKFunc.h\"\n\n#include \"ultimap2\\apic.h\"\n#include \"ultimap2.h\"\n\n\nPSSUSPENDPROCESS PsSuspendProcess;\nPSSUSPENDPROCESS PsResumeProcess;\nKDPC RTID_DPC;\n\nBOOL LogKernelMode;\nBOOL LogUserMode;\n\nPEPROCESS CurrentTarget;\nUINT64 CurrentCR3;\nHANDLE Ultimap2Handle;\nvolatile BOOLEAN UltimapActive = FALSE;\nvolatile BOOLEAN isSuspended = FALSE;\nvolatile BOOLEAN flushallbuffers = FALSE; //set to TRUE if all the data should be flushed\nKEVENT FlushData;\n\nBOOL SaveToFile;\nWCHAR OutputPath[200];\n\nint Ultimap2RangeCount;\nPURANGE Ultimap2Ranges = NULL;\n\nPVOID *Ultimap2_DataReady;\n\n\n#if (NTDDI_VERSION < NTDDI_VISTA)\n//implement this function for XP\nunsigned int KeQueryMaximumProcessorCount()\n{\n\tCCHAR cpunr;\n\tKAFFINITY cpus, original;\n\tULONG cpucount;\n\n\tcpucount = 0;\n\tcpus = KeQueryActiveProcessors();\n\toriginal = cpus;\n\twhile (cpus)\n\t{\n\t\tif (cpus % 2)\n\t\t\tcpucount++;\n\n\t\tcpus = cpus / 2;\n\t}\n\n\treturn cpucount;\n}\n#endif\n\ntypedef struct\n{\t\n\tPToPA_ENTRY ToPAHeader;\n\tPToPA_ENTRY ToPAHeader2;\n\n\tPVOID ToPABuffer;\n\tPVOID ToPABuffer2;\n\n\tPMDL ToPABufferMDL;\n\tPMDL ToPABuffer2MDL;\n\n\tPRTL_GENERIC_TABLE ToPALookupTable;\n\tPRTL_GENERIC_TABLE ToPALookupTable2;\n\n\tKEVENT Buffer2ReadyForSwap;\n\tKEVENT InitiateSave;\n\n\tKEVENT DataReady;\n\tKEVENT DataProcessed;\n\n\tUINT64 CurrentOutputBase;\n\tUINT64 CurrentSaveOutputBase;\n\tUINT64 CurrentSaveOutputMask;\n\n\tUINT64 MappedAddress; //set by WaitForData  , use with continue\n\tUINT64 Buffer2FlushSize; //used by WaitForData\n\n\n\tKDPC OwnDPC;\n\tHANDLE WriterThreadHandle;\n\n\t//for saveToFile mode\n\tHANDLE FileHandle;\n\tKEVENT FileAccess;\n\tUINT64 TraceFileSize;\n\n\tvolatile BOOL Interrupted;\n}  ProcessorInfo, *PProcessorInfo;\nvolatile PProcessorInfo *PInfo;\n\nint Ultimap2CpuCount;\n\n\nKMUTEX SuspendMutex;\nKEVENT SuspendEvent;\nHANDLE SuspendThreadHandle;\nvolatile int suspendCount;\nBOOL ultimapEnabled = FALSE;\nBOOL singleToPASystem = FALSE;\nBOOL NoPMIMode = FALSE;\n\n\nvoid suspendThread(PVOID StartContext)\n/* Thread responsible for suspending the target process when the buffer is getting full */\n{\n\tNTSTATUS wr;\n\t__try\n\t{\n\t\twhile (UltimapActive)\n\t\t{\n\t\t\twr = KeWaitForSingleObject(&SuspendEvent, Executive, KernelMode, FALSE, NULL);\n\t\t\tif (!UltimapActive) return;\n\n\t\t\tDbgPrint(\"suspendThread event triggered\");\n\t\t\tKeWaitForSingleObject(&SuspendMutex, Executive, KernelMode, FALSE, NULL);\n\t\t\tif (!isSuspended)\n\t\t\t{\n\t\t\t\tif (CurrentTarget == 0)\n\t\t\t\t{\n\t\t\t\t\tif (PsSuspendProcess(CurrentTarget) == 0)\n\t\t\t\t\t\tisSuspended = TRUE;\n\t\t\t\t\telse\n\t\t\t\t\t\tDbgPrint(\"Failed to suspend target\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tKeReleaseMutex(&SuspendMutex, FALSE);\n\t\t}\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"Exception in suspendThread thread\\n\");\n\t}\n}\n\nNTSTATUS ultimap2_continue(int cpunr)\n{\n\tNTSTATUS r = STATUS_UNSUCCESSFUL;\n\tif ((cpunr < 0) || (cpunr >= Ultimap2CpuCount))\n\t{\n\t\tDbgPrint(\"ultimap2_continue(%d)\", cpunr);\n\t\treturn STATUS_UNSUCCESSFUL;\n\t}\n\n\tif (PInfo)\n\t{\n\t\tPProcessorInfo pi = PInfo[cpunr];\n\n\t\tif (pi->MappedAddress)\n\t\t{\n\t\t\tMmUnmapLockedPages((PVOID)(UINT_PTR)pi->MappedAddress, pi->ToPABuffer2MDL); //unmap this memory\n\t\t\tpi->MappedAddress = 0;\n\t\t\tr = STATUS_SUCCESS;\n\t\t}\n\t\telse\n\t\t\tDbgPrint(\"MappedAddress was 0\");\n\n\t\tDbgPrint(\"%d DataProcessed\", cpunr);\n\t\tKeSetEvent(&pi->DataProcessed, 0, FALSE); //let the next swap happen if needed\n\n\t\t\n\t}\n\t\n\treturn r;\n\t\n}\n\nNTSTATUS ultimap2_waitForData(ULONG timeout, PULTIMAP2DATAEVENT data)\n{\n\tNTSTATUS r=STATUS_UNSUCCESSFUL;\n\n\n\n\n\t//Wait for the events in the list\n\t//If an event is triggered find out which one is triggered, then map that block into the usermode space and return the address and block\n\t//That block will be needed to continue\n\n\tif (UltimapActive)\n\t{\n\t\tNTSTATUS wr = STATUS_UNSUCCESSFUL;\n\t\tLARGE_INTEGER wait;\n\t\tPKWAIT_BLOCK waitblock;\n\n\t\tint cpunr;\n\n\t\twaitblock = ExAllocatePool(NonPagedPool, Ultimap2CpuCount*sizeof(KWAIT_BLOCK));\n\t\twait.QuadPart = -10000LL * timeout;\n\n\t\tif (timeout == 0xffffffff) //infinite wait\n\t\t\twr = KeWaitForMultipleObjects(Ultimap2CpuCount, Ultimap2_DataReady, WaitAny, UserRequest, UserMode, TRUE, NULL, waitblock);\n\t\telse\n\t\t\twr = KeWaitForMultipleObjects(Ultimap2CpuCount, Ultimap2_DataReady, WaitAny, UserRequest, UserMode, TRUE, &wait, waitblock);\n\n\t\tExFreePool(waitblock);\n\n\t\tDbgPrint(\"ultimap2_waitForData wait returned %x\", wr);\n\n\t\tcpunr = wr - STATUS_WAIT_0;\n\n\n\t\tif ((cpunr < Ultimap2CpuCount) && (cpunr>=0))\n\t\t{\n\t\t\tPProcessorInfo pi = PInfo[cpunr];\n\n\t\t\t\n\n\n\t\t\tif (pi->Buffer2FlushSize)\n\t\t\t{\n\t\t\t\tif (pi->ToPABuffer2MDL)\n\t\t\t\t{\n\t\t\t\t\t__try\n\t\t\t\t\t{\n\n\t\t\t\t\t\tdata->Address = (UINT64)MmMapLockedPagesSpecifyCache(pi->ToPABuffer2MDL, UserMode, MmCached, NULL, FALSE, NormalPagePriority);\n\n\t\t\t\t\t\tDbgPrint(\"MmMapLockedPagesSpecifyCache returned address %p\\n\", data->Address);\n\n\t\t\t\t\t\tif (data->Address)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdata->Size = pi->Buffer2FlushSize;\n\t\t\t\t\t\t\tdata->CpuID = cpunr;\n\n\t\t\t\t\t\t\tpi->MappedAddress = data->Address;\n\t\t\t\t\t\t\tr = STATUS_SUCCESS;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\t__except (1)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"ultimap2_waitForData: Failure mapping memory into waiter process. Count=%d\", (int)MmGetMdlByteCount(pi->ToPABuffer2MDL));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"ToPABuffer2MDL is NULL. Not even gonna try\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tDbgPrint(\"ultimap2_waitForData flushsize was 0\");\n\t\t\t}\n\t\t}\n\n\t}\n\n\tDbgPrint(\"ultimap2_waitForData returned %x\\n\", r);\n\treturn r;\n}\n\nvoid createUltimap2OutputFile(int cpunr)\n{\n\tNTSTATUS r;\n\tPProcessorInfo pi = PInfo[cpunr];\n\tUNICODE_STRING usFile;\n\tOBJECT_ATTRIBUTES oaFile;\n\tIO_STATUS_BLOCK iosb;\n\tWCHAR Buffer[200];\n\t\n#ifdef AMD64\t\n\tDbgPrint(\"OutputPath=%S\", OutputPath);\n\tswprintf_s(Buffer, 200, L\"%sCPU%d.trace\", OutputPath, cpunr);\n#else\n\tRtlStringCbPrintfW(Buffer, 200, L\"%sCPU%d.trace\", OutputPath, cpunr);\n#endif\n\n\tDbgPrint(\"Buffer=%S\", Buffer);\n\n\n\tRtlInitUnicodeString(&usFile, Buffer);\n\n\tInitializeObjectAttributes(&oaFile, &usFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);\n\n\tDbgPrint(\"Creating file %S\", usFile.Buffer);\n\n\tpi->FileHandle = 0;\n\tZwDeleteFile(&oaFile);\n\tr = ZwCreateFile(&pi->FileHandle, SYNCHRONIZE | FILE_READ_DATA | FILE_APPEND_DATA | GENERIC_ALL, &oaFile, &iosb, 0, FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);\n\tDbgPrint(\"%d: ZwCreateFile=%x\\n\", (int)cpunr, r);\n\n\n\n}\n\nvoid WriteThreadForSpecificCPU(PVOID StartContext)\n{\n\tint cpunr = (int)(UINT_PTR)StartContext;\n\tPProcessorInfo pi = PInfo[cpunr];\n\t\n\n\n\tIO_STATUS_BLOCK iosb;\n\tNTSTATUS r = STATUS_UNSUCCESSFUL;\n\t\n\n\t//DbgPrint(\"WriteThreadForSpecificCPU %d alive\", (int)StartContext);\n\n\n\n\tif (SaveToFile)\n\t{\n\t\tif (KeWaitForSingleObject(&pi->FileAccess, Executive, KernelMode, FALSE, NULL) == STATUS_SUCCESS)\n\t\t{\n\t\t\tcreateUltimap2OutputFile(cpunr);\n\t\t\tKeSetEvent(&pi->FileAccess, 0, FALSE);\n\t\t}\n\t\telse\n\t\t\tcreateUltimap2OutputFile(cpunr);\n\t}\n\n\t\n\tKeSetSystemAffinityThread((KAFFINITY)(1 << cpunr));\n\t\n\twhile (UltimapActive)\n\t{\n\t\tNTSTATUS wr = KeWaitForSingleObject(&pi->InitiateSave, Executive, KernelMode, FALSE, NULL);\n\t\t//DbgPrint(\"WriteThreadForSpecificCPU %d:  wr=%x\", (int)StartContext, wr);\n\t\tif (!UltimapActive)\n\t\t\tbreak;\n\t\t\n\t\tif (wr == STATUS_SUCCESS)\n\t\t{\n\t\t\tUINT64 Size;\n\t\t\tToPA_LOOKUP tl;\n\t\t\tPToPA_LOOKUP result;\n\n\t\t\t//DbgPrint(\"%d: writing buffer\", (int)StartContext);\n\n\t\t\t//figure out the size\n\t\t\ttl.PhysicalAddress = pi->CurrentSaveOutputBase;\n\t\t\ttl.index = 0;\n\t\t\tresult = RtlLookupElementGenericTable(pi->ToPALookupTable2, &tl);\n\n\t\t\tif (result)\n\t\t\t{\n\t\t\t\t//write...\n\t\t\t\t//DbgPrint(\"%d: result->index=%d CurrentSaveOutputMask=%p\", (int)StartContext, result->index, pi->CurrentSaveOutputMask);\n\t\t\t\tif (singleToPASystem)\n\t\t\t\t\tSize = pi->CurrentSaveOutputMask >> 32;\n\t\t\t\telse\n\t\t\t\t\tSize = ((result->index * 511) + ((pi->CurrentSaveOutputMask & 0xffffffff) >> 7)) * 4096 + (pi->CurrentSaveOutputMask >> 32);\n\n\t\t\t\tif (Size > 0)\n\t\t\t\t{\n\n\t\t\t\t\tif (SaveToFile)\n\t\t\t\t\t{\n\t\t\t\t\t\twr = KeWaitForSingleObject(&pi->FileAccess, Executive, KernelMode, FALSE, NULL);\n\t\t\t\t\t\tif (wr==STATUS_SUCCESS)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (pi->FileHandle==0) //a usermode flush has happened\n\t\t\t\t\t\t\t\tcreateUltimap2OutputFile(cpunr); \n\n\t\t\t\t\t\t\tr = ZwWriteFile(pi->FileHandle, NULL, NULL, NULL, &iosb, pi->ToPABuffer2, (ULONG)Size, NULL, NULL);\n\n\t\t\t\t\t\t\tpi->TraceFileSize += Size;\n\t\t\t\t\t\t\t//DbgPrint(\"%d: ZwCreateFile(%p, %d)=%x\\n\", (int)StartContext, pi->ToPABuffer2, (ULONG)Size, r);\n\n\t\t\t\t\t\t\tKeSetEvent(&pi->FileAccess, 0, FALSE);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//map ToPABuffer2 into the CE process\n\t\t\t\t\t\t\n\t\t\t\t\t\t//wake up a worker thread\n\t\t\t\t\t\tpi->Buffer2FlushSize = Size;\n\t\t\t\t\t\tDbgPrint(\"%d: WorkerThread(%p, %d)=%x\\n\", (int)(UINT_PTR)StartContext, pi->ToPABuffer2, (ULONG)Size, r);\n\t\t\t\t\t\tKeSetEvent(&pi->DataReady, 0, TRUE); //a ce thread waiting in ultimap2_waitForData should now wake and process the data\n\t\t\t\t\t\t//and wait for it to finish\n\t\t\t\t\t\tr=KeWaitForSingleObject(&pi->DataProcessed, Executive, KernelMode, FALSE, NULL);\t\n\t\t\t\t\t\tDbgPrint(\"KeWaitForSingleObject(DataProcessed)=%x\", r);\n\n\t\t\t\t\t}\n\t\t\t\t\t//DbgPrint(\"%d: Writing %x bytes\\n\", (int)StartContext, Size);\n\t\t\t\t}\n\n\n\t\t\t}\n\t\t\telse\n\t\t\t\tDbgPrint(\"Unexpected physical address while writing results for cpu %d  (%p)\", (int)(UINT_PTR)StartContext, pi->CurrentSaveOutputBase);\n\t\t\t\n\n\t\t\tKeSetEvent(&pi->Buffer2ReadyForSwap, 0, FALSE);\n\t\t}\t\t\n\t}\n\n\tKeSetSystemAffinityThread(KeQueryActiveProcessors());\n\n\tif (pi->FileHandle)\n\t\tZwClose(pi->FileHandle);\n\n\tKeSetEvent(&pi->Buffer2ReadyForSwap, 0, FALSE); \n}\n\nvoid ultimap2_LockFile(int cpunr)\n{\n\tif ((cpunr < 0) || (cpunr >= Ultimap2CpuCount))\n\t\treturn;\n\n\tif (PInfo)\n\t{\n\t\tNTSTATUS wr;\n\t\tPProcessorInfo pi = PInfo[cpunr];\n\n\t\t//DbgPrint(\"AcquireUltimap2File()\");\n\t\twr = KeWaitForSingleObject(&pi->FileAccess, Executive, KernelMode, FALSE, NULL);\n\t\tif (wr == STATUS_SUCCESS)\n\t\t{\n\t\t\t//DbgPrint(\"Acquired\");\n\t\t\tif (pi->FileHandle)\n\t\t\t{\n\t\t\t\tZwClose(pi->FileHandle);\n\t\t\t\tpi->FileHandle = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid ultimap2_ReleaseFile(int cpunr)\n{\n\tif ((cpunr < 0) || (cpunr >= Ultimap2CpuCount))\n\t\treturn;\n\n\tif (PInfo)\n\t{\n\t\tPProcessorInfo pi = PInfo[cpunr];\n\t\tKeSetEvent(&pi->FileAccess, 0, FALSE);\n\t\t//DbgPrint(\"Released\");\n\t}\n}\n\nUINT64 ultimap2_GetTraceFileSize()\n//Gets an aproximation of the filesize.  Don't take this too exact\n{\n\tUINT64 size = 0;\n\t\n\tif (PInfo)\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t\t\tsize += PInfo[i]->TraceFileSize;\n\t}\n\t\n\treturn size;\n}\n\nvoid ultimap2_ResetTraceFileSize()\n{\n\tif (PInfo)\n\t{\n\t\tint i;\n\t\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t\t\tPInfo[i]->TraceFileSize = 0;\n\t}\t\n}\n\n\nvoid SwitchToPABuffer(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)\n/*\nDPC routine that switches the Buffer pointer and marks buffer2 that it's ready for data saving\nOnly called when buffer2 is ready for flushing\n*/\n{\n\t//write the contents of the current cpu buffer\n\tPProcessorInfo pi = PInfo[KeGetCurrentProcessorNumber()];\n\n\t//DbgPrint(\"SwitchToPABuffer for cpu %d\\n\", KeGetCurrentProcessorNumber());\n\n\tif (pi)\n\t{\t\t\n\t\tUINT64 CTL = __readmsr(IA32_RTIT_CTL);\n\t\tUINT64 Status = __readmsr(IA32_RTIT_STATUS);\n\t\tPVOID temp;\n\n\t\tif ((Status >> 5) & 1) //Stopped\n\t\t\tDbgPrint(\"%d Not all data recorded\\n\", KeGetCurrentProcessorNumber());\n\n\n\t\tif ((Status >> 4) & 1)\n\t\t\tDbgPrint(\"ALL LOST\");\n\n\t\t//only if the buffer is bigger than 2 pages.  That you can check in IA32_RTIT_OUTPUT_MASK_PTRS and IA32_RTIT_OUTPUT_BASE \n\t\t//if (KeGetCurrentProcessorNumber() == 0)\n\t\t//\tDbgPrint(\"%d: pi->CurrentOutputBase=%p __readmsr(IA32_RTIT_OUTPUT_BASE)=%p __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS)=%p\", KeGetCurrentProcessorNumber(), pi->CurrentOutputBase, __readmsr(IA32_RTIT_OUTPUT_BASE), __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\n\n\t\tif (pi->Interrupted == FALSE)\n\t\t{\n\t\t\t//return; //debug test. remove me when released\n\t\t\t\n\t\t\tif (!singleToPASystem)\n\t\t\t{\n\t\t\t\tif ((!flushallbuffers) && (((__readmsr(IA32_RTIT_OUTPUT_MASK_PTRS) & 0xffffffff) >> 7) < 2))\n\t\t\t\t\treturn; //don't flush yet\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tINT64 offset = __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS);\n\n\t\t\t\t/*if (KeGetCurrentProcessorNumber() == 0)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"pi->CurrentOutputBase=%p\", pi->CurrentOutputBase);\n\t\t\t\t\tDbgPrint(\"offset=%p\", offset);\n\t\t\t\t}*/\n\n\t\t\t\toffset = offset >> 32;\n\n\t\t\t\t//if (KeGetCurrentProcessorNumber() == 0)\n\t\t\t\t//\tDbgPrint(\"offset=%p\", offset);\n\n\t\t\t\tif ((!flushallbuffers) && (((pi->CurrentOutputBase == 0) || (offset < 8192))))\n\t\t\t\t\treturn; //don't flush yet\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"%d:Flushing because of interrupt\", KeGetCurrentProcessorNumber());\n\t\t}\n\n\t\tDbgPrint(\"%d: Flush this data (%p)\", KeGetCurrentProcessorNumber(), __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\t\t//DbgPrint(\"%d: pi->CurrentOutputBase=%p __readmsr(IA32_RTIT_OUTPUT_BASE)=%p __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS)=%p\", KeGetCurrentProcessorNumber(), pi->CurrentOutputBase, __readmsr(IA32_RTIT_OUTPUT_BASE), __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\n\t\t__writemsr(IA32_RTIT_CTL, 0); //disable packet generation\n\t\t__writemsr(IA32_RTIT_STATUS, 0);\n\n\n\t\t//DbgPrint(\"%d: pi->CurrentOutputBase=%p __readmsr(IA32_RTIT_OUTPUT_BASE)=%p __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS)=%p\", KeGetCurrentProcessorNumber(), pi->CurrentOutputBase, __readmsr(IA32_RTIT_OUTPUT_BASE), __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\n\t\t\n\t\t\n\n\t\t//switch the pointer to the secondary buffers\n\t\tKeClearEvent(&pi->Buffer2ReadyForSwap);\n\n\t\t//swap the buffer\n\t\ttemp = pi->ToPABuffer;\n\t\tpi->ToPABuffer = pi->ToPABuffer2; \n\t\tpi->ToPABuffer2 = temp;\n\n\t\t//swap the MDL that describes it\n\t\ttemp = pi->ToPABufferMDL;\n\t\tpi->ToPABufferMDL = pi->ToPABuffer2MDL;\n\t\tpi->ToPABuffer2MDL = temp;\n\n\t\t//swap the header\n\t\ttemp = pi->ToPAHeader;\n\t\tpi->ToPAHeader = pi->ToPAHeader2;\n\t\tpi->ToPAHeader2 = temp;\n\n\t\t//swap the lookup table\n\t\ttemp = pi->ToPALookupTable;\n\t\tpi->ToPALookupTable = pi->ToPALookupTable2;\n\t\tpi->ToPALookupTable2 = temp;\n\n\t\t//lookup which entry it's pointing at\n\t\tpi->CurrentSaveOutputBase = __readmsr(IA32_RTIT_OUTPUT_BASE);\n\t\tpi->CurrentSaveOutputMask = __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS);\n\n\t\tKeSetEvent(&pi->InitiateSave,0,FALSE);\n\n\t\tpi->Interrupted = FALSE;\n\n\t\t//reactivate packet generation\n\t\tpi->CurrentOutputBase = MmGetPhysicalAddress(pi->ToPAHeader).QuadPart;\n\n\t\t__writemsr(IA32_RTIT_OUTPUT_BASE, pi->CurrentOutputBase);\n\t\t__writemsr(IA32_RTIT_OUTPUT_MASK_PTRS, 0);\n\n\t\t__writemsr(IA32_RTIT_CTL, CTL);\n\t}\n}\n\nvoid WaitForWriteToFinishAndSwapWriteBuffers(BOOL interruptedOnly)\n{\n    int i;\n\t\n\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t{\n\t\tPProcessorInfo pi = PInfo[i];\n\t\tif ((pi->ToPABuffer2) && ((pi->Interrupted) || (!interruptedOnly)))\n\t\t{\n\t\t\tKeWaitForSingleObject(&pi->Buffer2ReadyForSwap, Executive, KernelMode, FALSE, NULL);\n\n\t\t\tif (!UltimapActive) return;\n\n\t\t\tKeInsertQueueDpc(&pi->OwnDPC, NULL, NULL);\n\t\t}\n\t\t\n\t}\n\n\tKeFlushQueuedDpcs();\n}\n\nvoid bufferWriterThread(PVOID StartContext)\n{\n\t//passive mode\n\n\t//wait for event\n\tLARGE_INTEGER Timeout;\n\tNTSTATUS wr;\n\n\tDbgPrint(\"bufferWriterThread active\");\n\n\t\n\twhile (UltimapActive)\n\t{\n\t\tif (NoPMIMode)\n\t\t\tTimeout.QuadPart = -1000LL;  //- 10000LL=1 millisecond //-100000000LL = 10 seconds   -1000000LL= 0.1 second\n\t\telse\n\t\t\tTimeout.QuadPart = -10000LL;  //- 10000LL=1 millisecond //-100000000LL = 10 seconds   -1000000LL= 0.1 second\n\n\t\t//DbgPrint(\"%d : Wait for FlushData\", cpunr());\n\t\twr = KeWaitForSingleObject(&FlushData, Executive, KernelMode, FALSE, &Timeout);\n\t\t//DbgPrint(\"%d : After wait for FlushData\", cpunr());\n\t\t//wr = KeWaitForSingleObject(&FlushData, Executive, KernelMode, FALSE, NULL);\n\n\t\t//DbgPrint(\"bufferWriterThread: Alive (wr==%x)\", wr);\n\t\tif (!UltimapActive)\n\t\t{\n\t\t\tDbgPrint(\"bufferWriterThread: Terminating\");\n\t\t\treturn;\n\t\t}\n\n\t\t//if (wr != STATUS_SUCCESS) continue; //DEBUG code so PMI's get triggered\n\n\n\n\t\tif ((wr == STATUS_SUCCESS) || (wr == STATUS_TIMEOUT))\n\t\t{\n\t\t\tif ((wr == STATUS_SUCCESS) && (!isSuspended))\n\t\t\t{\n\t\t\t\t//woken up by a dpc\t\t\t\t\n\t\t\t\tDbgPrint(\"FlushData event set and not suspended. Suspending target process\\n\");\n\t\t\t\tKeWaitForSingleObject(&SuspendMutex, Executive, KernelMode, FALSE, NULL);\n\t\t\t\tif (!isSuspended)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Still going to suspend target process\");\n\t\t\t\t\tif (PsSuspendProcess(CurrentTarget)==0)\n\t\t\t\t\t\tisSuspended = TRUE;\n\t\t\t\t}\n\t\t\t\tKeReleaseMutex(&SuspendMutex, FALSE);\n\n\t\t\t\tDbgPrint(\"After the target has been suspended (isSuspended=%d)\\n\", isSuspended);\n\t\t\t}\t\t\t\n\n\t\t\tif (wr == STATUS_SUCCESS) //the filled cpu's must take preference\n\t\t\t{\n\t\t\t\tunsigned int i;\n\t\t\t\tBOOL found = TRUE;\n\n\t\t\t\t//DbgPrint(\"bufferWriterThread: Suspended\");\n\n\n\t\t\t\t//first flush the CPU's that complained their buffers are full\n\t\t\t\tDbgPrint(\"Flushing full CPU\\'s\");\n\t\t\t\twhile (found)\n\t\t\t\t{\n\t\t\t\t\tWaitForWriteToFinishAndSwapWriteBuffers(TRUE);\n\t\t\t\t\tif (!UltimapActive) return;\n\n\t\t\t\t\t//check if no interrupt has been triggered while this was busy ('could' happen as useless info like core ratio is still recorded)\n\t\t\t\t\tfound = FALSE;\n\t\t\t\t\tfor (i = 0; i < KeQueryMaximumProcessorCount(); i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (PInfo[i]->Interrupted)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tDbgPrint(\"PInfo[%d]->Interrupted\\n\", PInfo[i]->Interrupted);\n\t\t\t\t\t\t\tfound = TRUE;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//wait till the previous buffers are done writing\n\t\t\t//DbgPrint(\"%d: Normal flush\", cpunr());\n\t\t\tWaitForWriteToFinishAndSwapWriteBuffers(FALSE);\n\t\t\t//DbgPrint(\"%d : after flush\", cpunr());\n\n\t\t\tif (isSuspended)\n\t\t\t{\n\t\t\t\tKeWaitForSingleObject(&SuspendMutex, Executive, KernelMode, FALSE, NULL);\n\t\t\t\tif (isSuspended)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Resuming target process\");\n\t\t\t\t\tPsResumeProcess(CurrentTarget);\n\t\t\t\t\tisSuspended = FALSE;\n\t\t\t\t}\n\t\t\t\tKeReleaseMutex(&SuspendMutex, FALSE);\n\t\t\t}\n\t\t\t//an interrupt could have fired while WaitForWriteToFinishAndSwapWriteBuffers was busy, pausing the process. If that happened, then the next KeWaitForSingleObject will exit instantly due to it being signaled \n\t\t}\n\t\telse\n\t\t\tDbgPrint(\"Unexpected wait result\");\n\t\t\n\t}\n}\n\n\nNTSTATUS ultimap2_flushBuffers()\n{\n\tif (!UltimapActive)\n\t\treturn STATUS_UNSUCCESSFUL;\n\n\tDbgPrint(\"ultimap2_flushBuffers\");\n\n\tKeWaitForSingleObject(&SuspendMutex, Executive, KernelMode, FALSE, NULL);\n\tif (CurrentTarget)\n\t{\n\t\tif (!isSuspended)\n\t\t{\n\t\t\tPsSuspendProcess(CurrentTarget);\n\t\t\tisSuspended = TRUE;\n\t\t}\n\t}\n\tKeReleaseMutex(&SuspendMutex, FALSE);\n\n\tflushallbuffers = TRUE;\n\t\n\tDbgPrint(\"wait1\");\n\tWaitForWriteToFinishAndSwapWriteBuffers(FALSE); //write the last saved buffer\n\n\tDbgPrint(\"wait2\");\n\tWaitForWriteToFinishAndSwapWriteBuffers(FALSE); //write the current buffer\n\n\tflushallbuffers = FALSE;\n\tDbgPrint(\"after wait\");\n\tKeWaitForSingleObject(&SuspendMutex, Executive, KernelMode, FALSE, NULL);\n\tif (CurrentTarget)\n\t{\n\t\tif (isSuspended)\n\t\t{\n\t\t\tPsResumeProcess(CurrentTarget);\n\t\t\tisSuspended = FALSE;\n\t\t}\n\t}\n\tKeReleaseMutex(&SuspendMutex, FALSE);\t\n\n\tDbgPrint(\"ultimap2_flushBuffers exit\");\n\treturn STATUS_SUCCESS;\n}\n\n\n\nvoid RTIT_DPC_Handler(__in struct _KDPC *Dpc, __in_opt PVOID DeferredContext, __in_opt PVOID SystemArgument1,__in_opt PVOID SystemArgument2)\n{\n\t//Signal the bufferWriterThread\n\tKeSetEvent(&SuspendEvent, 0, FALSE);\n\tKeSetEvent(&FlushData, 0, FALSE);\n}\n \n\nvoid PMI(__in struct _KINTERRUPT *Interrupt, __in PVOID ServiceContext)\n{\n\t//check if caused by me, if so defer to dpc\n\tDbgPrint(\"PMI\");\n\t__try\n\t{\n\t\tif ((__readmsr(IA32_PERF_GLOBAL_STATUS) >> 55) & 1)\n\t\t{\n\t\t\tUINT64 Status = __readmsr(IA32_RTIT_STATUS);\n\n\t\t\tDbgPrint(\"PMI: caused by me\");\t\n\t\t\t__writemsr(IA32_PERF_GLOBAL_OVF_CTRL, (UINT64)1 << 55); //clear ToPA full status\n\n\t\t\tif ((__readmsr(IA32_PERF_GLOBAL_STATUS) >> 55) & 1)\n\t\t\t{\n\t\t\t\tDbgPrint(\"PMI: Failed to clear the status\\n\");\n\t\t\t}\n\n\t\t\tDbgPrint(\"PMI: IA32_RTIT_OUTPUT_MASK_PTRS=%p\\n\", __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\t\t\tDbgPrint(\"PMI: IA32_RTIT_STATUS=%p\\n\", Status);\n\t\t\t\n\t\t\tif ((Status >> 5) & 1) //Stopped\n\t\t\t\tDbgPrint(\"PMI %d: Not all data recorded (AT THE PMI!)\\n\", KeGetCurrentProcessorNumber());\n\n\n\t\t\tDbgPrint(\"PMI: IA32_RTIT_OUTPUT_MASK_PTRS %p\\n\", __readmsr(IA32_RTIT_OUTPUT_MASK_PTRS));\n\n\t\t\tPInfo[KeGetCurrentProcessorNumber()]->Interrupted = TRUE;\n\n\t\t\tKeInsertQueueDpc(&RTID_DPC, NULL, NULL);\n\n\t\t\t//clear apic state\n\n\t\t\tapic_clearPerfmon();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Unexpected PMI\");\n\t\t}\n\t}\n\t__except (0)\n\t{\n\t\tDbgPrint(\"PMI exception\");\n\t}\n\n}\n\nvoid *pperfmon_hook2 = (void *)PMI;\n\n\nvoid ultimap2_disable_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\tDbgPrint(\"ultimap2_disable_dpc for cpu %d\\n\", KeGetCurrentProcessorNumber());\n\n\t__try\n\t{\n\t\tif (DeferredContext) //only pause\n\t\t{\n\t\t\tRTIT_CTL ctl;\n\t\t\tDbgPrint(\"temp disable\\n\");\n\t\t\tctl.Value = __readmsr(IA32_RTIT_CTL);\n\t\t\tctl.Bits.TraceEn = 0;\n\t\t\t__writemsr(IA32_RTIT_CTL, ctl.Value);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"%d: disable all\\n\", KeGetCurrentProcessorNumber());\n\n\n\t\t\t__writemsr(IA32_RTIT_CTL, 0);\n\t\t\t__writemsr(IA32_RTIT_STATUS, 0);\n\t\t\t__writemsr(IA32_RTIT_CR3_MATCH, 0);\n\t\t\t__writemsr(IA32_RTIT_OUTPUT_BASE, 0);\n\t\t\t__writemsr(IA32_RTIT_OUTPUT_MASK_PTRS, 0);\n\t\t}\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"ultimap2_disable_dpc exception\");\n\t}\n}\n\nvoid ultimap2_setup_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)\n{\n\tRTIT_CTL ctl;\n\tRTIT_STATUS s;\n\tint i = -1;\n\n\n\n\t__try\n\t{\n\t\tctl.Value = __readmsr(IA32_RTIT_CTL);\n\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"ultimap2_setup_dpc: IA32_RTIT_CTL in unreadable\");\n\t\treturn;\n\t}\n\n\tctl.Bits.TraceEn = 1;\n\n\tif (LogKernelMode)\n\t\tctl.Bits.OS = 1;\n\telse\n\t\tctl.Bits.OS = 0;\n\n\tif (LogUserMode)\n\t\tctl.Bits.USER = 1;\n\telse\n\t\tctl.Bits.USER = 0;\n\n\tif (CurrentCR3)\n\t\tctl.Bits.CR3Filter = 1;\n\telse\n\t\tctl.Bits.CR3Filter = 0;\n\t\t\n\tctl.Bits.ToPA = 1;\n\tctl.Bits.TSCEn = 0;\n\tctl.Bits.DisRETC = 0;\n\tctl.Bits.BranchEn = 1;\n\n\tif (PInfo == NULL)\n\t\treturn;\n\t \n\tif (PInfo[KeGetCurrentProcessorNumber()]->ToPABuffer == NULL)\n\t{\n\t\tDbgPrint(\"ToPA for cpu %d not setup\\n\", KeGetCurrentProcessorNumber());\n\t\treturn;\n\t}\n\t\n\t__try\n\t{\n\t\tint cpunr = KeGetCurrentProcessorNumber();\n\t\ti = 0;\n\n\t\tPInfo[cpunr]->CurrentOutputBase = MmGetPhysicalAddress(PInfo[cpunr]->ToPAHeader).QuadPart;\n\n\t\t__writemsr(IA32_RTIT_OUTPUT_BASE, PInfo[cpunr]->CurrentOutputBase);\n\t\ti = 1;\n\t\t__writemsr(IA32_RTIT_OUTPUT_MASK_PTRS, 0);\n\t\ti = 2;\n\n\n\t\t__try\n\t\t{\n\t\t\t__writemsr(IA32_RTIT_CR3_MATCH, CurrentCR3);\n\t\t}\n\t\t__except (1)\n\t\t{\n\t\t\tCurrentCR3 = CurrentCR3 & 0xfffffffffffff000ULL;\n\t\t\tDbgPrint(\"Failed to set the actual CR3. Using a sanitized CR3: %llx\\n\", CurrentCR3);\n\t\t}\n\n\t\ti = 3;\n\n\t\t//ranges\n\t\tif (Ultimap2Ranges && Ultimap2RangeCount)\n\t\t{\n\t\t\t\n\t\t\tfor (i = 0; i < Ultimap2RangeCount; i++)\n\t\t\t{\n\t\t\t\tULONG msr_start = IA32_RTIT_ADDR0_A + (2 * i);\n\t\t\t\tULONG msr_stop = IA32_RTIT_ADDR0_B + (2 * i);\n\t\t\t\tUINT64 bit = 32 + (i * 4);\n\n\t\t\t\tDbgPrint(\"Range %d: (%p -> %p)\", i, (PVOID)(UINT_PTR)(Ultimap2Ranges[i].StartAddress), (PVOID)(UINT_PTR)(Ultimap2Ranges[i].EndAddress));\n\t\t\t\tDbgPrint(\"Writing range %d to msr %x and %x\", i, msr_start, msr_stop);\n\t\t\t\t__writemsr(msr_start, Ultimap2Ranges[i].StartAddress);\n\t\t\t\t__writemsr(msr_stop, Ultimap2Ranges[i].EndAddress);\n\n\t\t\t\tDbgPrint(\"bit=%d\", bit);\n\t\t\t\tDbgPrint(\"Value before=%llx\", ctl.Value);\n\t\t\t\tif (Ultimap2Ranges[i].IsStopAddress)\n\t\t\t\t\tctl.Value |= (UINT64)2ULL << bit; //TraceStop This stops all tracing on this cpu. Doesn't get reactivated\n\t\t\t\telse\n\t\t\t\t\tctl.Value |= (UINT64)1ULL << bit; //FilterEn //not supported in the latest windows build\n\n\t\t\t\tDbgPrint(\"Value after=%llx\", ctl.Value);\n\t\t\t}\n\t\t}\n\t\ti = 4;\n\n\t\t__writemsr(IA32_RTIT_STATUS, 0);\n\t\ti = 5;\n\t\t//if (KeGetCurrentProcessorNumber() == 0)\n\t\t__writemsr(IA32_RTIT_CTL, ctl.Value);\n\t\ti = 6;\n\n\t\n\t\t\t\n\t\ts.Value=__readmsr(IA32_RTIT_STATUS);\n\t\tif (s.Bits.Error)\n\t\t\tDbgPrint(\"Setup for cpu %d failed\", KeGetCurrentProcessorNumber());\n\t\telse\n\t\t\tDbgPrint(\"Setup for cpu %d succesful\", KeGetCurrentProcessorNumber());\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"Error in ultimap2_setup_dpc.  i=%d\",i);\n\t\tDbgPrint(\"ctl.Value=%p\\n\", ctl.Value);\n\t\tDbgPrint(\"CR3=%p\\n\", CurrentCR3);\n\t\t//DbgPrint(\"OutputBase=%p\", __readmsr(IA32_RTIT_OUTPUT_BASE));\n\t}\n\t\n}\n\nint getToPAHeaderCount(ULONG _BufferSize)\n{\n\treturn 1 + (_BufferSize / 4096) / 511;\n}\n\nint getToPAHeaderSize(ULONG _BufferSize)\n{\n\t//511 entries per ToPA header (4096*511=2093056 bytes per ToPA header)\n\t//BufferSize / 2093056 = Number of ToPA headers needed\n\treturn getToPAHeaderCount(_BufferSize) * 4096;\n}\n\nRTL_GENERIC_COMPARE_RESULTS NTAPI ToPACompare(__in struct _RTL_GENERIC_TABLE *Table, __in PToPA_LOOKUP FirstStruct, __in PToPA_LOOKUP SecondStruct)\n{\n\t//DbgPrint(\"Comparing %p with %p\", FirstStruct->PhysicalAddress, FirstStruct->PhysicalAddress);\n\n\tif (FirstStruct->PhysicalAddress == SecondStruct->PhysicalAddress)\n\t\treturn GenericEqual;\n\telse\n\t{\n\t\tif (SecondStruct->PhysicalAddress < FirstStruct->PhysicalAddress)\n\t\t\treturn GenericLessThan;\n\t\telse\n\t\t\treturn GenericGreaterThan;\n\t}\n}\n\nPVOID NTAPI ToPAAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in CLONG ByteSize)\n{\n\treturn ExAllocatePool(NonPagedPool, ByteSize);\n}\n\nVOID NTAPI ToPADealloc(__in struct _RTL_GENERIC_TABLE *Table, __in __drv_freesMem(Mem) __post_invalid PVOID Buffer)\n{\n\tExFreePool(Buffer);\n}\n\nvoid* setupToPA(PToPA_ENTRY *Header, PVOID *OutputBuffer, PMDL *BufferMDL, PRTL_GENERIC_TABLE *gt, ULONG _BufferSize, int NoPMI)\n{\n\tToPA_LOOKUP tl;\n\tPToPA_ENTRY r;\n\tUINT_PTR Output, Stop;\n\tULONG ToPAIndex = 0;\n\tint PABlockSize = 0;\n\tint BlockSize;\n\n\n\tPRTL_GENERIC_TABLE x;\n\tint i;\n\n\tif (singleToPASystem)\n\t{\n\t\t\n\t\tPHYSICAL_ADDRESS la,ha, boundary;\n\t\tULONG newsize;\n\n\t\tBlockSize = _BufferSize; //yup, only 1 single entry\t\n\t\t\n\n\t\t//get the closest possible\n\t\tif (BlockSize > 64 * 1024 * 1024)\n\t\t\t{\n\t\t\t\tPABlockSize = 15;\n\t\t\t\tBlockSize = 128 * 1024 * 1024;\n\t\t\t}\n\t\t\telse\n\t\t\t\tif (BlockSize > 32 * 1024 * 1024)\n\t\t\t\t{\n\t\t\t\t\tPABlockSize = 14;\n\t\t\t\t\tBlockSize = 64 * 1024 * 1024;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tif (BlockSize > 16 * 1024 * 1024)\n\t\t\t\t\t{\n\t\t\t\t\t\tPABlockSize = 13;\n\t\t\t\t\t\tBlockSize = 32 * 1024 * 1024;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tif (BlockSize > 8 * 1024 * 1024)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPABlockSize = 12;\n\t\t\t\t\t\t\tBlockSize = 16 * 1024 * 1024;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tif (BlockSize > 4 * 1024 * 1024)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tPABlockSize = 11;\n\t\t\t\t\t\t\t\tBlockSize = 8 * 1024 * 1024;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tif (BlockSize > 2 * 1024 * 1024)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tPABlockSize = 10;\n\t\t\t\t\t\t\t\t\tBlockSize = 4 * 1024 * 1024;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\tif (BlockSize > 1 * 1024 * 1024)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tPABlockSize = 9;\n\t\t\t\t\t\t\t\t\t\tBlockSize = 2 * 1024 * 1024;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\tif (BlockSize > 512 * 1024)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 8;\n\t\t\t\t\t\t\t\t\t\t\tBlockSize = 1 * 1024 * 1024;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 256 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 7;\n\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 512 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 128 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 6;\n\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 256 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 64 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 5;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 128 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 32 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 4;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 64 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 16*1024)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 3;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 32 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 8 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 2;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 16 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (BlockSize > 4 * 1024)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 1;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 8 * 1024;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPABlockSize = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tBlockSize = 4096;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t//adjust the buffersize so it is dividable by the blocksize\n\t\tnewsize = BlockSize;\n\t\t\t\n\t\tDbgPrint(\"BufferSize=%x\\n\", _BufferSize);\n\t\tDbgPrint(\"BlockSize=%x (PABlockSize=%d)\\n\", BlockSize, PABlockSize);\n\t\tDbgPrint(\"newsize=%x\\n\", newsize);\n\n\t\t\n\t\tla.QuadPart = 0;\n\t\tha.QuadPart = 0xFFFFFFFFFFFFFFFFULL;\n\t\tboundary.QuadPart = BlockSize;\n\n\t\t*OutputBuffer=MmAllocateContiguousMemorySpecifyCache(newsize, la, ha, boundary, MmCached);\n\t\t//*OutputBuffer=MmAllocateContiguousMemory(newsize, ha);\n\n\t\tDbgPrint(\"Allocated OutputBuffer at %p\", MmGetPhysicalAddress(*OutputBuffer).QuadPart);\n\n\t\t_BufferSize = newsize;\n\n\t\tif (*OutputBuffer == NULL)\n\t\t{\n\t\t\tDbgPrint(\"setupToPA (Single ToPA System): Failure allocating output buffer\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\tr = ExAllocatePool(NonPagedPool, 4096);\n\t\tif (r == NULL)\n\t\t{\n\t\t\tMmFreeContiguousMemory(*OutputBuffer);\n\t\t\t*OutputBuffer = NULL;\n\t\t\tDbgPrint(\"setupToPA (Single ToPA System): Failure allocating header for buffer\");\n\t\t\treturn NULL;\n\t\t}\n\n\t}\n\telse\n\t{\n\t\t//Not a single ToPA system\n\t\tBlockSize = 4096;\n\n\t\t*OutputBuffer = ExAllocatePool(NonPagedPool, _BufferSize);\n\t\tif (*OutputBuffer == NULL)\n\t\t{\n\t\t\tDbgPrint(\"setupToPA: Failure allocating output buffer\");\n\t\t\treturn NULL;\n\t\t}\n\n\t\tr = ExAllocatePool(NonPagedPool, getToPAHeaderSize(_BufferSize));\n\t\tif (r == NULL)\n\t\t{\n\t\t\tExFreePool(*OutputBuffer);\n\t\t\t*OutputBuffer = NULL;\n\t\t\tDbgPrint(\"setupToPA: Failure allocating header for buffer\");\n\t\t\treturn NULL;\n\t\t}\n\t}\n\t\n\n\t*Header = r;\n\n\t*gt=ExAllocatePool(NonPagedPool, sizeof(RTL_GENERIC_TABLE));\n\n\tif (*gt == NULL)\n\t{\n\t\tDbgPrint(\"Failure allocating table\");\n\t\tif (singleToPASystem)\n\t\t\tMmFreeContiguousMemory(*OutputBuffer);\n\t\telse\n\t\t\tExFreePool(*OutputBuffer);\n\t\t*OutputBuffer = NULL;\n\n\t\tExFreePool(*Header);\n\t\t*Header = NULL;\n\n\t\treturn NULL;\n\t}\n\n\tx = *gt;\n\n\tRtlInitializeGenericTable(x, ToPACompare, ToPAAlloc, ToPADealloc, NULL);\n\n\n\ttl.index = 0;\n\ttl.PhysicalAddress = MmGetPhysicalAddress(&r[0]).QuadPart;\n\tRtlInsertElementGenericTable(x, &tl, sizeof(tl), NULL);\n\n\tOutput = (UINT_PTR)*OutputBuffer;\n\tStop = Output+_BufferSize;\n\t\n\t*BufferMDL = IoAllocateMdl(*OutputBuffer, _BufferSize, FALSE, FALSE, NULL);\n\tMmBuildMdlForNonPagedPool(*BufferMDL);\n\n\tif (singleToPASystem)\n\t{\n\t\tr[0].Value = (UINT64)MmGetPhysicalAddress((PVOID)Output).QuadPart;\n\t\tr[0].Bits.Size = PABlockSize;\n\t\tif (NoPMI)\n\t\t\tr[0].Bits.INT = 0;\n\t\telse\n\t\t  r[0].Bits.INT = 1;\n\t\tr[0].Bits.STOP = 1;\n\t\t\n\t\tr[1].Value = MmGetPhysicalAddress(&r[0]).QuadPart;\n\t\tr[1].Bits.END = 1;\n\t}\n\telse\n\t{\n\t\twhile (Output < Stop)\n\t\t{\n\t\t\t//fill in the topa entries pointing to eachother\n\n\n\t\t\tif ((ToPAIndex + 1) % 512 == 0)\n\t\t\t{\n\t\t\t\t//point it to the next ToPA table\n\t\t\t\tr[ToPAIndex].Value = MmGetPhysicalAddress(&r[ToPAIndex + 1]).QuadPart;\n\t\t\t\tr[ToPAIndex].Bits.END = 1;\n\n\t\t\t\ttl.index = tl.index++;\n\t\t\t\ttl.PhysicalAddress = MmGetPhysicalAddress(&r[ToPAIndex + 1]).QuadPart;\n\t\t\t\tRtlInsertElementGenericTable(x, &tl, sizeof(tl), NULL);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tr[ToPAIndex].Value = (UINT64)MmGetPhysicalAddress((PVOID)Output).QuadPart;\n\t\t\t\tr[ToPAIndex].Bits.Size = 0;\n\t\t\t\tOutput += 4096;\n\t\t\t}\n\n\t\t\tToPAIndex++;\n\t\t}\n\n\t\tToPAIndex--;\n\t\tr[ToPAIndex].Bits.STOP = 1;\n\t\ti = (ToPAIndex * 90) / 100; //90%\n\n\t\tif ((i == (int)ToPAIndex) && (i > 0)) //don't interrupt on the very last entry (if possible)\n\t\t\ti--;\n\n\t\tif ((i > 0) && ((i + 1) % 512 == 0))\n\t\t\ti--;\n\n\n\t\tDbgPrint(\"Interrupt at index %d\", i);\n\n\t\tif (NoPMI)\n\t\t\tr[i].Bits.INT = 0;\n\t\telse\n\t\t\tr[i].Bits.INT = 1; //Interrupt after filling this entry \n\n\n\t\t//and every 2nd page after this.  (in case of a rare situation where resume is called right after suspend)\n\n\t\tif (ToPAIndex > 0)\n\t\t{\n\t\t\twhile (i < (int)(ToPAIndex - 1))\n\t\t\t{\n\t\t\t\tif (((i + 1) % 512) && (NoPMI==0))  //anything but 0\n\t\t\t\t\tr[i].Bits.INT = 1;\n\n\t\t\t\ti += 2;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn (void *)r;\n}\n\nNTSTATUS ultimap2_pause()\n{\n\tif (ultimapEnabled)\n\t{\n\t\tforEachCpu(ultimap2_disable_dpc, (PVOID)1, NULL, NULL, NULL);\n\t\tif (UltimapActive)\n\t\t{\n\t\t\tflushallbuffers = TRUE;\n\t\t\tWaitForWriteToFinishAndSwapWriteBuffers(FALSE); //write the last saved buffer\n\t\t\tWaitForWriteToFinishAndSwapWriteBuffers(FALSE); //write the current buffer\n\t\t\tflushallbuffers = FALSE;\n\t\t}\n\t}\n\n\treturn STATUS_SUCCESS; \n}\n\nNTSTATUS ultimap2_resume()\n{\n\tif ((ultimapEnabled) && (PInfo))\n\t\tforEachCpu(ultimap2_setup_dpc, NULL, NULL, NULL, NULL);\n\n\treturn STATUS_SUCCESS;\n}\n\n\n\nvoid *clear = NULL;\nBOOL RegisteredProfilerInterruptHandler;\nvoid SetupUltimap2(UINT32 PID, UINT32 BufferSize, WCHAR *Path, int rangeCount, PURANGE Ranges, int NoPMI, int UserMode, int KernelMode)\n{\n\t//for each cpu setup tracing\n\t//add the PMI interupt\n\tint i;\n\tNTSTATUS r= STATUS_UNSUCCESSFUL;\n\tint cpuid_r[4];\n\n\tif (Path)\n\t\tDbgPrint(\"SetupUltimap2(%x, %x, %S, %d, %p,%d,%d,%d\\n\", PID, BufferSize, Path, rangeCount, Ranges, NoPMI, UserMode, KernelMode);\n\telse\n\t\tDbgPrint(\"SetupUltimap2(%x, %x, %d, %p,%d,%d,%d\\n\", PID, BufferSize, rangeCount, Ranges, NoPMI, UserMode, KernelMode);\n\n\n\t__cpuidex(cpuid_r, 0x14, 0);\n\n\tif ((cpuid_r[2] & 2) == 0)\n\t{\n\t\tDbgPrint(\"Single ToPA System\");\n\t\tsingleToPASystem = TRUE;\n\t}\n\n\tNoPMIMode = NoPMI;\n\tLogKernelMode = KernelMode;\n\tLogUserMode = UserMode;\n\n\n\n\tDbgPrint(\"Path[0]=%d\\n\", Path[0]);\n\n\tSaveToFile = (Path[0] != 0);\n\n\tif (SaveToFile)\n\t{\n\t\twcsncpy(OutputPath, Path, 199);\n\t\tOutputPath[199] = 0;\n\t\tDbgPrint(\"Ultimap2: SaveToFile==TRUE:  OutputPath=%S\",OutputPath);\n\t}\n\telse\n\t{\n\t\tDbgPrint(\"Ultimap2: Runtime processing\");\n\t}\n\n\tif (rangeCount)\n\t{\n\t\tif (Ultimap2Ranges)\n\t\t{\n\t\t\tExFreePool(Ultimap2Ranges);\n\t\t\tUltimap2Ranges = NULL;\n\t\t}\n\n\t\tUltimap2Ranges = ExAllocatePool(NonPagedPool, rangeCount*sizeof(URANGE));\n\n\t\tfor (i = 0; i < rangeCount; i++)\n\t\t\tUltimap2Ranges[i] = Ranges[i];\n\n\t\tUltimap2RangeCount = rangeCount;\n\n\t}\n\telse\n\t\tUltimap2RangeCount = 0;\n\n\n\t//get the EProcess and CR3 for this PID\n\tif (PID)\n\t{\n\t\tif (PsLookupProcessByProcessId((PVOID)PID, &CurrentTarget) == STATUS_SUCCESS)\n\t\t{\n\t\t\t//todo add specific windows version checks and hardcode offsets/ or use scans\n\t\t\tif (getCR3() & 0xfff)\n\t\t\t{\n\t\t\t\tDbgPrint(\"Split kernel/usermode pages\\n\");\n\t\t\t\t//uses supervisor/usermode pagemaps\t\t\t\n\t\t\t\tCurrentCR3 = *(UINT64 *)((UINT_PTR)CurrentTarget + 0x278);\n\t\t\t\tif ((CurrentCR3 & 0xfffffffffffff000ULL) == 0)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"No usermode CR3\\n\");\n\t\t\t\t\tCurrentCR3 = *(UINT64 *)((UINT_PTR)CurrentTarget + 0x28);\n\t\t\t\t}\n\n\t\t\t\tDbgPrint(\"CurrentCR3=%llx\\n\", CurrentCR3);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tKAPC_STATE apc_state;\n\t\t\t\tRtlZeroMemory(&apc_state, sizeof(apc_state));\n\t\t\t\t__try\n\t\t\t\t{\n\t\t\t\t\tKeStackAttachProcess((PVOID)CurrentTarget, &apc_state);\n\t\t\t\t\tCurrentCR3 = getCR3();\n\t\t\t\t\tKeUnstackDetachProcess(&apc_state);\n\t\t\t\t}\n\t\t\t\t__except (1)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Failure getting CR3 for this process\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Failure getting the EProcess for pid %d\", PID);\n\t\t\treturn;\n\t\t}\n\t}\n\telse\n\t{\n\t\tCurrentTarget = 0;\n\t\tCurrentCR3 = 0;\n\t}\n\n\tDbgPrint(\"CurrentCR3=%llx\\n\", CurrentCR3);\n\n\n\n\n\n\tif ((PsSuspendProcess == NULL) || (PsResumeProcess == NULL))\n\t{\n\t\tDbgPrint(\"No Suspend/Resume support\");\n\t\treturn;\n\t}\n\t\t\n\n\tKeInitializeDpc(&RTID_DPC, RTIT_DPC_Handler, NULL);\n\t\n\tKeInitializeEvent(&FlushData, SynchronizationEvent, FALSE);\n\tKeInitializeEvent(&SuspendEvent, SynchronizationEvent, FALSE);\n\tKeInitializeMutex(&SuspendMutex, 0);\n\n\n\tUltimap2CpuCount = KeQueryMaximumProcessorCount();\n\n\tPInfo = ExAllocatePool(NonPagedPool, Ultimap2CpuCount*sizeof(PProcessorInfo));\n\tUltimap2_DataReady = ExAllocatePool(NonPagedPool, Ultimap2CpuCount*sizeof(PVOID));\n\n\tif (PInfo == NULL)\n\t{\n\t\tDbgPrint(\"PInfo alloc failed\");\n\t\treturn;\n\t}\n\n\tif (Ultimap2_DataReady == NULL)\n\t{\n\t\tDbgPrint(\"Ultimap2_DataReady alloc failed\");\n\t\treturn;\n\t}\n\n\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t{\n\t\tPInfo[i] = ExAllocatePool(NonPagedPool, sizeof(ProcessorInfo));\n\t\tRtlZeroMemory(PInfo[i], sizeof(ProcessorInfo));\n\t\t\n\t\tKeInitializeEvent(&PInfo[i]->InitiateSave, SynchronizationEvent, FALSE);\n\t\tKeInitializeEvent(&PInfo[i]->Buffer2ReadyForSwap, NotificationEvent, TRUE);\n\n\t\tsetupToPA(&PInfo[i]->ToPAHeader, &PInfo[i]->ToPABuffer, &PInfo[i]->ToPABufferMDL, &PInfo[i]->ToPALookupTable, BufferSize, NoPMI);\n\t\tsetupToPA(&PInfo[i]->ToPAHeader2, &PInfo[i]->ToPABuffer2, &PInfo[i]->ToPABuffer2MDL, &PInfo[i]->ToPALookupTable2, BufferSize, NoPMI);\n\n\t\tDbgPrint(\"cpu %d:\", i);\n\t\tDbgPrint(\"ToPAHeader=%p ToPABuffer=%p Size=%x\", PInfo[i]->ToPAHeader, PInfo[i]->ToPABuffer, BufferSize);\n\t\tDbgPrint(\"ToPAHeader2=%p ToPABuffer2=%p Size=%x\", PInfo[i]->ToPAHeader2, PInfo[i]->ToPABuffer2, BufferSize);\n\n\n\t\tKeInitializeEvent(&PInfo[i]->DataReady, SynchronizationEvent, FALSE);\n\t\tKeInitializeEvent(&PInfo[i]->DataProcessed, SynchronizationEvent, FALSE);\n\n\t\tKeInitializeEvent(&PInfo[i]->FileAccess, SynchronizationEvent, TRUE);\n\n\t\tUltimap2_DataReady[i] = &PInfo[i]->DataReady;\n\n\t\tKeInitializeDpc(&PInfo[i]->OwnDPC, SwitchToPABuffer, NULL);\n\t\tKeSetTargetProcessorDpc(&PInfo[i]->OwnDPC, (CCHAR)i);\n\t}\n\t\n\tUltimapActive = TRUE;\n\tultimapEnabled = TRUE;\n\n\tPsCreateSystemThread(&SuspendThreadHandle, 0, NULL, 0, NULL, suspendThread, NULL);\t\n\tPsCreateSystemThread(&Ultimap2Handle, 0, NULL, 0, NULL, bufferWriterThread, NULL);\n\n\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t\tPsCreateSystemThread(&PInfo[i]->WriterThreadHandle, 0, NULL, 0, NULL, WriteThreadForSpecificCPU, (PVOID)i); \n\n\tif ((NoPMI == FALSE) && (RegisteredProfilerInterruptHandler == FALSE))\n\t{\n\n\t\tDbgPrint(\"Registering PMI handler\\n\");\n\n\t\tpperfmon_hook2 = (void *)PMI;\n\n\t\tr = HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), &pperfmon_hook2); //hook the perfmon interrupt\n\t\tif (r == STATUS_SUCCESS)\n\t\t\tRegisteredProfilerInterruptHandler = TRUE;\n\n\t\tDbgPrint(\"HalSetSystemInformation returned %x\\n\", r);\n\n\t\tif (r != STATUS_SUCCESS)\n\t\t\tDbgPrint(\"Failure hooking the permon interrupt.  Ultimap2 will not be able to use interrupts until you reboot (This can happen when the perfmon interrupt is hooked more than once. It has no restore/undo hook)\\n\");\n\t}\n\n\n\n\tforEachCpu(ultimap2_setup_dpc, NULL, NULL, NULL, NULL);\n\t\n}\n\nvoid UnregisterUltimapPMI()\n{\n\tNTSTATUS r;\n\tDbgPrint(\"UnregisterUltimapPMI()\\n\");\n\tif (RegisteredProfilerInterruptHandler)\n\t{\t\t\n\t\n\t\tpperfmon_hook2 = NULL;\n\t\tr = HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), &pperfmon_hook2); \n\t\tDbgPrint(\"1: HalSetSystemInformation to disable returned %x\\n\", r);\n\n\t\tif (r == STATUS_SUCCESS)\n\t\t\treturn;\n\n\t\tr = HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), &clear); //unhook the perfmon interrupt\n\t\tDbgPrint(\"2: HalSetSystemInformation to disable returned %x\\n\", r);\n\n\t\tif (r == STATUS_SUCCESS)\n\t\t\treturn;\n\n\n\t\tr = HalSetSystemInformation(HalProfileSourceInterruptHandler, sizeof(PVOID*), 0);\n\t\tDbgPrint(\"3: HalSetSystemInformation to disable returned %x\\n\", r);\n\t\t\n\t}\n\telse\n\t\tDbgPrint(\"UnregisterUltimapPMI() not needed\\n\");\n}\n\nvoid DisableUltimap2(void)\n{\n\tint i;\n\n\tDbgPrint(\"-------------------->DisableUltimap2<------------------\");\n\n\tif (!ultimapEnabled)\n\t\treturn;\n\n\tDbgPrint(\"-------------------->DisableUltimap2:Stage 1<------------------\");\n\t\n\tforEachCpuAsync(ultimap2_disable_dpc, NULL, NULL, NULL, NULL);\n\n\t\n\tUltimapActive = FALSE;\n\t\n\tif (SuspendThreadHandle)\n\t{\n\t\tDbgPrint(\"Waiting for SuspendThreadHandle\");\n\t\tKeSetEvent(&SuspendEvent, 0, FALSE);\n\t\tZwWaitForSingleObject(SuspendThreadHandle, FALSE, NULL);\n\t\tZwClose(SuspendThreadHandle);\n\t\tSuspendThreadHandle = NULL;\n\t}\n\n\tif (PInfo)\n\t{\n\t\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t\t{\n\t\t\tKeSetEvent(&PInfo[i]->DataProcessed, 0, FALSE);\n\t\t\tKeSetEvent(&PInfo[i]->DataReady, 0, FALSE);\n\t\t}\n\t}\n\n\tif (Ultimap2Handle)\n\t{\n\t\tDbgPrint(\"Waiting for Ultimap2Handle\");\n\t\tKeSetEvent(&FlushData, 0, FALSE);\n\t\tZwWaitForSingleObject(Ultimap2Handle, FALSE, NULL);\n\t\tZwClose(Ultimap2Handle);\n\t\tUltimap2Handle = NULL;\n\t}\n\n\t\n\tif (PInfo)\n\t{\n\t\tDbgPrint(\"going to deal with the PInfo data\");\n\t\tfor (i = 0; i < Ultimap2CpuCount; i++)\n\t\t{\n\t\t\tif (PInfo[i])\n\t\t\t{\n\t\t\t\tPToPA_LOOKUP li;\n\n\n\t\t\t\tKeSetEvent(&PInfo[i]->Buffer2ReadyForSwap, 0, FALSE);\n\t\t\t\tKeSetEvent(&PInfo[i]->InitiateSave, 0, FALSE);\n\n\n\t\t\t\tDbgPrint(\"Waiting for WriterThreadHandle[%d]\",i);\n\t\t\t\tZwWaitForSingleObject(PInfo[i]->WriterThreadHandle, FALSE, NULL);\n\t\t\t\tZwClose(PInfo[i]->WriterThreadHandle);\n\t\t\t\tPInfo[i]->WriterThreadHandle = NULL;\n\n\t\t\t\tif (PInfo[i]->ToPABufferMDL)\n\t\t\t\t{\n\t\t\t\t\tIoFreeMdl(PInfo[i]->ToPABufferMDL);\n\t\t\t\t\tPInfo[i]->ToPABufferMDL = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (PInfo[i]->ToPABuffer)\n\t\t\t\t{\n\t\t\t\t\tif (singleToPASystem)\n\t\t\t\t\t\tMmFreeContiguousMemory(PInfo[i]->ToPABuffer);\n\t\t\t\t\telse\n\t\t\t\t\t\tExFreePool(PInfo[i]->ToPABuffer);\n\t\t\t\t\tPInfo[i]->ToPABuffer = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (PInfo[i]->ToPABuffer2MDL)\n\t\t\t\t{\n\t\t\t\t\tIoFreeMdl(PInfo[i]->ToPABuffer2MDL);\n\t\t\t\t\tPInfo[i]->ToPABufferMDL = NULL;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (PInfo[i]->ToPABuffer2)\n\t\t\t\t{\n\t\t\t\t\tif (singleToPASystem)\n\t\t\t\t\t\tMmFreeContiguousMemory(PInfo[i]->ToPABuffer2);\n\t\t\t\t\telse\n\t\t\t\t\t\tExFreePool(PInfo[i]->ToPABuffer2);\n\n\t\t\t\t\tPInfo[i]->ToPABuffer2 = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (PInfo[i]->ToPAHeader)\n\t\t\t\t{\n\t\t\t\t\tExFreePool(PInfo[i]->ToPAHeader);\n\t\t\t\t\tPInfo[i]->ToPAHeader = NULL;\n\t\t\t\t}\n\n\t\t\t\tif (PInfo[i]->ToPAHeader2)\n\t\t\t\t{\n\t\t\t\t\tExFreePool(PInfo[i]->ToPAHeader2);\n\t\t\t\t\tPInfo[i]->ToPAHeader2 = NULL;\n\t\t\t\t}\n\n\t\t\t\twhile (li = RtlGetElementGenericTable(PInfo[i]->ToPALookupTable, 0))\n\t\t\t\t\tRtlDeleteElementGenericTable(PInfo[i]->ToPALookupTable, li);\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\tExFreePool(PInfo[i]->ToPALookupTable);\n\t\t\t\tPInfo[i]->ToPALookupTable = NULL;\n\n\t\t\t\twhile (li = RtlGetElementGenericTable(PInfo[i]->ToPALookupTable2, 0))\n\t\t\t\t\tRtlDeleteElementGenericTable(PInfo[i]->ToPALookupTable2, li);\n\n\t\t\t\tExFreePool(PInfo[i]->ToPALookupTable2);\n\t\t\t\tPInfo[i]->ToPALookupTable2 = NULL;\n\t\t\n\n\t\t\t\tExFreePool(PInfo[i]);\n\t\t\t\tPInfo[i] = NULL;\n\t\t\t}\n\n\t\t\t\n\t\t}\n\n\t\tExFreePool(PInfo);\n\t\tExFreePool(Ultimap2_DataReady);\n\t\t\n\t\tPInfo = NULL;\n\n\t\tDbgPrint(\"Finished terminating ultimap2\");\n\t}\n\n\tif (Ultimap2Ranges)\n\t{\n\t\tExFreePool(Ultimap2Ranges);\n\t\tUltimap2Ranges = NULL;\n\n\t\tUltimap2RangeCount = 0;\n\t}\n\n\tDbgPrint(\"-------------------->DisableUltimap2:Finish<------------------\");\n\n\n}\n"
  },
  {
    "path": "src/ultimap2.h",
    "content": "#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_PERF_GLOBAL_OVF_CTRL\t0x390\n\n#define IA32_RTIT_CTL\t\t\t\t0x570\n#define IA32_RTIT_STATUS\t\t\t0x571\n#define IA32_RTIT_CR3_MATCH\t\t\t0x572\n\n#define IA32_RTIT_OUTPUT_BASE\t\t0x560\n#define IA32_RTIT_OUTPUT_MASK_PTRS  0x561\n\n#define IA32_RTIT_ADDR0_A\t\t\t0x580\n#define IA32_RTIT_ADDR0_B\t\t\t0x581\n#define IA32_RTIT_ADDR1_A\t\t\t0x582\n#define IA32_RTIT_ADDR1_B\t\t\t0x583\n#define IA32_RTIT_ADDR2_A\t\t\t0x584\n#define IA32_RTIT_ADDR2_B\t\t\t0x585\n#define IA32_RTIT_ADDR3_A\t\t\t0x586\n#define IA32_RTIT_ADDR3_B\t\t\t0x587\n\ntypedef struct\n{\n\tUINT64 StartAddress;\n\tUINT64 EndAddress;\n\tUINT64 IsStopAddress;\n} URANGE, *PURANGE;\n\n#pragma pack(push)\n#pragma pack(1)\ntypedef union {\n\t\tstruct{\n\t\t\tULONG TraceEn : 1;   //0\n\t\t\tULONG Reserved_0 : 1; //1\n\t\t\tULONG OS : 1; //2\n\t\t\tULONG USER : 1; //3\n\t\t\tULONG Reserved_1 : 2; //4,5\n\t\t\tULONG FabricEn : 1; //6\n\t\t\tULONG CR3Filter : 1; //7\n\t\t\tULONG ToPA : 1; //8\n\t\t\tULONG MTCEn : 1; //9\n\t\t\tULONG TSCEn : 1; //10\n\t\t\tULONG DisRETC : 1; //11\n\t\t\tULONG Reserved_2 : 1; //12\n\t\t\tULONG BranchEn : 1; //13\n\t\t\tULONG MTCFreq : 4; //14,15,16,17\n\t\t\tULONG Reserved_3 : 1; //18\n\t\t\tULONG CycThresh : 4; //19,20,21,22\n\t\t\tULONG Reserved_4 : 1; //32\n\t\t\tULONG PSBFreq : 4; //24,25,26,27\n\t\t\tULONG Reserved_5 : 4; //28,29,30,31\n\n\t\t\tULONG ADDR0_CFG : 4;\n\t\t\tULONG ADDR1_CFG : 4;\n\t\t\tULONG ADDR2_CFG : 4;\n\t\t\tULONG ADDR3_CFG : 4;\n\t\t\tULONG Reserved_6 : 16;\n\t\t} Bits;\n\t\tUINT64 Value;\n\t}  RTIT_CTL, *PRTIT_CTL;\n\n \ntypedef union {\n\tstruct{\n\t\tUINT64 FilterEn : 1;\n\t\tUINT64 ContextEn : 1;\n\t\tUINT64 TriggerEn : 1;\n\t\tUINT64 Reserved_1 : 1;\n\t\tUINT64 Error : 1;\n\t\tUINT64 Stopped : 1;\n\t\tUINT64 Reserved_2 : 58;\n\t} Bits;\n\tUINT64 Value;\n}  RTIT_STATUS, *PRTIT_STATUS;\n\ntypedef union {\n\tstruct{\n\t\tUINT64 END : 1;\n\t\tUINT64 Reserved_0 : 1;\n\t\tUINT64 INT : 1;\n\t\tUINT64 Reserved_1 : 1;\n\t\tUINT64 STOP : 1;\n\t\tUINT64 Reserved_2 : 1;\n\t\tUINT64 Size : 4;\n\t\tUINT64 Reserved_3 : 2;\n\t\tUINT64 PhysicalFrameNr : 52;\n\t} Bits;\n\tUINT64 Value;\n}  ToPA_ENTRY, *PToPA_ENTRY;\n\ntypedef struct{\n\tUINT64 PhysicalAddress;\n\tint index;\n} ToPA_LOOKUP, *PToPA_LOOKUP;\n\ntypedef struct\n{\n\tUINT64 Address;\n\tUINT64 Size;\n\tUINT64 CpuID;\t\n} ULTIMAP2DATAEVENT, *PULTIMAP2DATAEVENT;\n\n#pragma pack(pop)\n\nvoid SetupUltimap2(UINT32 PID, UINT32 BufferSize, WCHAR *Path, int rangeCount, PURANGE Ranges, int NoPMI, int UserMode, int KernelMode);\nvoid DisableUltimap2(void);\n\nNTSTATUS ultimap2_waitForData(ULONG timeout, PULTIMAP2DATAEVENT data);\nNTSTATUS ultimap2_continue(int cpunr);\nNTSTATUS ultimap2_flushBuffers();\n\nNTSTATUS ultimap2_pause();\nNTSTATUS ultimap2_resume();\nvoid ultimap2_LockFile(int cpunr);\nvoid ultimap2_ReleaseFile(int cpunr);\nUINT64 ultimap2_GetTraceFileSize();\nvoid ultimap2_ResetTraceFileSize();\n\nvoid UnregisterUltimapPMI();\n\ntypedef NTSTATUS(*PSSUSPENDPROCESS)(PEPROCESS p);\n\nextern PSSUSPENDPROCESS PsSuspendProcess;\nextern PSSUSPENDPROCESS PsResumeProcess;\n\n#endif"
  },
  {
    "path": "src/vmxhelper.c",
    "content": "#pragma warning( disable: 4100 4103 4213)\n#include <ntifs.h>\n#include <ntddk.h>\n#include <windef.h>\n#include \"vmxhelper.h\"\n#include \"DBKFunc.h\"\n\n#ifdef AMD64\nextern UINT_PTR dovmcall_intel(void *vmcallinfo, unsigned int level1pass);\nextern UINT_PTR dovmcall_amd(void *vmcallinfo, unsigned int level1pass);\n//dovmcall is defined in vmxhelpera.asm\n#else\n_declspec( naked ) UINT_PTR dovmcall_intel(void *vmcallinfo)\n{\n\t__asm\n\t{\n\t\tpush edx\n\t\tmov eax,[esp+8]  //+8 because of push\n\t\tmov edx, dword ptr vmx_password1\n\t\tmov ecx, dword ptr vmx_password3\n\t\t__emit 0x0f\n\t\t__emit 0x01\n\t    __emit 0xc1 //vmcall, eax will be edited, or a UD exception will be raised\n\t\tpop edx\n\t\tret 8\n\t}\n}\n\n_declspec( naked ) UINT_PTR dovmcall_amd(void *vmcallinfo)\n{\n\t__asm\n\t{\n\t\tpush edx\n\t\tmov eax,[esp+8]  \n\t\tmov edx, dword ptr  vmx_password1\n\t\tmov ecx, dword ptr  vmx_password3\n\t\t__emit 0x0f\n\t\t__emit 0x01\n\t    __emit 0xd9 //vmmcall, eax will be edited, or a UD exception will be raised\n\t\tpop edx\n\t\tret 8\n\t}\n}\n#endif\n\ntypedef UINT_PTR (DOVMCALL) (void *vmcallinfo);\nDOVMCALL *dovmcall;\n\n\nint vmx_hasredirectedint1()\n{\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_INT1REDIRECTED;\n\treturn (int)dovmcall(&vmcallinfo);\n}\n\nunsigned int vmx_getversion()\n/*\nThis will either raise a unhandled opcode exception, or return the used dbvm version\n*/\n{\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\n\tDbgPrint(\"vmx_getversion()\\n\");\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_GETVERSION;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_getRealCR0()\n{\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_GETCR0;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nUINT_PTR vmx_getRealCR3()\n{\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_GETCR3;\n\n\treturn dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_getRealCR4()\n{\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_GETCR4;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_redirect_interrupt1(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int1cs, UINT_PTR int1eip)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tunsigned int redirecttype;\n\t\tunsigned int newintvector;\n\t\tUINT64 int1eip;\n\t\tunsigned int int1cs;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tDbgPrint(\"vmx_redirect_interrupt1: redirecttype=%d int1cs=%x int1eip=%llx sizeof(vmcallinfo)=%x\\n\", redirecttype, int1cs, int1eip, sizeof(vmcallinfo));\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_REDIRECTINT1;\n\tvmcallinfo.redirecttype=redirecttype;\n\tvmcallinfo.newintvector=newintvector;\n\tvmcallinfo.int1eip=int1eip;\n\tvmcallinfo.int1cs=int1cs;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_redirect_interrupt3(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int3cs, UINT_PTR int3eip)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tunsigned int redirecttype;\n\t\tunsigned int newintvector;\n\t\tunsigned long long int3eip;\n\t\tunsigned int int3cs;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tDbgPrint(\"vmx_redirect_interrupt3: int3cs=%x int3eip=%x sizeof(vmcallinfo)=%x\\n\", int3cs, int3eip, sizeof(vmcallinfo));\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_REDIRECTINT3;\n\tvmcallinfo.redirecttype=redirecttype;\n\tvmcallinfo.newintvector=newintvector;\n\tvmcallinfo.int3eip=int3eip;\n\tvmcallinfo.int3cs=int3cs;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\n\nunsigned int vmx_redirect_interrupt14(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int14cs, UINT_PTR int14eip)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tunsigned int redirecttype;\n\t\tunsigned int newintvector;\n\t\tunsigned long long int14eip;\n\t\tunsigned int int14cs;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tDbgPrint(\"vmx_redirect_interrupt14: int14cs=%x int14eip=%x sizeof(vmcallinfo)=%x\\n\", int14cs, int14eip, sizeof(vmcallinfo));\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_REDIRECTINT14;\n\tvmcallinfo.redirecttype=redirecttype;\n\tvmcallinfo.newintvector=newintvector;\n\tvmcallinfo.int14eip=int14eip;\n\tvmcallinfo.int14cs=int14cs;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_register_cr3_callback(unsigned int cs, unsigned int eip, unsigned int ss, unsigned int esp)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tunsigned int callbacktype; //32-bit for this driver, so always 0\n\t\tunsigned long long callback_eip;\n\t\tunsigned int callback_cs;\n\t\tunsigned long long callback_esp;\n\t\tunsigned int callback_ss;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_REGISTER_CR3_EDIT_CALLBACK;\n\tvmcallinfo.callbacktype=0;\n\tvmcallinfo.callback_eip=eip;\n\tvmcallinfo.callback_cs=cs;\n\tvmcallinfo.callback_esp=esp;\n\tvmcallinfo.callback_ss=ss;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_exit_cr3_callback(unsigned int newcr3)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tunsigned long long newcr3;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\t//DbgPrint(\"vmx_exit_cr3_callback(%x)\\n\",newcr3);\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_RETURN_FROM_CR3_EDIT_CALLBACK;\n\tvmcallinfo.newcr3=newcr3;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\n\nunsigned int vmx_watch_pagewrites(UINT64 PhysicalAddress, int Size, int Options, int MaxEntryCount)\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_FINDWHATWRITESPAGE\n\t\tUINT64 PhysicalAddress;\n\t\tint Size;\n\t\tint Options; //binary.  \n\t\t             //  Bit 0: 0=Log RIP once. 1=Log RIP multiple times (when different registers)\n\t\t\t\t\t //  Bit 1: 0=Only log given Physical Address. 1=Log everything in the page(s) that is/are affected\n\t\t             //  Bit 2: 0=Do not save FPU/XMM data, 1=Also save FPU/XMM data\n\t\t\t\t\t //  Bit 3: 0=Do not save a stack snapshot, 1=Save stack snapshot\n\t\t             //  Bit 4: 0=No PMI when full, 1=PMI when full\n\t\tint MaxEntryCount; //how much memory should DBVM allocate for the buffer \t\t\n\t\tint UsePMI; //trigger a PMI interrupt when full (so you don't lose info)\n\t\tint ID; //ID describing this watcher for this CPU (keep track of this on a per cpu basis if you do more than 1)\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_WATCH_WRITES;\n\tvmcallinfo.PhysicalAddress = PhysicalAddress;\n\n\tif (((PhysicalAddress + Size) & 0xfffffffffffff000ULL) > PhysicalAddress) //passes a pageboundary, strip of the excess\n\t\tSize = 0x1000 - (PhysicalAddress & 0xfff);\n\t\n\tvmcallinfo.Size = Size;\n\tvmcallinfo.Options = Options;\n\tvmcallinfo.MaxEntryCount = MaxEntryCount;\n\tvmcallinfo.ID = 0xffffffff;\n\n\tdovmcall(&vmcallinfo);;\n\treturn vmcallinfo.ID;\n}\n\nunsigned int vmx_watch_pageaccess(UINT64 PhysicalAddress, int Size, int Options, int MaxEntryCount)\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_FINDWHATWRITESPAGE\n\t\tUINT64 PhysicalAddress;\n\t\tint Size;\n\t\tint Options; //binary.  \n\t\t//  Bit 0: 0=Log RIP once. 1=Log RIP multiple times (when different registers)\n\t\t//  Bit 1: 0=Only log given Physical Address. 1=Log everything in the page(s) that is/are affected\n\t\t//  Bit 2: 0=Do not save FPU/XMM data, 1=Also save FPU/XMM data\n\t\t//  Bit 3: 0=Do not save a stack snapshot, 1=Save stack snapshot\n\t\t//  Bit 4: 0=No PMI when full, 1=PMI when full\n\t\tint MaxEntryCount; //how much memory should DBVM allocate for the buffer \t\t\n\t\t\n\t\tint ID; //ID describing this watcher for this CPU (keep track of this on a per cpu basis if you do more than 1)\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_WATCH_READS;\n\tvmcallinfo.PhysicalAddress = PhysicalAddress;\n\n\tif (((PhysicalAddress + Size) & 0xfffffffffffff000ULL) > PhysicalAddress) //passes a pageboundary, strip of the excess\n\t\tSize = 0x1000 - (PhysicalAddress & 0xfff);\n\n\tvmcallinfo.Size = Size;\n\tvmcallinfo.Options = Options;\n\tvmcallinfo.MaxEntryCount = MaxEntryCount;\n\tvmcallinfo.ID = 0xffffffff;\n\n\tdovmcall(&vmcallinfo);;\n\treturn vmcallinfo.ID;\n}\n\nunsigned int vmx_watch_retreivelog(int ID, PPageEventListDescriptor result, int *resultsize)\n/*\nUsed to retrieve both read and write watches\n*/\n{\n\tunsigned int r;\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_FINDWHATWRITESPAGE\n\t\tDWORD ID;\n\t\tUINT64 results;\t\t\n\t\tint resultsize;\n\t\tint copied; //the number of bytes copied so far (This is a repeating instruction)\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_WATCH_RETRIEVELOG;\n\n\tvmcallinfo.ID = ID;\n\tvmcallinfo.results = (UINT64)result;\n\tvmcallinfo.resultsize = *resultsize;\n\tr=(unsigned int)dovmcall(&vmcallinfo);;\n\t*resultsize = vmcallinfo.resultsize;\n\treturn r; //returns 0 on success, 1 on too small buffer.  buffersize contains the size in both cases\n}\n\nunsigned int vmx_watch_delete(int ID)\n{\n\t//disables the watch operation\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_FINDWHATWRITESPAGE\n\t\tDWORD ID;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_WATCH_DELETE;\n\n\tvmcallinfo.ID = ID;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\nunsigned int vmx_cloak_activate(QWORD physicalPage)\n/*\n Copies a page to a shadow page and marks the original page as execute only (or no access at all if the cpu does not support it)\n\n On read/write the shadow page's contents are read/written, but execute will execute the original page\n\n To access the contents of the original(executing) page use vmx_cloak_readOriginal and vmx_cloak_writeOriginal\n\n possible issue: the read and execute operation can be in the same page at the same time, so when the page is swapped by the contents of the unmodified page to facilitate the read of unmodified memory\n                 the unmodified code will execute as well (integrity check checking itself)\n\n possible solutions:  do not cloak pages with integrity checks and then edit the integrity check willy nilly\n                      use single byte edits (e.g int3 bps to facilitate changes)\n\t\t\t\t\t  make edits so integrity check routines are jumped over\n\n Note: Affects ALL cpu's so only needs to be called once\n*/\n{\n\t//disables the watch operation\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_CLOAK_ACTIVATE\n\t\tQWORD physicalAddress;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CLOAK_ACTIVATE;\n\tvmcallinfo.physicalAddress = physicalPage;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\n//todo: vmx_cload_passthrougwrites() : lets you specify which write operation locations can be passed through to the execute page\n\nunsigned int vmx_cloak_deactivate(QWORD physicalPage)\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_CLOAK_ACTIVATE\n\t\tQWORD physicalAddress;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CLOAK_DEACTIVATE;\n\tvmcallinfo.physicalAddress = physicalPage;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\nunsigned int vmx_cloak_readOriginal(QWORD physicalPage, void *destination)\n/*\nreads 4096 bytes from the cloaked page and put it into original (original must be able to hold 4096 bytes, and preferably on a page boundary)\n*/\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; \n\t\tQWORD physicalAddress;\n\t\tQWORD destination;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CLOAK_READORIGINAL;\n\tvmcallinfo.physicalAddress = physicalPage;\n\tvmcallinfo.destination = (QWORD)destination;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\nunsigned int vmx_cloak_writeOriginal(QWORD physicalPage, void *source)\n/*\nreads 4096 bytes from the cloaked page and put it into original (original must be able to hold 4096 bytes, and preferably on a page boundary)\n*/\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_CLOAK_ACTIVATE\n\t\tQWORD physicalAddress;\n\t\tQWORD source;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CLOAK_WRITEORIGINAL;\n\tvmcallinfo.physicalAddress = physicalPage;\n\tvmcallinfo.source = (QWORD)source;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\nunsigned int vmx_changeregonbp(QWORD physicalAddress, CHANGEREGONBPINFO *changereginfo)\n/*\nplaces an int3 bp at the given address, and on execution changes the state to the given state\nif a cloaked page is given, the BP will be set in the executing page\n\nif no cloaked page is given, cloak it (needed for the single step if no IP change is done)\n\nNote: effects ALL cpu's\n*/\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command; //VMCALL_CLOAK_CHANGEREGONBP\n\t\tQWORD physicalAddress;\n\t\tCHANGEREGONBPINFO changereginfo;\t\t\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CLOAK_CHANGEREGONBP;\n\tvmcallinfo.physicalAddress = physicalAddress;\n\tvmcallinfo.changereginfo = *changereginfo;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);; //0 on success, anything else fail\n}\n\n\n\n\nunsigned int vmx_ultimap_getDebugInfo(PULTIMAPDEBUGINFO debuginfo)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\t\n\t\tULTIMAPDEBUGINFO debuginfo;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tunsigned int i;\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_ULTIMAP_DEBUGINFO;\n\n\ti=(unsigned int)dovmcall(&vmcallinfo);;\n\t*debuginfo=vmcallinfo.debuginfo;\n\n\treturn i;\n}\n\nunsigned int vmx_ultimap(UINT_PTR cr3towatch, UINT64 debugctl_value, void *storeaddress)\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tUINT64 cr3;\n\t\tUINT64 debugctl;\n\t\tUINT64 storeaddress;\t\t\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_ULTIMAP;\n\tvmcallinfo.cr3=(UINT64)cr3towatch;\n\tvmcallinfo.debugctl=(UINT64)debugctl_value;\n\tvmcallinfo.storeaddress=(UINT64)(UINT_PTR)storeaddress;\n\n\tDbgPrint(\"vmx_ultimap(%I64x, %I64x, %I64x)\\n\", (UINT64)vmcallinfo.cr3, (UINT64)vmcallinfo.debugctl, vmcallinfo.storeaddress);\n\t\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_ultimap_disable()\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_ULTIMAP_DISABLE;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_ultimap_pause()\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_ULTIMAP_PAUSE;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_ultimap_resume()\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_ULTIMAP_RESUME;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_disable_dataPageFaults()\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_DISABLE_DATAPAGEFAULTS;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_enable_dataPageFaults()\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_ENABLE_DATAPAGEFAULTS;\n\n\treturn (unsigned int)dovmcall(&vmcallinfo);;\n}\n\nUINT_PTR vmx_getLastSkippedPageFault()\n{\n\t#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n\t#pragma pack()\n\n\tvmcallinfo.structsize=sizeof(vmcallinfo);\n\tvmcallinfo.level2pass=vmx_password2;\n\tvmcallinfo.command=VMCALL_GETLASTSKIPPEDPAGEFAULT;\n\n\treturn (UINT_PTR)dovmcall(&vmcallinfo);;\n}\n\nunsigned int vmx_add_memory(UINT64 *list, int count)\n{\n\tint r=0;\n\tint j=0;\n#pragma pack(1)\n\ttypedef struct _vmcall_add_memory\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t\tUINT64 PhysicalPages[0];\n\t} AddMemoryInfoCall, *PAddMemoryInfoCall;\n#pragma pack()\n\tPAddMemoryInfoCall vmcallinfo=ExAllocatePool(NonPagedPool, sizeof(AddMemoryInfoCall) + count * sizeof(UINT64));\n\n\n\tDbgPrint(\"vmx_add_memory(%p,%d)\\n\", list, count);\n\tDbgPrint(\"vmx_add_memory(vmx_password1=%x,vmx_password2=%x)\\n\", vmx_password1, vmx_password2);\n\n\tDbgPrint(\"structsize at offset %d\\n\", (UINT64)(&vmcallinfo->structsize) - (UINT64)vmcallinfo);\n\tDbgPrint(\"level2pass at offset %d\\n\", (UINT64)(&vmcallinfo->level2pass) - (UINT64)vmcallinfo);\n\tDbgPrint(\"command at offset %d\\n\", (UINT64)(&vmcallinfo->command) - (UINT64)vmcallinfo);\n\tDbgPrint(\"PhysicalPages[0] at offset %d\\n\", (UINT64)(&vmcallinfo->PhysicalPages[0]) - (UINT64)vmcallinfo);\n\tDbgPrint(\"PhysicalPages[1] at offset %d\\n\", (UINT64)(&vmcallinfo->PhysicalPages[1]) - (UINT64)vmcallinfo);\n\n\n\t__try\n\t{\n\t\tint i;\n\t\tvmcallinfo->structsize = sizeof(AddMemoryInfoCall) + count * sizeof(UINT64);\n\t\tDbgPrint(\"vmcallinfo->structsize=%d\\n\", vmcallinfo->structsize);\n\t\tvmcallinfo->level2pass = vmx_password2;\n\t\tvmcallinfo->command = VMCALL_ADD_MEMORY;\n\t\tj = 1;\n\t\tfor (i = 0; i < count; i++)\n\t\t{\n\t\t\tvmcallinfo->PhysicalPages[i] = list[i];\n\t\t}\n\t\tj = 2;\n\n\t\tr = (unsigned int)dovmcall(vmcallinfo);\n\t\tj = 3; //never\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"vmx_add_memory(%p,%d) gave an exception at part %d with exception code %x\\n\", list, count, j, GetExceptionCode());\t\t\n\t\t\n\t\tr = 0x100;\n\t}\n\n\tExFreePool(vmcallinfo);\n\treturn r;\n\t\n}\n\nint vmx_causedCurrentDebugBreak()\n{\n#pragma pack(1)\n\tstruct\n\t{\n\t\tunsigned int structsize;\n\t\tunsigned int level2pass;\n\t\tunsigned int command;\n\t} vmcallinfo;\n#pragma pack()\n\n\tvmcallinfo.structsize = sizeof(vmcallinfo);\n\tvmcallinfo.level2pass = vmx_password2;\n\tvmcallinfo.command = VMCALL_CAUSEDDEBUGBREAK;\n\n\treturn (int)dovmcall(&vmcallinfo);;\n}\n\nvoid vmx_init_dovmcall(int isIntel)\n{\n\tif (isIntel)\n\t\t(void *)dovmcall=(void *)dovmcall_intel;\n\telse\n\t\t(void *)dovmcall=(void *)dovmcall_amd;\n\n}\n\n\n//DBVMInterruptService\n"
  },
  {
    "path": "src/vmxhelper.h",
    "content": "#ifndef VMXHELPER_H\n#define VMXHELPER_H\n\n#pragma warning( disable: 4200)\n\n#define VMCALL_GETVERSION 0\n#define VMCALL_CHANGEPASSWORD 1\n#define VMCALL_READ_PHYSICAL_MEMORY 3\n#define VMCALL_WRITE_PHYSICAL_MEMORY 4\n#define VMCALL_REDIRECTINT1 9\n#define VMCALL_INT1REDIRECTED 10\n#define VMCALL_CHANGESELECTORS 12\n#define VMCALL_BLOCK_INTERRUPTS 13\n#define VMCALL_RESTORE_INTERRUPTS 14\n\n#define VMCALL_REGISTER_CR3_EDIT_CALLBACK 16\n#define VMCALL_RETURN_FROM_CR3_EDIT_CALLBACK 17\n#define VMCALL_GETCR0 18\n#define VMCALL_GETCR3 19\n#define VMCALL_GETCR4 20\n#define VMCALL_RAISEPRIVILEGE 21\n#define VMCALL_REDIRECTINT14 22\n#define VMCALL_INT14REDIRECTED 23\n#define VMCALL_REDIRECTINT3 24\n#define VMCALL_INT3REDIRECTED 25\n\n//dbvm v6+\n#define VMCALL_READMSR 26\n#define VMCALL_WRITEMSR 27\n\n#define VMCALL_ULTIMAP 28\n#define VMCALL_ULTIMAP_DISABLE 29\n\n\n//dbvm v7+\n#define VMCALL_SWITCH_TO_KERNELMODE 30\n\n#define VMCALL_DISABLE_DATAPAGEFAULTS 31\n#define VMCALL_ENABLE_DATAPAGEFAULTS 32\n#define VMCALL_GETLASTSKIPPEDPAGEFAULT 33\n\n#define VMCALL_ULTIMAP_PAUSE 34\n#define VMCALL_ULTIMAP_RESUME 35\n\n#define VMCALL_ULTIMAP_DEBUGINFO 36\n\n\n//dbvm v10+\n#define VMCALL_WATCH_WRITES 41\n#define VMCALL_WATCH_READS 41\n#define VMCALL_WATCH_RETRIEVELOG 43\n#define VMCALL_WATCH_DELETE 44\n\n#define VMCALL_CLOAK_ACTIVATE 45\n#define VMCALL_CLOAK_DEACTIVATE 46\n#define VMCALL_CLOAK_READORIGINAL 47\n#define VMCALL_CLOAK_WRITEORIGINAL 48\n\n#define VMCALL_CLOAK_CHANGEREGONBP 49\n\n#define VMCALL_ADD_MEMORY 57\n\n#define VMCALL_CAUSEDDEBUGBREAK 63\n\n\ntypedef UINT64 QWORD;\n\ntypedef struct _CHANGEREGONBPINFO\n{\n\tstruct\n\t{\n\t\tunsigned changeRAX : 1;\n\t\tunsigned changeRBX : 1;\n\t\tunsigned changeRCX : 1;\n\t\tunsigned changeRDX : 1;\n\t\tunsigned changeRSI : 1;\n\t\tunsigned changeRDI : 1;\n\t\tunsigned changeRBP : 1;\n\t\tunsigned changeRSP : 1;\n\t\tunsigned changeRIP : 1;\n\t\tunsigned changeR8 : 1;\n\t\tunsigned changeR9 : 1;\n\t\tunsigned changeR10 : 1;\n\t\tunsigned changeR11 : 1;\n\t\tunsigned changeR12 : 1;\n\t\tunsigned changeR13 : 1;\n\t\tunsigned changeR14 : 1;\n\t\tunsigned changeR15 : 1;\n\t\t//flags reg:\n\t\tunsigned changeCF : 1;\n\t\tunsigned changePF : 1;\n\t\tunsigned changeAF : 1;\n\t\tunsigned changeZF : 1;\n\t\tunsigned changeSF : 1;\n\t\tunsigned changeOF : 1;\n\t\tunsigned newCF : 1;\n\t\tunsigned newPF : 1;\n\t\tunsigned newAF : 1;\n\t\tunsigned newZF : 1;\n\t\tunsigned newSF : 1;\n\t\tunsigned newOF : 1;\n\t\tunsigned reserved : 3;\n\t} Flags;\n\n\tQWORD newRAX;\n\tQWORD newRBX;\n\tQWORD newRCX;\n\tQWORD newRDX;\n\tQWORD newRSI;\n\tQWORD newRDI;\n\tQWORD newRBP;\n\tQWORD newRSP;\n\tQWORD newRIP;\n\tQWORD newR8;\n\tQWORD newR9;\n\tQWORD newR10;\n\tQWORD newR11;\n\tQWORD newR12;\n\tQWORD newR13;\n\tQWORD newR14;\n\tQWORD newR15;\n} CHANGEREGONBPINFO, *PCHANGEREGONBPINFO;\n\ntypedef struct _pageevent_basic\n{\n\tQWORD VirtualAddress;\n\tQWORD PhysicalAddress;\n\tQWORD CR3; //in case of kernel or other process\n\tQWORD FSBASE;\n\tQWORD GSBASE;\n\tQWORD FLAGS;\n\tQWORD RAX;\n\tQWORD RBX;\n\tQWORD RCX;\n\tQWORD RDX;\n\tQWORD RSI;\n\tQWORD RDI;\n\tQWORD R8;\n\tQWORD R9;\n\tQWORD R10;\n\tQWORD R11;\n\tQWORD R12;\n\tQWORD R13;\n\tQWORD R14;\n\tQWORD R15;\n\tQWORD RBP; \n\tQWORD RSP; \n\tQWORD RIP;\n\tWORD CS;\n\tWORD DS;\n\tWORD ES;\n\tWORD SS;\n\tWORD FS;\n\tWORD GS;\n\tDWORD Count;\n} PageEventBasic, *PPageEventBasic;\n\ntypedef struct _fxsave64\n{\n\tWORD FCW;\n\tWORD FSW;\n\tBYTE FTW;\n\tBYTE Reserved;\n\tWORD FOP;\n\tUINT64 FPU_IP;\n\tUINT64 FPU_DP;\n\tDWORD MXCSR;\n\tDWORD MXCSR_MASK;\n\tQWORD FP_MM0;\n\tQWORD FP_MM0_H;\n\tQWORD FP_MM1;\n\tQWORD FP_MM1_H;\n\tQWORD FP_MM2;\n\tQWORD FP_MM2_H;\n\tQWORD FP_MM3;\n\tQWORD FP_MM3_H;\n\tQWORD FP_MM4;\n\tQWORD FP_MM4_H;\n\tQWORD FP_MM5;\n\tQWORD FP_MM5_H;\n\tQWORD FP_MM6;\n\tQWORD FP_MM6_H;\n\tQWORD FP_MM7;\n\tQWORD FP_MM7_H;\n\tQWORD XMM0;\n\tQWORD XMM0_H;\n\tQWORD XMM1;\n\tQWORD XMM1_H;\n\tQWORD XMM2;\n\tQWORD XMM2_H;\n\tQWORD XMM3;\n\tQWORD XMM3_H;\n\tQWORD XMM4;\n\tQWORD XMM4_H;\n\tQWORD XMM5;\n\tQWORD XMM5_H;\n\tQWORD XMM6;\n\tQWORD XMM6_H;\n\tQWORD XMM7;\n\tQWORD XMM7_H;\n\tQWORD XMM8;\n\tQWORD XMM8_H;\n\tQWORD XMM9;\n\tQWORD XMM9_H;\n\tQWORD XMM10;\n\tQWORD XMM10_H;\n\tQWORD XMM11;\n\tQWORD XMM11_H;\n\tQWORD XMM12;\n\tQWORD XMM12_H;\n\tQWORD XMM13;\n\tQWORD XMM13_H;\n\tQWORD XMM14;\n\tQWORD XMM14_H;\n\tQWORD XMM15;\n\tQWORD XMM15_H;\n\tQWORD res1;\n\tQWORD res1_H;\n\tQWORD res2;\n\tQWORD res2_H;\n\tQWORD res3;\n\tQWORD res3_H;\n\tQWORD res4;\n\tQWORD res4_H;\n\tQWORD res5;\n\tQWORD res5_H;\n\tQWORD res6;\n\tQWORD res6_H;\n} FXSAVE64, *PFXSAVE64;\n\ntypedef struct _pageevent_extended\n{\n\tPageEventBasic basic;\n\tFXSAVE64 fpudata;\n} PageEventExtended, *PPageEventExtended;\n\ntypedef struct _pageevent_basic_withstack\n{\n\tPageEventBasic basic;\n\tunsigned char stack[4096];\n} PageEventBasicWithStack, *PPageEventBasicWithStack;\n\ntypedef struct _pageevent_extended_withstack\n{\n\tPageEventBasic basic;\n\tFXSAVE64 fpudata;\n\tunsigned char stack[4096];\n} PageEventExtendedWithStack, *PPageEventExtendedWithStack;\n\ntypedef struct _pageeventlistdescriptor\n{\n\tDWORD ID;\n\tDWORD maxSize;\n\tDWORD numberOfEntries;\n\tDWORD missedEntries;\n\tDWORD entryType; //0=PageEventBasic, 1=PageEventExtended, 2=PageEventBasicWithStack, 3=PageEventExtendedWithStack\n\tunion\n\t{\n\t\tPageEventBasic basic[0];\n\t\tPageEventExtended extended[0];\n\t\tPageEventBasicWithStack basics[0];\n\t\tPageEventExtendedWithStack extendeds[0];\n\t} pe;\n\n} PageEventListDescriptor, *PPageEventListDescriptor;\n\n\ntypedef enum {virt_differentInterrupt=0, virt_emulateInterrupt=1} VMXInterruptRedirectType;\n\ntypedef struct\n{\n\tUINT64 Active; //set to 1 when active\n\tUINT64 CR3; //Holds the CR3 value to watch taskswitch to and from\n\tUINT64 DEBUGCTL; //Holds the DebugCTL value to set when inside the target process\n\tUINT64 DS_AREA; //Holds the DS_AREA to set when\n\tUINT64 OriginalDebugCTL; //When inside the target process this holds the debugctl that was set before entering. Return this on readMSR (and set with writeMSR when inside the process)\n\tUINT64 OriginalDS_AREA; //When inside the target process this holds the DS_AREA that was set before entering. Return this with readMSR ('''')\n\tUINT64 CR3_switchcount;\n\tUINT64 CR3_switchcount2;\n\tUINT64 LastOldCR3;\n\tUINT64 LastNewCR3;\n} ULTIMAPDEBUGINFO, *PULTIMAPDEBUGINFO;\n\n\nunsigned int vmcall(void *vmcallinfo, unsigned int level1pass);\n\nunsigned int vmx_getversion();\nunsigned int vmx_getRealCR0();\nUINT_PTR vmx_getRealCR3();\nunsigned int vmx_getRealCR4();\n\nunsigned int vmx_redirect_interrupt1(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int1cs, UINT_PTR int1eip);\nunsigned int vmx_redirect_interrupt3(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int3cs, UINT_PTR int3eip);\nunsigned int vmx_redirect_interrupt14(VMXInterruptRedirectType redirecttype, unsigned int newintvector, unsigned int int14cs, UINT_PTR int14eip);\n\nunsigned int vmx_register_cr3_callback(unsigned int cs, unsigned int eip, unsigned int ss, unsigned int esp);\nunsigned int vmx_exit_cr3_callback(unsigned int newcr3);\n\nunsigned int vmx_ultimap(UINT_PTR cr3towatch, UINT64 debugctl_value, void *storeaddress);\nunsigned int vmx_ultimap_disable();\n\nunsigned int vmx_ultimap_pause();\nunsigned int vmx_ultimap_resume();\n\n\nunsigned int vmx_ultimap_getDebugInfo(PULTIMAPDEBUGINFO debuginfo);\n\nunsigned int vmxusable;\nUINT64     vmx_password1;\nunsigned int vmx_password2;\nUINT64      vmx_password3;\nunsigned int vmx_version;\n\nUINT_PTR vmx_getLastSkippedPageFault();\nunsigned int vmx_enable_dataPageFaults();\nunsigned int vmx_disable_dataPageFaults();\n\nunsigned int vmx_add_memory(UINT64 *list, int count);\n\nint vmx_causedCurrentDebugBreak();\n\nvoid vmx_init_dovmcall(int isIntel);\n\n#endif"
  },
  {
    "path": "src/vmxoffload.c",
    "content": "/*\nsets up all the needed data structures \ncopies dbvm into physical memory\njumps into dbvm's os entry point\n\n*/\n#pragma warning( disable: 4100 4103 4152 4189 4456)\n\n#ifndef AMD64\n#pragma warning( disable: 4740)\n#endif\n\n#include <ntifs.h>\n#include <windef.h>\n\n#include \"dbkfunc.h\"\n#include \"vmxoffload.h\"\n#include \"vmxhelper.h\"\n\n#ifdef TOBESIGNED\n#include \"sigcheck.h\"\n#endif\n\nunsigned char *vmm;\n\n#pragma pack(2) \nstruct\n{\n\tWORD limit;\n\tUINT_PTR base;\n} NewGDTDescriptor;\n#pragma pack()\n\n#pragma pack(1) \ntypedef struct _INITVARS\n{\n\tUINT64 loadedOS; //physical address of the loadedOS section\n\tUINT64 vmmstart; //physical address of virtual address 00400000 (obsoletish...)\n\tUINT64 pagedirlvl4; //Virtual address of the pml4 table (the virtual memory after this until the next 4MB alignment is free to use)\n\tUINT64 nextstack; //The virtual address of the stack for the next CPU (vmloader only sets it up when 0)\n\tUINT64 extramemory; //Physical address of some extra initial memory (physically contiguous)\n\tUINT64 extramemorysize; //the number of pages that extramemory spans\n\tUINT64 contiguousmemory; //Physical address of some extra initial memory (physically contiguous)\n\tUINT64 contiguousmemorysize; //the number of pages that extramemory spans\n} INITVARS, *PINITVARS;\n\n\ntypedef struct\n{ //ok, everything uint64, I hate these incompatibilities with alignment between gcc and ms c\n\tUINT64\t\tcpucount;\n\tUINT64\t\toriginalEFER;\n\tUINT64\t\toriginalLME;\n\tUINT64\t\tidtbase;\n\tUINT64\t\tidtlimit;\n\tUINT64\t\tgdtbase;\n\tUINT64\t\tgdtlimit;\n\tUINT64\t\tcr0;\n\tUINT64\t\tcr2;\n\tUINT64\t\tcr3;\n\tUINT64\t\tcr4;\n\tUINT64\t\tdr7;\n\tUINT64\t\trip;\n\n\tUINT64\t\trax;\n\tUINT64\t\trbx;\n\tUINT64\t\trcx;\n\tUINT64\t\trdx;\n\tUINT64\t\trsi;\n\tUINT64\t\trdi;\n\tUINT64\t\trbp;\n\tUINT64\t\trsp;\n\tUINT64\t\tr8;\n\tUINT64\t\tr9;\n\tUINT64\t\tr10;\n\tUINT64\t\tr11;\n\tUINT64\t\tr12;\n\tUINT64\t\tr13;\n\tUINT64\t\tr14;\n\tUINT64\t\tr15;\n\n\tUINT64\t\trflags;\n\tUINT64\t\tcs;\n\tUINT64\t\tss;\n\tUINT64\t\tds;\n\tUINT64\t\tes;\n\tUINT64\t\tfs;\n\tUINT64\t\tgs;\n\tUINT64\t\ttr;\n\tUINT64\t\tldt;\n\n\tUINT64\t\tcs_AccessRights;\n\tUINT64\t\tss_AccessRights;\n\tUINT64\t\tds_AccessRights;\n\tUINT64\t\tes_AccessRights;\n\tUINT64\t\tfs_AccessRights;\n\tUINT64\t\tgs_AccessRights;\n\n\tUINT64\t\tcs_Limit;\n\tUINT64\t\tss_Limit;\n\tUINT64\t\tds_Limit;\n\tUINT64\t\tes_Limit;\n\tUINT64\t\tfs_Limit;\n\tUINT64\t\tgs_Limit;\n\t\n\tUINT64\t\tfsbase;\n\tUINT64\t\tgsbase;\n\n} OriginalState, *POriginalState;\n#pragma pack() \n\nunsigned char *enterVMM2;\nPMDL enterVMM2MDL;\nPOriginalState originalstate; //one of the reasons why multiple cpu's don't start at exactly the same time\nPMDL originalstateMDL;\n\nUINT_PTR enterVMM2PA;\n\nPVOID TemporaryPagingSetup;\nUINT_PTR TemporaryPagingSetupPA;\nPMDL TemporaryPagingSetupMDL;\n\nUINT_PTR DBVMPML4PA;\nUINT_PTR originalstatePA;\nUINT_PTR NewGDTDescriptorVA;\nUINT_PTR vmmPA;\n\nint initializedvmm=0;\n\nKSPIN_LOCK LoadedOSSpinLock; //spinlock to prevent LoadedOS from being overwritten (should not be needed, but just being safe)\n\n#ifdef AMD64\nextern void enterVMM( void ); //declared in vmxoffloada.asm\nextern void enterVMMPrologue(void);\nextern void enterVMMEpilogue(void);\nextern void JTAGBP(void);\n#else\n_declspec( naked ) void enterVMM( void )\n{\n\n\t__asm\n\t{\nbegin:\n\t\txchg bx,bx //trigger bochs breakpoint\n\n\t\t//setup the GDT\n\t\tlgdt [ebx] //ebx is the 'virtual address' so just do that before disabling paging ok...\n\n\t\t//switch to identify mapped pagetable\n\t\tmov cr3,edx\n\t\tjmp short weee\nweee:\n\t\t\n\n\n\t\t//now jump to the physical address (identity mapped to the same virtual address)\n\t\tmov eax,secondentry\n\t    sub eax,begin\n\t\tadd eax,esi\n\t\tjmp eax\n\nsecondentry:\n\n\t\t\n\n\t\t//disable paging\t\t\n\t\tmov eax,cr0\n\t\tand eax,0x7FFFFFFF\n\t\tmov cr0,eax\n\t\t//paging off\n\t\tjmp short weee2\nweee2:\n\n\t\t\n\n\t\t//load paging for vmm (but don't apply yet, in nonpaged mode)\n\t\tmov cr3,ecx\n\n\t\t//enable PAE and PSE\n\t\tmov eax,0x30\n\t\t__emit 0x0f  //-|\n\t\t__emit 0x22  //-|-mov cr4,eax  (still WTF's me that visual studio doesn't know about cr4)\n\t\t__emit 0xe0  //-|\n\n\n\t\tmov ecx,0xc0000080 //enable efer_lme\n\t\trdmsr\n\t\tor eax,0x100\n\t\twrmsr\n\n\t\t//mov eax,cr0\t\t\n\t\t//or eax,0x80000020 //re-enable pg (and ne to be sure)\n\t\t//edit, who cares, fuck the original state, it's my own state now\n\t\tmov eax,0x80000021\n\t\tmov cr0,eax\n\n\t\tmov eax,edi //tell dbvm it's an OS entry and a that location the start info is\n\t\tmov ebx,ebp //tell vmmPA\n\n\t\t__emit 0xea  //-|\n\t\t__emit 0x00  //-|\n\t\t__emit 0x00  //-|\n\t\t__emit 0x40  //-|JMP FAR 0x50:0x00400000\n\t\t__emit 0x00  //-|\n\t\t__emit 0x50  //-|\n\t\t__emit 0x00  //-|\n\n\t\t__emit 0xce\n\t\t__emit 0xce\n\t\t__emit 0xce\n\t\t__emit 0xce\n\t\t__emit 0xce\n\t\t__emit 0xce\n\t\t__emit 0xce\n\n\t}\n}\n#endif\n\nPMDL DBVMMDL;\n\nPINITVARS initvars;\n\nvoid cleanupDBVM() {\n\tif (!initializedvmm)\n\t\treturn;\n\n\tif (enterVMM2MDL) {\n\t\tMmUnlockPages(enterVMM2MDL);\n\t\tIoFreeMdl(enterVMM2MDL);\n\t\tenterVMM2MDL = 0;\n\t}\n\n\tif (enterVMM2) {\n\t\tRtlZeroMemory(enterVMM2, 4096);\n\t\tMmFreeContiguousMemory(enterVMM2);\n\t\tenterVMM2 = 0;\n\t}\n\n\tif (TemporaryPagingSetupMDL) {\n\t\tMmUnlockPages(TemporaryPagingSetupMDL);\n\t\tIoFreeMdl(TemporaryPagingSetupMDL);\n\t\tTemporaryPagingSetupMDL = 0;\n\t}\n\n\tif (TemporaryPagingSetup) {\n\t\tRtlZeroMemory(TemporaryPagingSetup, 4096 * 4);\n\t\tExFreePool(TemporaryPagingSetup);\n\t\tTemporaryPagingSetup = 0;\n\t}\n\n\tif (originalstateMDL) {\n\t\tMmUnlockPages(originalstateMDL);\n\t\tIoFreeMdl(originalstateMDL);\n\t\toriginalstateMDL = 0;\n\t}\n\n\tif (originalstate) {\n\t\tRtlZeroMemory(originalstate, 4096);\n\t\tExFreePool(originalstate);\n\t\toriginalstate = 0;\n\t}\n\n\tinitializedvmm = 0;\n}\n\nvoid initializeDBVM(PCWSTR dbvmimgpath)\n/*\nRuns at passive mode\n*/\n{\n\tif (initializedvmm)\n\t\treturn; //already initialized\n\n\tDbgPrint(\"First time run. Initializing vmm section\");\n\n\tPHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;\n\tLowAddress.QuadPart = 0;\n\tHighAddress.QuadPart = -1;\n\tSkipBytes.QuadPart = 0;\n\n\tDBVMMDL = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, 4 * 1024 * 1024, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED);\n\tif (!DBVMMDL) {\n\t\tDbgPrint(\"Failure allocating the required 4MB\\n\");\n\t\treturn;\n\t}\n\n\tvmm = MmMapLockedPagesSpecifyCache(DBVMMDL, KernelMode, MmCached, NULL, FALSE, 0);\n\t\n\t//default password when dbvm is just loaded (needed for adding extra ram)\n\tvmx_password1 = 0x76543210;\n\tvmx_password2 = 0xfedcba98;\n\tvmx_password3 = 0x90909090;\n\n\n\tif (vmm)\n\t{\n\t\tint i;\n\t\tPHYSICAL_ADDRESS maxPA;\n\t\tHANDLE dbvmimghandle;\n\t\tUNICODE_STRING filename;\n\t\tIO_STATUS_BLOCK statusblock;\n\t\tOBJECT_ATTRIBUTES oa;\n\t\tNTSTATUS OpenedFile;\n\n\t\tvmmPA = (UINT_PTR)MmGetPhysicalAddress(vmm).QuadPart;\n\n\t\tDbgPrint(\"Allocated memory at virtual address %p (physical address %I64x)\\n\", vmm, MmGetPhysicalAddress(vmm));\n\t\tvmmPA = MmGetMdlPfnArray(DBVMMDL)[0] << 12;\n\t\tDbgPrint(\"(physical address %I64x)\\n\", vmmPA);\n\n\t\tRtlZeroMemory(vmm, 4 * 1024 * 1024); //initialize\n\n\t\tRtlInitUnicodeString(&filename, dbvmimgpath);\n\n\n\t\t//Load the .img file\n\t\tInitializeObjectAttributes(&oa, &filename, 0, NULL, NULL);\n\t\tOpenedFile = ZwCreateFile(&dbvmimghandle, SYNCHRONIZE | STANDARD_RIGHTS_READ, &oa, &statusblock, NULL, FILE_SYNCHRONOUS_IO_NONALERT | FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, 0, NULL, 0);\n\n#ifdef TOBESIGNED\n\t\tif (OpenedFile==STATUS_SUCCESS)\n\t\t\tOpenedFile=CheckSignatureOfFile(&filename, FALSE);\n#endif\n\n\t\tif (OpenedFile == STATUS_SUCCESS)\n\t\t{\n\t\t\tWORD startsector;\n\t\t\tLARGE_INTEGER byteoffset;\n\t\t\tFILE_STANDARD_INFORMATION fsi;\n\t\t\tNTSTATUS ReadFile;\n\n\n\n\n\n\n\t\t\t//Getting filesize\n\t\t\tZwQueryInformationFile(dbvmimghandle, &statusblock, &fsi, sizeof(fsi), FileStandardInformation);\n\n\t\t\t//fsi.EndOfFile contains the filesize\n\n\t\t\tif (fsi.EndOfFile.QuadPart>4 * 1024 * 1024)\n\t\t\t{\n\t\t\t\tDbgPrint(\"File bigger than 4MB. Big retard detected\\n\");\n\t\t\t\treturn;\n\t\t\t}\n\n\n\t\t\tbyteoffset.QuadPart = 0x8; //offset containing sectornumber of the vmm location\n\t\t\tReadFile = ZwReadFile(dbvmimghandle, NULL, NULL, NULL, &statusblock, &startsector, 2, &byteoffset, NULL);\n\n\t\t\tif (ReadFile == STATUS_PENDING)\n\t\t\t{\n\t\t\t\tif (ZwWaitForSingleObject(dbvmimghandle, FALSE, NULL) != STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\tDbgPrint(\"Read failure\\n\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (statusblock.Status == STATUS_SUCCESS)\n\t\t\t{\n\t\t\t\tDWORD vmmsize = fsi.EndOfFile.LowPart;// -(startsector * 512);\n\n\t\t\t\t//now read the vmdisk into the allocated memory\n\t\t\t\tDbgPrint(\"The startsector=%d (that's offset %d)\\n\", startsector, startsector * 512);\n\n\t\t\t\tbyteoffset.QuadPart = startsector * 512;\n\t\t\t\tReadFile = ZwReadFile(dbvmimghandle, NULL, NULL, NULL, &statusblock, vmm, vmmsize, &byteoffset, NULL);\n\t\t\t\tif (ReadFile == STATUS_PENDING)\n\t\t\t\t\tZwWaitForSingleObject(dbvmimghandle, FALSE, NULL);\n\n\t\t\t\tvmmsize = (vmmsize + 4096) & 0xfffffffffffff000ULL; //adjust the size internally to a page boundary (sure, there's some mem loss, but it's predicted, dbvm assumes first 10 pages are scratch pages)\n\n\t\t\t\tDbgPrint(\"vmmsize=%x\\n\", vmmsize);\n\n\t\t\t\tif (statusblock.Status == STATUS_SUCCESS)\n\t\t\t\t{\n\t\t\t\t\t//basic paging setup for the vmm, will get expanded by the vmm itself\n\t\t\t\t\tUINT64\t\t*GDTBase;\n\t\t\t\t\tPPDPTE_PAE\tPageMapLevel4;\n\t\t\t\t\tPPDPTE_PAE\tPageDirPtr;\n\t\t\t\t\tPPDE_PAE\tPageDir;\n\t\t\t\t\tPPTE_PAE\tPageTable1, PageTable2;\n\t\t\t\t\tUINT_PTR\tFreeVA = (((UINT_PTR)vmm + vmmsize) & 0xfffffffffffff000ULL) + 4096; //next free virtual address\n\n\t\t\t\t\tUINT64\t\tmainstack;\n\t\t\t\t\tinitvars = (PINITVARS)&vmm[0x10];\n\n\t\t\t\t\tmainstack = FreeVA; FreeVA += 16 * 4096;\n\n\t\t\t\t\tGDTBase = (UINT64*)FreeVA; FreeVA += 4096;\n\t\t\t\t\tPageDirPtr = (PPDPTE_PAE)FreeVA; FreeVA += 4096;\n\t\t\t\t\tPageDir = (PPDE_PAE)FreeVA;  FreeVA += 4096;\n\t\t\t\t\tPageTable1 = (PPTE_PAE)FreeVA;  FreeVA += 4096;\n\t\t\t\t\tPageTable2 = (PPTE_PAE)FreeVA;  FreeVA += 4096;\n\t\t\t\t\tPageMapLevel4 = (PPDPTE_PAE)FreeVA;  FreeVA += 4096; //has to be the last alloc\n\n\t\t\t\t\tDBVMPML4PA = (UINT_PTR)MmGetPhysicalAddress(PageMapLevel4).QuadPart;\n\n\n\t\t\t\t\t//blame MS for making this hard to read\n\t\t\t\t\tDbgPrint(\"Setting up initial paging table for vmm\\n\");\n\n\t\t\t\t\t*(PUINT64)(&PageMapLevel4[0]) = MmGetPhysicalAddress(PageDirPtr).QuadPart;\n\t\t\t\t\tPageMapLevel4[0].P = 1;\n\t\t\t\t\tPageMapLevel4[0].RW = 1;\n\n\t\t\t\t\t*(PUINT64)(&PageDirPtr[0]) = MmGetPhysicalAddress(PageDir).QuadPart;\n\t\t\t\t\tPageDirPtr[0].P = 1;\n\t\t\t\t\tPageDirPtr[0].RW = 1;\n\n\t\t\t\t\t//DBVM 11 does no longer need the map at 0 to 00400000\n\t\t\t\t\t*(PUINT64)(&PageDir[0]) = 0; //00000000-00200000\n\t\t\t\t\tPageDir[0].P = 1;\n\t\t\t\t\tPageDir[0].RW = 0; //map as readonly (only for the jump to 0x00400000)\n\t\t\t\t\tPageDir[0].PS = 1;\n\n\t\t\t\t\t*(PUINT64)(&PageDir[1]) = 0x00200000; //00200000-00400000\n\t\t\t\t\tPageDir[1].P = 1;\n\t\t\t\t\tPageDir[1].RW = 0;\n\t\t\t\t\tPageDir[1].PS = 1;\n\n\n\t\t\t\t\t{\n\t\t\t\t\t\t*(PUINT64)(&PageDir[2]) = MmGetPhysicalAddress(PageTable1).QuadPart;\n\t\t\t\t\t\tPageDir[2].P = 1;\n\t\t\t\t\t\tPageDir[2].RW = 1;\n\t\t\t\t\t\tPageDir[2].PS = 0; //points to a pagetable \n\n\t\t\t\t\t\t*(PUINT64)(&PageDir[3]) = MmGetPhysicalAddress(PageTable2).QuadPart;\n\t\t\t\t\t\tPageDir[3].P = 1;\n\t\t\t\t\t\tPageDir[3].RW = 1;\n\t\t\t\t\t\tPageDir[3].PS = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t//fill in the pagetables\n\t\t\t\t\tfor (i = 0; i<1024; i++) //pagetable1 and 2 are allocated after eachother, so 1024 can be used here using pagetable1\n\t\t\t\t\t{\n\t\t\t\t\t\t*(PUINT64)(&PageTable1[i]) = MmGetPhysicalAddress((PVOID)(((UINT_PTR)vmm) + (4096 * i))).QuadPart;\n\t\t\t\t\t\tPageTable1[i].P = 1;\n\t\t\t\t\t\tPageTable1[i].RW = 1;\n\t\t\t\t\t}\n\n\n\t\t\t\t\ti = (int)((UINT64)((mainstack - (UINT64)vmm)) >> 12);\n\t\t\t\t\tPageTable1[i].P = 0; //mark the first page of the stack as unreadable\n\n\n\n\t\t\t\t\t//setup GDT\n\t\t\t\t\tGDTBase[0] = 0;\t\t\t\t\t\t//0 :\n\t\t\t\t\tGDTBase[1] = 0x00cf92000000ffffULL;\t//8 : 32-bit data\n\t\t\t\t\tGDTBase[2] = 0x00cf96000000ffffULL;\t//16: test, stack, failed, unused\n\t\t\t\t\tGDTBase[3] = 0x00cf9b000000ffffULL;\t//24: 32-bit code\n\t\t\t\t\tGDTBase[4] = 0x00009a000000ffffULL;\t//32: 16-bit code\n\t\t\t\t\tGDTBase[5] = 0x000092000000ffffULL;\t//40: 16-bit data\n\t\t\t\t\tGDTBase[6] = 0x00009a030000ffffULL;\t//48: 16-bit code, starting at 0x30000\n\t\t\t\t\tGDTBase[7] = 0;\t\t\t\t\t\t//56: 32-bit task\t\n\t\t\t\t\tGDTBase[8] = 0;\t\t\t\t\t\t//64: 64-bit task\n\t\t\t\t\tGDTBase[9] = 0;\t\t\t\t\t\t//72:  ^   ^   ^\n\t\t\t\t\tGDTBase[10] = 0x00af9b000000ffffULL;\t//80: 64-bit code\n\t\t\t\t\tGDTBase[11] = 0;\t\t\t\t\t\t//88:  ^   ^   ^\n\t\t\t\t\tGDTBase[12] = 0;\t\t\t\t\t\t//96: 64-bit tss descriptor (2)\n\t\t\t\t\tGDTBase[13] = 0;\t\t\t\t\t\t//104: ^   ^   ^\n\n\n\t\t\t\t\tNewGDTDescriptor.limit = 0x6f; //111\n\t\t\t\t\tNewGDTDescriptor.base = 0x00400000 + (UINT64)GDTBase - (UINT64)vmm;\n\n\t\t\t\t\tDbgPrint(\"&NewGDTDescriptor=%p, &NewGDTDescriptor.limit=%p, &NewGDTDescriptor.base=%p\\n\", &NewGDTDescriptor, &NewGDTDescriptor.limit, &NewGDTDescriptor.base);\n\t\t\t\t\tDbgPrint(\"NewGDTDescriptor.limit=%x\\n\", NewGDTDescriptor.limit);\n\t\t\t\t\tDbgPrint(\"NewGDTDescriptor.base=%p\\n\", NewGDTDescriptor.base);\n\n\t\t\t\t\tNewGDTDescriptorVA = (UINT_PTR)&NewGDTDescriptor;\n\n\n\t\t\t\t\tmaxPA.QuadPart = 0x003fffffULL; //allocate 4k at the lower 4MB\n\t\t\t\t\tDbgPrint(\"Before enterVMM2 alloc: maxPA=%I64x\\n\", maxPA.QuadPart);\n\n\t\t\t\t\tenterVMM2 = MmAllocateContiguousMemory(4096, maxPA);\n\t\t\t\t\tif (enterVMM2)\n\t\t\t\t\t{\n\t\t\t\t\t\tunsigned char *original = (unsigned char *)enterVMM;\n\t\t\t\t\t\tRtlZeroMemory(enterVMM2, 4096);\n\n\t\t\t\t\t\tenterVMM2MDL = IoAllocateMdl(enterVMM2, 4096, FALSE, FALSE, NULL);\n\t\t\t\t\t\tMmProbeAndLockPages(enterVMM2MDL, KernelMode, IoReadAccess);\n\n\t\t\t\t\t\tDbgPrint(\"enterVMM is located at %p (%I64x)\\n\", enterVMM, MmGetPhysicalAddress(enterVMM).QuadPart);\n\t\t\t\t\t\tDbgPrint(\"enterVMM2 is located at %p (%I64x)\\n\", enterVMM2, MmGetPhysicalAddress(enterVMM2).QuadPart);\n\n\n\t\t\t\t\t\tDbgPrint(\"Copying function till end\\n\");\n\t\t\t\t\t\t//copy memory\n\n\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\twhile ((i<4096) && ((original[i] != 0xce) || (original[i + 1] != 0xce) || (original[i + 2] != 0xce) || (original[i + 3] != 0xce) || (original[i + 4] != 0xce)))\n\t\t\t\t\t\t\ti++;\n\n\t\t\t\t\t\tDbgPrint(\"size is %d\", i);\n\n\t\t\t\t\t\tRtlCopyMemory(enterVMM2, original, i);\n\t\t\t\t\t\tDbgPrint(\"Copy done\\n\");\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"Failure allocating enterVMM2\\n\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\n\n\n\t\t\t\t\t//now create a paging setup where enterVMM2 is identity mapped AND mapped at the current virtual address, needed to be able to go down to nonpaged mode\n\t\t\t\t\t//easiest way, make every page point to enterVMM2\t\t\t\t\n\n\t\t\t\t\t//allocate 4 pages\n\t\t\t\t\tDbgPrint(\"Allocating memory for the temp pagedir\\n\");\n\t\t\t\t\tTemporaryPagingSetup = ExAllocatePool(PagedPool, 4 * 4096);\n\t\t\t\t\tif (TemporaryPagingSetup == NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\tDbgPrint(\"TemporaryPagingSetup==NULL!!!\\n\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tTemporaryPagingSetupMDL = IoAllocateMdl(TemporaryPagingSetup, 4 * 4096, FALSE, FALSE, NULL);\n\t\t\t\t\tMmProbeAndLockPages(TemporaryPagingSetupMDL, KernelMode, IoReadAccess);\n\n\n\n\t\t\t\t\tRtlZeroMemory(TemporaryPagingSetup, 4096 * 4);\n\t\t\t\t\tDbgPrint(\"TemporaryPagingSetup is located at %p (%I64x)\\n\", TemporaryPagingSetup, MmGetPhysicalAddress(TemporaryPagingSetup).QuadPart);\n\n\n\t\t\t\t\tTemporaryPagingSetupPA = MmGetMdlPfnArray(TemporaryPagingSetupMDL)[0] << 12; // (UINT_PTR)MmGetPhysicalAddress(TemporaryPagingSetup).QuadPart;\n\n\t\t\t\t\tenterVMM2PA = MmGetMdlPfnArray(enterVMM2MDL)[0] << 12;\n\t\t\t\t\tDbgPrint(\"TemporaryPagingSetupPA = (%I64x) (Should be %I64x)\\n\", (UINT64)TemporaryPagingSetupPA, (UINT64)MmGetPhysicalAddress(TemporaryPagingSetup).QuadPart);\n#ifdef AMD64\t\t\t\n\t\t\t\t\tDbgPrint(\"Setting up temporary paging setup for x64\\n\");\n\n\n\t\t\t\t\t{\n\t\t\t\t\t\tPUINT64 PML4Table = (PUINT64)TemporaryPagingSetup;\n\t\t\t\t\t\tPUINT64\tPageDirPtr = (PUINT64)((UINT_PTR)TemporaryPagingSetup + 4096);\n\t\t\t\t\t\tPUINT64\tPageDir = (PUINT64)((UINT_PTR)TemporaryPagingSetup + 2 * 4096);\n\t\t\t\t\t\tPUINT64\tPageTable = (PUINT64)((UINT_PTR)TemporaryPagingSetup + 3 * 4096);\n\n\t\t\t\t\t\tDbgPrint(\"PAE paging\\n\");\n\t\t\t\t\t\tfor (i = 0; i<512; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPML4Table[i] = MmGetPhysicalAddress(PageDirPtr).QuadPart;\n\t\t\t\t\t\t\t((PPDPTE_PAE)(&PML4Table[i]))->P = 1;\n\n\t\t\t\t\t\t\tPageDirPtr[i] = MmGetPhysicalAddress(PageDir).QuadPart;\n\t\t\t\t\t\t\t((PPDPTE_PAE)(&PageDirPtr[i]))->P = 1;\n\n\t\t\t\t\t\t\tPageDir[i] = MmGetPhysicalAddress(PageTable).QuadPart;\n\t\t\t\t\t\t\t((PPDE_PAE)(&PageDir[i]))->P = 1;\n\t\t\t\t\t\t\t((PPDE_PAE)(&PageDir[i]))->PS = 0; //4KB\n\n\t\t\t\t\t\t\tPageTable[i] = enterVMM2PA;\n\t\t\t\t\t\t\t((PPTE_PAE)(&PageTable[i]))->P = 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n#else\n\t\t\t\t\tDbgPrint(\"Setting up temporary paging setup\\n\");\n\t\t\t\t\tif (PTESize==8) //PAE paging\n\t\t\t\t\t{\n\t\t\t\t\t\tPUINT64\tPageDirPtr=(PUINT64)TemporaryPagingSetup;\t\t\t\t\t\t\n\t\t\t\t\t\tPUINT64\tPageDir=(PUINT64)((UINT_PTR)TemporaryPagingSetup+4096);\n\t\t\t\t\t\tPUINT64\tPageTable=(PUINT64)((UINT_PTR)TemporaryPagingSetup+2*4096);\n\n\t\t\t\t\t\tDbgPrint(\"PAE paging\\n\");\n\t\t\t\t\t\tfor (i=0; i<512; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPageDirPtr[i]=MmGetPhysicalAddress(PageDir).QuadPart;\n\t\t\t\t\t\t\t((PPDPTE_PAE)(&PageDirPtr[i]))->P=1;\n\t\t\t\t\t\t\t//((PPDPTE_PAE)(&PageDirPtr[i]))->RW=1;\n\n\n\t\t\t\t\t\t\tPageDir[i]=MmGetPhysicalAddress(PageTable).QuadPart;\n\t\t\t\t\t\t\t((PPDE_PAE)(&PageDir[i]))->P=1;\n\t\t\t\t\t\t\t//((PPDE_PAE)(&PageDir[i]))->RW=1;\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t((PPDE_PAE)(&PageDir[i]))->PS=0; //4KB\n\n\t\t\t\t\t\t\tPageTable[i]=MmGetPhysicalAddress(enterVMM2).QuadPart;\n\t\t\t\t\t\t\t((PPTE_PAE)(&PageTable[i]))->P=1;\n\t\t\t\t\t\t\t//((PPTE_PAE)(&PageTable[i]))->RW=1;\t\t\t\t\t\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\t\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t//normal(old) 4 byte page entries\n\t\t\t\t\t\tPDWORD PageDir=(PDWORD)TemporaryPagingSetup;\n\t\t\t\t\t\tPDWORD PageTable=(PDWORD)((DWORD)TemporaryPagingSetup+4096);\n\t\t\t\t\t\tDbgPrint(\"Normal paging\\n\");\n\t\t\t\t\t\tfor (i=0; i<1024; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tPageDir[i]=MmGetPhysicalAddress(PageTable).LowPart;\n\t\t\t\t\t\t\t((PPDE)(&PageDir[i]))->P=1;\n\t\t\t\t\t\t\t((PPDE)(&PageDir[i]))->RW=1;\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t((PPDE)(&PageDir[i]))->PS=0; //4KB\n\n\t\t\t\t\t\t\tPageTable[i]=MmGetPhysicalAddress(enterVMM2).LowPart;\n\t\t\t\t\t\t\t((PPTE)(&PageTable[i]))->P=1;\n\t\t\t\t\t\t\t((PPTE)(&PageTable[i]))->RW=1;\t\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n#endif\n\n\t\t\t\t\tDbgPrint(\"Temp paging has been setup\\n\");\n\n\n\t\t\t\t\t//enterVMM2PA = (UINT_PTR)MmGetPhysicalAddress(enterVMM2).QuadPart;\n\n\n\n\n\t\t\t\t\toriginalstate = ExAllocatePool(PagedPool, 4096);\n\t\t\t\t\toriginalstateMDL = IoAllocateMdl(originalstate, 4096, FALSE, FALSE, NULL);\n\t\t\t\t\tMmProbeAndLockPages(originalstateMDL, KernelMode, IoReadAccess);\n\n\t\t\t\t\tRtlZeroMemory(originalstate, 4096);\n\t\t\t\t\toriginalstatePA = MmGetMdlPfnArray(originalstateMDL)[0] << 12; //(UINT_PTR)MmGetPhysicalAddress(originalstate).QuadPart;\t\t\t\t\t\n\n\t\t\t\t\tDbgPrint(\"enterVMM2PA=%llx\\n\", enterVMM2PA);\n\t\t\t\t\tDbgPrint(\"originalstatePA=%llx\\n\", originalstatePA);\n\t\t\t\t\tDbgPrint(\"originalstatePA=%llx\\n\", (UINT_PTR)MmGetPhysicalAddress(originalstate).QuadPart);\n\n\t\t\t\t\t//setup init vars\t\n\t\t\t\t\tinitvars->loadedOS = originalstatePA;\n\t\t\t\t\tinitvars->vmmstart = vmmPA;\n\t\t\t\t\tinitvars->pagedirlvl4 = 0x00400000 + ((UINT64)PageMapLevel4 - (UINT64)vmm);\n\t\t\t\t\tinitvars->nextstack = 0x00400000 + ((UINT64)mainstack - (UINT64)vmm) + (16 * 4096) - 0x40;\n\t\t\t\t\tinitvars->contiguousmemory = 0;\n\t\t\t\t\t\n\t\t\t\t\tPMDL contiguousMDL = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, 8 * 4096, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED);\n\t\t\t\t\tif (contiguousMDL) {\n\t\t\t\t\t\tinitvars->contiguousmemory = MmGetMdlPfnArray(contiguousMDL)[0] << 12;\n\t\t\t\t\t\tDbgPrint(\"contiguous PA =%llx\\n\", initvars->contiguousmemory);\n\t\t\t\t\t\tinitvars->contiguousmemorysize = 8;\n\t\t\t\t\t\tExFreePool(contiguousMDL);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tDbgPrint(\"Failed allocating 32KB of contiguous memory\");\n\n\n\t\t\t\t\tinitializedvmm = TRUE;\n\n\t\t\t\t\tKeInitializeSpinLock(&LoadedOSSpinLock);\n\n\t\t\t\t}\n\t\t\t}\n\t\t\tZwClose(dbvmimghandle);\n\n\n\t\t\tDbgPrint(\"Opened and processed: %S\\n\", filename.Buffer);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDbgPrint(\"Failure opening the file. Status=%x  (filename=%S)\\n\", OpenedFile, filename.Buffer);\n\t\t}\n\t\t//fill in some specific memory regions\n\t\tMmUnmapLockedPages(vmm, DBVMMDL);\n\t}\n\telse\n\t{\n\t\tDbgPrint(\"Failure allocating the required 4MB\\n\");\n\t}\n\tExFreePool(DBVMMDL);\n}\n\nvoid vmxoffload(void)\n{\n\t//save entry state for easy exit in ReturnFromvmxoffload\n\tEFLAGS eflags;\n\n\tPHYSICAL_ADDRESS minPA, maxPA,boundary;\n\tGDT gdt;\n\tIDT idt;\n\t\n\t/*\n\t__try\n\t{\n\t\tDbgBreakPoint();\n\t}\n\t__except (1)\n\t{\n\t\tDbgPrint(\"No debugger\\n\");\n\t}*/\n\t\n\t\n\t//allocate 8MB of contigues physical memory\n\tminPA.QuadPart=0;\n\tmaxPA.QuadPart=0xffffffffff000000ULL;\n\tboundary.QuadPart=0x00800000ULL; //8 mb boundaries\n\n\n\tDbgPrint(\"vmxoffload\\n\");\n\n\n\n\tDbgPrint(\"initializedvmm=%d\\n\", initializedvmm); \n\tif (initializedvmm)\n\t{\n\t\tDbgPrint(\"cpunr=%d\\n\",cpunr());\n\t\t\n\t\tDbgPrint(\"Storing original state\\n\");\n\t\toriginalstate->cpucount=getCpuCount();\n\t\tDbgPrint(\"originalstate->cpucount=%d\",originalstate->cpucount);\n\n\n\t\toriginalstate->originalEFER=readMSR(0xc0000080); //amd prefers this over an LME\n\n\t\toriginalstate->originalLME=(int)(((DWORD)(readMSR(0xc0000080)) >> 8) & 1);\t\t\n\t\tDbgPrint(\"originalstate->originalLME=%d\",originalstate->originalLME);\n\n\t\t\n\t\toriginalstate->cr0=(UINT_PTR)getCR0();\n\t\t\n\n\t\tDbgPrint(\"originalstate->cr0=%I64x\",originalstate->cr0);\n\n\t\t/*\n\t\t{\n\t\t\tint xxx;\n\t\t\tunsigned char *x;\n\t\t\tx=&originalstate->cr0;\n\t\t\tfor (xxx=0; xxx<8; xxx++)\n\t\t\t{\n\t\t\t\tDbgPrint(\"%x \",x[xxx]);\n\t\t\t}\n\t\t}\n\t\t*/\n\n\t\toriginalstate->cr2=(UINT_PTR)getCR2();\n\t\tDbgPrint(\"originalstate->cr2=%I64x\",originalstate->cr2);\n\t\t/*\n\t\t{\n\t\t\tint xxx;\n\t\t\tunsigned char *x;\n\t\t\tx=&originalstate->cr2;\n\t\t\tfor (xxx=0; xxx<8; xxx++)\n\t\t\t{\n\t\t\t\tDbgPrint(\"%x \",x[xxx]);\n\t\t\t}\n\t\t}*/\n\n\t\toriginalstate->cr3=(UINT_PTR)getCR3();\n\t\t//DbgPrint(\"originalstate->cr3=%I64x\",originalstate->cr3);\n\n\t\toriginalstate->cr4=(UINT_PTR)getCR4();\n\t\t//DbgPrint(\"originalstate->cr4=%I64x\",originalstate->cr4);\n\n\t\toriginalstate->ss=getSS();\n\t\toriginalstate->ss_AccessRights = getAccessRights(originalstate->ss);\n\t\toriginalstate->ss_Limit = getSegmentLimit(originalstate->ss);\n\n\t\t//DbgPrint(\"originalstate->ss=%I64x\",originalstate->ss);\n\t\toriginalstate->cs=getCS();\n\t\toriginalstate->cs_AccessRights = getAccessRights(originalstate->cs);\n\t\toriginalstate->cs_Limit = getSegmentLimit(originalstate->cs);\n\t\t//DbgPrint(\"originalstate->cs=%I64x\",originalstate->cs);\n\t\toriginalstate->ds=getDS();\n\t\toriginalstate->ds_AccessRights = getAccessRights(originalstate->ds);\n\t\toriginalstate->ds_Limit = getSegmentLimit(originalstate->ds);\n\t\t//DbgPrint(\"originalstate->ds=%I64x\",originalstate->ds);\n\t\toriginalstate->es=getES();\n\t\toriginalstate->es_AccessRights = getAccessRights(originalstate->es);\n\t\toriginalstate->es_Limit = getSegmentLimit(originalstate->es);\n\t\t//DbgPrint(\"originalstate->es=%I64x\",originalstate->es);\n\t\toriginalstate->fs=getFS();\n\t\toriginalstate->fs_AccessRights = getAccessRights(originalstate->fs);\n\t\toriginalstate->fs_Limit = getSegmentLimit(originalstate->fs);\n\t\t//DbgPrint(\"originalstate->fs=%I64x\",originalstate->fs);\n\t\toriginalstate->gs=getGS();\n\t\toriginalstate->gs_AccessRights = getAccessRights(originalstate->gs);\n\t\toriginalstate->gs_Limit = getSegmentLimit(originalstate->gs);\n\t\t//DbgPrint(\"originalstate->gs=%I64x\",originalstate->gs);\n\t\toriginalstate->ldt=GetLDT();\n\t\t//DbgPrint(\"originalstate->ldt=%I64x\",originalstate->ldt);\n\t\toriginalstate->tr=GetTR();\n\t\t//DbgPrint(\"originalstate->tr=%I64x\",originalstate->tr);\t\t\n\n\n\t\toriginalstate->fsbase=readMSR(0xc0000100);\n\t\toriginalstate->gsbase=readMSR(0xc0000101);\n\n\t\t//DbgPrint(\"originalstate->fsbase=%I64x originalstate->gsbase=%I64x\\n\", originalstate->fsbase, originalstate->gsbase);\n\n\n\t\toriginalstate->dr7=getDR7();\n\n\t\t\n\t\tgdt.vector=0;\n\t\tgdt.wLimit=0;\n\t\tGetGDT(&gdt);\t\t\t\t\t\t\t\t\t\n\t\toriginalstate->gdtbase=(ULONG_PTR)gdt.vector;\n\t\toriginalstate->gdtlimit=gdt.wLimit;\n\n\t\t//DbgPrint(\"originalstate->gdtbase=%I64x\",originalstate->gdtbase);\n\t\t//DbgPrint(\"originalstate->gdtlimit=%I64x\",originalstate->gdtlimit);\n\n\t\tGetIDT(&idt);\n\t\toriginalstate->idtbase=(ULONG_PTR)idt.vector;\n\t\toriginalstate->idtlimit=idt.wLimit;\n\n\t\t//DbgPrint(\"originalstate->idtbase=%I64x\",originalstate->idtbase);\n\t\t//DbgPrint(\"originalstate->idtlimit=%I64x\",originalstate->idtlimit);\n\t\t\n\t\t\n\t\teflags=getEflags();\t\t\n\t\teflags.IF = 0;\n\t\toriginalstate->rflags=*(PUINT_PTR)&eflags;\n\n\t\toriginalstate->rsp=getRSP();\n\t\t//DbgPrint(\"originalstate->rsp=%I64x\",originalstate->rsp);\n\t\toriginalstate->rbp=getRBP();\n\t\t//DbgPrint(\"originalstate->rbp=%I64x\",originalstate->rbp);\n\n\t\toriginalstate->rax=getRAX();\n\t\t//DbgPrint(\"originalstate->rax=%I64x\",originalstate->rax);\n\t\toriginalstate->rbx=getRBX();\n\t\t//DbgPrint(\"originalstate->rbx=%I64x\",originalstate->rbx);\n\t\toriginalstate->rcx=getRCX();\n\t\t//DbgPrint(\"originalstate->rcx=%I64x\",originalstate->rcx);\n\t\toriginalstate->rdx=getRDX();\n\t\t//DbgPrint(\"originalstate->rdx=%I64x\",originalstate->rdx);\n\t\toriginalstate->rsi=getRSI();\n\t\t//DbgPrint(\"originalstate->rsi=%I64x\",originalstate->rsi);\n\t\toriginalstate->rdi=getRDI();\n\t\t//DbgPrint(\"originalstate->rdi=%I64x\",originalstate->rdi);\n#ifdef AMD64\n\t\toriginalstate->r8=getR8();\n\t\t//DbgPrint(\"originalstate->r8=%I64x\",originalstate->r8);\n\t\toriginalstate->r9=getR9();\n\t\t//DbgPrint(\"originalstate->r9=%I64x\",originalstate->r9);\n\t\toriginalstate->r10=getR10();\n\t\t//DbgPrint(\"originalstate->r10=%I64x\",originalstate->r10);\n\t\toriginalstate->r11=getR11();\n\t\t//DbgPrint(\"originalstate->r11=%I64x\",originalstate->r11);\n\t\toriginalstate->r12=getR12();\n\t\t//DbgPrint(\"originalstate->r12=%I64x\",originalstate->r12);\n\t\toriginalstate->r13=getR13();\n\t\t//DbgPrint(\"originalstate->r13=%I64x\",originalstate->r13);\n\t\toriginalstate->r14=getR14();\n\t\t//DbgPrint(\"originalstate->r14=%I64x\",originalstate->r14);\n\t\toriginalstate->r15=getR15();\n\t\t//DbgPrint(\"originalstate->r15=%I64x\",originalstate->r15);\n#endif\n\t\t\n\n#ifdef AMD64\n\t\t\n\t\toriginalstate->rsp-=8; //adjust rsp for the \"call entervmmprologue\"\n \t\toriginalstate->rip=(UINT_PTR)enterVMMEpilogue; //enterVMMEpilogue is an address inside the entervmmprologue function\n\n\t\t//DbgPrint(\"originalstate->rip=%llx\",originalstate->rip);\n\n\t\t//DbgPrint(\"Calling entervmm2. (Originalstate=%p (%llx))\\n\",originalstate,originalstatePA);\n\n\n\t\t\n\n\t\t//call to entervmmprologue, pushes the return value on the stack\n\t\tenterVMMPrologue();\n\n\t\t\n\t\tenableInterrupts();\n\n\t\t//DbgPrint(\"Returned from enterVMMPrologue\\n\");\n\n\t\t//DbgPrint(\"cpunr=%d\\n\",cpunr());\n\n\t\n\t\t\n\n\t\n\t\t\n\n\t\t//KeLowerIrql(oldirql);\n\n\n\t\t\n\t\t//DbgPrint(\"cpunr=%d\\n\",cpunr());\n#else\n\n\t\t\n\t\t{\n\t\t\tULONG vmmentryeip;\n\t\t\t\n\t\t\t__asm\n\t\t\t{\n\t\t\t\tlea eax,[enterVMMEpilogue]\n\t\t\t\tmov vmmentryeip,eax \n\t\t\t}\t\n\t\t\toriginalstate->rip=(UINT64)vmmentryeip;\n\t\t}\n\t\t\n\n\n\t\t__asm{\n\t\t\t\n\t\t\tcli //goodbye interrupts\t\t\t\t\t\t\n\t\t\txchg bx,bx\n\n\n\t\t\tmov ebx,vmmPA\n\t\t\t__emit 0x8b\n\t\t\t__emit 0xeb //mov ebp,ebx\n\t\t\t\n\n\t\t\tlea ebx,NewGDTDescriptor\n\t\t\tmov ecx,DBVMPML4PA;\n\t\t\tmov edx,TemporaryPagingSetupPA //for the mov cr3,ecx\n\t\t\t\n\t\t\tmov esi,enterVMM2PA\n\t\t\tmov edi,originalstatePA\n\t\t\t\n\t\t\tcall [enterVMM2]\n\t\t\t\n\t\t\t//Will never get here. NEVER\n\t\t\tFUUUUU:\n\t\t\txchg bx,bx\n\t\t\tjmp FUUUUU\n\n\t\t\n\nenterVMMEpilogue:\n\t\t\t//cli //test\n\t\t\tnop\n\t\t\tnop\n\t\t\txchg bx,bx //bochs bp\n\t\t\tnop\n\t\t\tnop\n\t\t\tsti\t\t\t\t\n\t\t\tnop\n\t\t\tnop\n\t\t\tnop\t\t\t\t\t\t\n\t\t\tnop\n\t\t\tnop\n\t\t\tnop\t\t\t\t\t\t\n\t\t}\n\t\t//KeLowerIrql(oldirql);\n\t\t\n#endif\n\t\t//DbgPrint(\"Returning\\n\");\n\n\t\treturn;\n\n\n\n\t}\n\t\n}\n\nvoid vmxoffload_override(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID DeferredContext, PVOID *SystemArgument1, PVOID *SystemArgument2)\n{\n\t//runs at passive (in any unrelated cpu)\n\n\t//allocate 64KB of extra memory for this(and every other) cpu's DBVM\n\tPHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;\n\tPMDL mdl;\n\tDbgPrint(\"vmxoffload_override\\n\");\n\tLowAddress.QuadPart = 0;\n\tHighAddress.QuadPart = 0xffffffffffffffffI64;\n\tSkipBytes.QuadPart = 0;\n\tmdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, 64 * 1024, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED); //do not free this, EVER\n\n\tif (mdl)\n\t{\n\t\t//convert the pfnlist to a list DBVM understands\n\t\tPDBVMOffloadMemInfo mi = ExAllocatePool(NonPagedPool, sizeof(DBVMOffloadMemInfo));\n\t\tint i;\n\t\tPFN_NUMBER *pfnlist;\n\n\t\tDbgPrint(\"vmxoffload_override: mi=%p\\n\", mi);\n\t\t\n\t\tmi->List = ExAllocatePool(NonPagedPool, sizeof(UINT64) * 16);\n\n\t\tDbgPrint(\"vmxoffload_override: mi->list=%p\\n\", mi->List);\n\n\t\tpfnlist = MmGetMdlPfnArray(mdl);\n\t\t\n\t\tfor (i = 0; i < 16; i++)\n\t\t  mi->List[i] = pfnlist[i] << 12;\n\n\t\tmi->Count = 16;\n\n\t\tExFreePool(mdl);\n\n\t\t*SystemArgument1 = mi;\n\t}\n}\n\n__drv_functionClass(KDEFERRED_ROUTINE) \n__drv_maxIRQL(DISPATCH_LEVEL) \n__drv_minIRQL(DISPATCH_LEVEL) \n__drv_requiresIRQL(DISPATCH_LEVEL)\n__drv_sameIRQL VOID\nvmxoffload_dpc(\n__in struct _KDPC *Dpc,\n__in_opt PVOID DeferredContext,\n__in_opt PVOID SystemArgument1,\n__in_opt PVOID SystemArgument2\n)\n{\n\tint c = cpunr();\n\tDbgPrint(\"vmxoffload_dpc: CPU %d\\n\", c);\n\tKeAcquireSpinLockAtDpcLevel(&LoadedOSSpinLock);\n\tvmxoffload();\n\n\t//still here so very likely DBVM is loaded\n\tif (SystemArgument1)\n\t{\n\t\tint x;\n\t\tPDBVMOffloadMemInfo mi = (PDBVMOffloadMemInfo)SystemArgument1;\n\t\tDbgPrint(\"mi->List=%p mi->Count=%d\\n\", mi->List, mi->Count);\n\n\t\tx=vmx_add_memory(mi->List, mi->Count);\n\t\tDbgPrint(\"vmx_add_memory returned %x\\n\", x);\n\n\t\tif (mi->List)\n\t\t\tExFreePool(mi->List);\n\n\t\tExFreePool(mi);\n\t}\n\telse\n\t\tDbgPrint(\"Error: SystemArgument1=NULL\\n\");\n\tKeReleaseSpinLockFromDpcLevel(&LoadedOSSpinLock);\n}\n"
  },
  {
    "path": "src/vmxoffload.h",
    "content": "#ifndef VMXOFFLOAD_H\n#define VMXOFFLOAD_H\n\nvoid cleanupDBVM();\nvoid initializeDBVM(PCWSTR dbvmimgpath);\nvoid vmxoffload(void);\n\nvoid vmxoffload_override(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID DeferredContext, PVOID *SystemArgument1, PVOID *SystemArgument2);\n\nVOID vmxoffload_dpc(\n\t__in struct _KDPC *Dpc,\n\t__in_opt PVOID DeferredContext,\n\t__in_opt PVOID SystemArgument1,\n\t__in_opt PVOID SystemArgument2\n\t);\n\ntypedef struct _DBVMOffloadMemInfo\n{\n\tUINT64 *List;\n\tint Count;\n} DBVMOffloadMemInfo, *PDBVMOffloadMemInfo;\n\n#pragma pack (1)\ntypedef struct _PTE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned D         :  1; // dirty\n        unsigned PAT       :  1; // PAT\n        unsigned G         :  1; // global page\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n        unsigned PFN       : 20; // page-frame number\t\t\n} *PPTE;\n\ntypedef struct _PDE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned D         :  1; // dirty\n        unsigned PS        :  1; // reserved (0)\n        unsigned G         :  1; // reserved (0)\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n        unsigned PFN       : 20; // page-frame number\n} *PPDE;\n\ntypedef struct _PDE2MB\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned reserved1 :  1; // reserved (0)\n        unsigned PS        :  1; // reserved (0)\n        unsigned reserved3 :  1; // reserved (0)\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n        unsigned PFN       : 20; // page-frame number (>> 13 instead of >>12);\n} *PPDE2MB;\n\n\n\ntypedef struct _PTE_PAE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned D         :  1; // dirty\n        unsigned PAT       :  1; // \n        unsigned G         :  1; // global page\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n\t\tunsigned PFN_LOW : 20;\n\t\tunsigned PFN_HIGH : 32;\n} PTE_PAE, *PPTE_PAE;\n\ntypedef struct _PDE_PAE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned D         :  1; // dirty\n        unsigned PS        :  1; // pagesize\n        unsigned G         :  1; // reserved (0)\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n\t\tunsigned PFN_LOW : 20;\n\t\tunsigned PFN_HIGH : 32;\n} PDE_PAE, *PPDE_PAE;\n\ntypedef struct _PDE2MB_PAE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // read/write\n        unsigned US        :  1; // user/supervisor\n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n        unsigned A         :  1; // accessed\n        unsigned reserved1 :  1; // reserved (0)\n        unsigned PS        :  1; // reserved (0)\n        unsigned reserved3 :  1; // reserved (0)\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n        unsigned PAT       :  1; //\n\t\tunsigned PFN_LOW : 19;\n\t\tunsigned PFN_HIGH : 32;\n} *PPDE2MB_PAE;\n\n\n\ntypedef struct _PDPTE_PAE\n{\n        unsigned P         :  1; // present (1 = present)\n        unsigned RW        :  1; // Read Write\n        unsigned US        :  1; // User supervisor                \n        unsigned PWT       :  1; // page-level write-through\n        unsigned PCD       :  1; // page-level cache disabled\n\t\tunsigned reserved0 : 1; // reserved\n\t\tunsigned reserved1 : 1; // reserved\n\t\tunsigned reserved2 : 1; // reserved\n\t\tunsigned reserved3 : 1; // reserved\n        unsigned A1        :  1; // available 1 aka copy-on-write\n        unsigned A2        :  1; // available 2/ is 1 when paged to disk\n        unsigned A3        :  1; // available 3\n\t\tunsigned PFN_LOW : 20;\n\t\tunsigned PFN_HIGH : 32;\n} *PPDPTE_PAE;\n\n#endif\n"
  },
  {
    "path": "templates/CMakeLists.txt.tpl",
    "content": "cmake_minimum_required(VERSION 3.18.0)\nproject({{DRIVER_NAME}} VERSION 1.0.0)\n\nenable_language(C ASM_MASM)\n\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/../wdk\")\nfind_package(WDK REQUIRED)\nstring(REPLACE \"/GR\" \"\" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /W0 /WX\")\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} /W0 /WX\")\nadd_definitions( -DRELEASE=\"DEFINED\" )\n\nwdk_add_driver({{DRIVER_NAME}} KMDF 1.15\n    \"${CMAKE_CURRENT_SOURCE_DIR}/DBKDrvr.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/DBKFunc.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/debugger.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/deepkernel.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/interruptHook.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/IOPLDispatcher.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/memscan.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/noexceptions.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/processlist.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/threads.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/ultimap.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/ultimap2.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/ultimap2/apic.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/vmxhelper.c\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/vmxoffload.c\"\n\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/dbkfunca.asm\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/debuggera.asm\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/noexceptionsa.asm\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/ultimapa.asm\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/vmxhelpera.asm\"\n    \"${CMAKE_CURRENT_SOURCE_DIR}/amd64/vmxoffloada.asm\"\n)\n\ntarget_include_directories({{DRIVER_NAME}} PUBLIC \"${CMAKE_CURRENT_SOURCE_DIR}\" PUBLIC \"${CMAKE_CURRENT_BINARY_DIR}\")\nset(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})\nset_target_properties({{DRIVER_NAME}}\n    PROPERTIES\n    RUNTIME_OUTPUT_DIRECTORY_RELEASE \"${CMAKE_BINARY_DIR}\"\n    RUNTIME_OUTPUT_DIRECTORY_DEBUG \"${CMAKE_BINARY_DIR}\"\n)\n"
  },
  {
    "path": "templates/chamd.inf.tpl",
    "content": ";\n; {{DRIVER_NAME}}.inf\n;\n\n[Version]\nSignature=\"$WINDOWS NT$\"\nClass=Sample ; TODO: edit Class\nClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid\nProvider=%ManufacturerName%\nCatalogFile={{DRIVER_NAME}}.cat\nDriverVer=\nPnpLockDown=1\n\n[DestinationDirs]\nDefaultDestDir = 12\n{{DRIVER_NAME}}_Device_CoInstaller_CopyFiles = 11\n\n; ================= Class section =====================\n\n[ClassInstall32]\nAddreg=SampleClassReg\n\n[SampleClassReg]\nHKR,,,0,%ClassName%\nHKR,,Icon,,-5\n\n[SourceDisksNames]\n1 = %DiskName%,,,\"\"\n\n[SourceDisksFiles]\n{{DRIVER_NAME}}.sys  = 1,,\n;WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames\n\n;*****************************************\n; Install Section\n;*****************************************\n\n[Manufacturer]\n%ManufacturerName%=Standard,NT$ARCH$\n\n[Standard.NT$ARCH$]\n%{{DRIVER_NAME}}.DeviceDesc%={{DRIVER_NAME}}_Device, Root\\\\{{DRIVER_NAME}} ; TODO: edit hw-id\n\n[{{DRIVER_NAME}}_Device.NT]\nCopyFiles=Drivers_Dir\n\n[Drivers_Dir]\n{{DRIVER_NAME}}.sys\n\n;-------------- Service installation\n[{{DRIVER_NAME}}_Device.NT.Services]\nAddService = {{DRIVER_NAME}},%SPSVCINST_ASSOCSERVICE%, {{DRIVER_NAME}}_Service_Inst\n\n; -------------- {{DRIVER_NAME}} driver install sections\n[{{DRIVER_NAME}}_Service_Inst]\nDisplayName    = %{{DRIVER_NAME}}.SVCDESC%\nServiceType    = 1               ; SERVICE_KERNEL_DRIVER\nStartType      = 3               ; SERVICE_DEMAND_START\nErrorControl   = 1               ; SERVICE_ERROR_NORMAL\nServiceBinary  = %12%\\\\{{DRIVER_NAME}}.sys\n\n;\n;--- {{DRIVER_NAME}}_Device Coinstaller installation ------\n;\n\n[{{DRIVER_NAME}}_Device.NT.CoInstallers]\nAddReg={{DRIVER_NAME}}_Device_CoInstaller_AddReg\nCopyFiles={{DRIVER_NAME}}_Device_CoInstaller_CopyFiles\n\n[{{DRIVER_NAME}}_Device_CoInstaller_AddReg]\n;HKR,,CoInstallers32,0x00010000, \"WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller\"\n\n[{{DRIVER_NAME}}_Device_CoInstaller_CopyFiles]\n;WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll\n\n[{{DRIVER_NAME}}_Device.NT.Wdf]\nKmdfService =  {{DRIVER_NAME}}, {{DRIVER_NAME}}_wdfsect\n[{{DRIVER_NAME}}_wdfsect]\nKmdfLibraryVersion = $KMDFVERSION$\n\n[Strings]\nSPSVCINST_ASSOCSERVICE= 0x00000002\nManufacturerName=\"{{DRIVER_NAME}} Inc.\"\nClassName=\"Samples\" ; TODO: edit ClassName\nDiskName = \"{{DRIVER_NAME}} Installation Disk\"\n{{DRIVER_NAME}}.DeviceDesc = \"{{DRIVER_NAME}} Device\"\n{{DRIVER_NAME}}.SVCDESC = \"{{DRIVER_NAME}} Service\"\n"
  },
  {
    "path": "templates/driver64.dat.tpl",
    "content": "fgfgfgfh\nfghcghfhg\nfvfghfbg\n{{DRIVER_NAME}}.sys\n76543210\nfedcba98\n"
  },
  {
    "path": "templates/makecat.cdf.tpl",
    "content": "[CatalogHeader]\nName={{DRIVER_NAME}}.cat\nPublicVersion=0x0000001\nEncodingType=0x00010001\nCATATTR1=0x10010001:OSAttr:2:6.0\n[CatalogFiles]\n<hash>File1={{DRIVER_NAME}}.sys\n"
  },
  {
    "path": "wdk/FindWDK.cmake",
    "content": "# Redistribution and use is allowed under the OSI-approved 3-clause BSD license.\n# Copyright (c) 2018 Sergey Podobry (sergey.podobry at gmail.com). All rights reserved.\n\n#.rst:\n# FindWDK\n# ----------\n#\n# This module searches for the installed Windows Development Kit (WDK) and\n# exposes commands for creating kernel drivers and kernel libraries.\n#\n# Output variables:\n# - `WDK_FOUND` -- if false, do not try to use WDK\n# - `WDK_ROOT` -- where WDK is installed\n# - `WDK_VERSION` -- the version of the selected WDK\n# - `WDK_WINVER` -- the WINVER used for kernel drivers and libraries\n#        (default value is `0x0601` and can be changed per target or globally)\n# - `WDK_NTDDI_VERSION` -- the NTDDI_VERSION used for kernel drivers and libraries,\n#                          if not set, the value will be automatically calculated by WINVER\n#        (default value is left blank and can be changed per target or globally)\n#\n# Example usage:\n#\n#   find_package(WDK REQUIRED)\n#\n#   wdk_add_library(KmdfCppLib STATIC KMDF 1.15\n#       KmdfCppLib.h\n#       KmdfCppLib.cpp\n#       )\n#   target_include_directories(KmdfCppLib INTERFACE .)\n#\n#   wdk_add_driver(KmdfCppDriver KMDF 1.15\n#       Main.cpp\n#       )\n#   target_link_libraries(KmdfCppDriver KmdfCppLib)\n#\n\nif(DEFINED ENV{WDKContentRoot})\n    file(GLOB WDK_NTDDK_FILES\n        \"$ENV{WDKContentRoot}/Include/*/km/ntddk.h\" # WDK 10\n        \"$ENV{WDKContentRoot}/Include/km/ntddk.h\" # WDK 8.0, 8.1\n    )\nelse()\n    file(GLOB WDK_NTDDK_FILES\n        \"C:/Program Files*/Windows Kits/*/Include/*/km/ntddk.h\" # WDK 10\n        \"C:/Program Files*/Windows Kits/*/Include/km/ntddk.h\" # WDK 8.0, 8.1\n    )\nendif()\n\nif(WDK_NTDDK_FILES)\n    if (NOT CMAKE_VERSION VERSION_LESS 3.18.0)\n        list(SORT WDK_NTDDK_FILES COMPARE NATURAL) # sort to use the latest available WDK\n    endif()\n    list(GET WDK_NTDDK_FILES -1 WDK_LATEST_NTDDK_FILE)\nendif()\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(WDK REQUIRED_VARS WDK_LATEST_NTDDK_FILE)\n\nif(NOT WDK_LATEST_NTDDK_FILE)\n    return()\nendif()\n\nget_filename_component(WDK_ROOT ${WDK_LATEST_NTDDK_FILE} DIRECTORY)\nget_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)\nget_filename_component(WDK_VERSION ${WDK_ROOT} NAME)\nget_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY)\nif (NOT WDK_ROOT MATCHES \".*/[0-9][0-9.]*$\") # WDK 10 has a deeper nesting level\n    get_filename_component(WDK_ROOT ${WDK_ROOT} DIRECTORY) # go up once more\n    set(WDK_LIB_VERSION \"${WDK_VERSION}\")\n    set(WDK_INC_VERSION \"${WDK_VERSION}\")\nelse() # WDK 8.0, 8.1\n    set(WDK_INC_VERSION \"\")\n    foreach(VERSION winv6.3 win8 win7)\n        if (EXISTS \"${WDK_ROOT}/Lib/${VERSION}/\")\n            set(WDK_LIB_VERSION \"${VERSION}\")\n            break()\n        endif()\n    endforeach()\n    set(WDK_VERSION \"${WDK_LIB_VERSION}\")\nendif()\n\nmessage(STATUS \"WDK_ROOT: \" ${WDK_ROOT})\nmessage(STATUS \"WDK_VERSION: \" ${WDK_VERSION})\n\nset(WDK_WINVER \"0x0601\" CACHE STRING \"Default WINVER for WDK targets\")\nset(WDK_NTDDI_VERSION \"\" CACHE STRING \"Specified NTDDI_VERSION for WDK targets if needed\")\n\nset(WDK_ADDITIONAL_FLAGS_FILE \"${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/wdkflags.h\")\nfile(WRITE ${WDK_ADDITIONAL_FLAGS_FILE} \"#pragma runtime_checks(\\\"suc\\\", off)\")\n\nset(WDK_COMPILE_FLAGS\n    \"/Zp8\" # set struct alignment\n    \"/GF\"  # enable string pooling\n    \"/GR-\" # disable RTTI\n    \"/Gz\" # __stdcall by default\n    \"/kernel\"  # create kernel mode binary\n    \"/FIwarning.h\" # disable warnings in WDK headers\n    \"/FI${WDK_ADDITIONAL_FLAGS_FILE}\" # include file to disable RTC\n\t\"/Oi\" # enable intrinsic functions so that you can use functions like _disable or _enable\n    )\n\nset(WDK_COMPILE_DEFINITIONS \"WINNT=1\")\nset(WDK_COMPILE_DEFINITIONS_DEBUG \"MSC_NOOPT;DEPRECATE_DDK_FUNCTIONS=1;DBG=1\")\n\nif(CMAKE_SIZEOF_VOID_P EQUAL 4)\n    list(APPEND WDK_COMPILE_DEFINITIONS \"_X86_=1;i386=1;STD_CALL\")\n    set(WDK_PLATFORM \"x86\")\nelseif(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL \"ARM64\")\n    list(APPEND WDK_COMPILE_DEFINITIONS \"_ARM64_;ARM64;_USE_DECLSPECS_FOR_SAL=1;STD_CALL\")\n    set(WDK_PLATFORM \"arm64\")\nelseif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n    list(APPEND WDK_COMPILE_DEFINITIONS \"_AMD64_;AMD64\")\n    set(WDK_PLATFORM \"x64\")\nelse()\n    message(FATAL_ERROR \"Unsupported architecture\")\nendif()\n\nstring(CONCAT WDK_LINK_FLAGS\n    \"/MANIFEST:NO \" #\n    \"/DRIVER \" #\n    \"/OPT:REF \" #\n    \"/INCREMENTAL:NO \" #\n    \"/OPT:ICF \" #\n    \"/SUBSYSTEM:NATIVE \" #\n    \"/MERGE:_TEXT=.text;_PAGE=PAGE \" #\n    \"/NODEFAULTLIB \" # do not link default CRT\n    \"/SECTION:INIT,d \" #\n    \"/VERSION:10.0 \" #\n    )\n\n# Generate imported targets for WDK lib files\nfile(GLOB WDK_LIBRARIES \"${WDK_ROOT}/Lib/${WDK_LIB_VERSION}/km/${WDK_PLATFORM}/*.lib\")\nforeach(LIBRARY IN LISTS WDK_LIBRARIES)\n    get_filename_component(LIBRARY_NAME ${LIBRARY} NAME_WE)\n    string(TOUPPER ${LIBRARY_NAME} LIBRARY_NAME)\n    add_library(WDK::${LIBRARY_NAME} INTERFACE IMPORTED)\n    set_property(TARGET WDK::${LIBRARY_NAME} PROPERTY INTERFACE_LINK_LIBRARIES ${LIBRARY})\nendforeach(LIBRARY)\nunset(WDK_LIBRARIES)\n\nfunction(wdk_add_driver _target)\n    cmake_parse_arguments(WDK \"\" \"KMDF;WINVER;NTDDI_VERSION\" \"\" ${ARGN})\n\n    add_executable(${_target} ${WDK_UNPARSED_ARGUMENTS})\n\n    set_target_properties(${_target} PROPERTIES SUFFIX \".sys\")\n    set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS \"${WDK_COMPILE_FLAGS}\")\n    set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS\n        \"${WDK_COMPILE_DEFINITIONS};$<$<CONFIG:Debug>:${WDK_COMPILE_DEFINITIONS_DEBUG}>;_WIN32_WINNT=${WDK_WINVER}\"\n        )\n    set_target_properties(${_target} PROPERTIES LINK_FLAGS \"${WDK_LINK_FLAGS}\")\n    if(WDK_NTDDI_VERSION)\n        target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})\n    endif()\n\n    target_include_directories(${_target} SYSTEM PRIVATE\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared\"\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km\"\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt\"\n        )\n\n    target_link_libraries(${_target} WDK::NTOSKRNL WDK::HAL WDK::WMILIB)\n\n    if(WDK::BUFFEROVERFLOWK)\n        target_link_libraries(${_target} WDK::BUFFEROVERFLOWK) # to support Windows 7 and Vista\n    else()\n        target_link_libraries(${_target} WDK::BUFFEROVERFLOWFASTFAILK)\n    endif()\n\n    if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL \"ARM64\")\n        target_link_libraries(${_target} \"arm64rt.lib\")\n    endif()\n\n    if(CMAKE_SIZEOF_VOID_P EQUAL 4)\n        target_link_libraries(${_target} WDK::MEMCMP)\n    endif()\n\n    if(DEFINED WDK_KMDF)\n        target_include_directories(${_target} SYSTEM PRIVATE \"${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}\")\n        target_link_libraries(${_target}\n            \"${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfDriverEntry.lib\"\n            \"${WDK_ROOT}/Lib/wdf/kmdf/${WDK_PLATFORM}/${WDK_KMDF}/WdfLdr.lib\"\n            )\n\n        if(CMAKE_SIZEOF_VOID_P EQUAL 4)\n            set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS \"/ENTRY:FxDriverEntry@8\")\n        elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n            set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS \"/ENTRY:FxDriverEntry\")\n        endif()\n    else()\n        if(CMAKE_SIZEOF_VOID_P EQUAL 4)\n            set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS \"/ENTRY:GsDriverEntry@8\")\n        elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n            set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS \"/ENTRY:GsDriverEntry\")\n        endif()\n    endif()\nendfunction()\n\nfunction(wdk_add_library _target)\n    cmake_parse_arguments(WDK \"\" \"KMDF;WINVER;NTDDI_VERSION\" \"\" ${ARGN})\n\n    add_library(${_target} ${WDK_UNPARSED_ARGUMENTS})\n\n    set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS \"${WDK_COMPILE_FLAGS}\")\n    set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS\n        \"${WDK_COMPILE_DEFINITIONS};$<$<CONFIG:Debug>:${WDK_COMPILE_DEFINITIONS_DEBUG};>_WIN32_WINNT=${WDK_WINVER}\"\n        )\n    if(WDK_NTDDI_VERSION)\n        target_compile_definitions(${_target} PRIVATE NTDDI_VERSION=${WDK_NTDDI_VERSION})\n    endif()\n\n    target_include_directories(${_target} SYSTEM PRIVATE\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/shared\"\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km\"\n        \"${WDK_ROOT}/Include/${WDK_INC_VERSION}/km/crt\"\n        )\n\n    if(DEFINED WDK_KMDF)\n        target_include_directories(${_target} SYSTEM PRIVATE \"${WDK_ROOT}/Include/wdf/kmdf/${WDK_KMDF}\")\n    endif()\nendfunction()\n"
  }
]