Showing preview only (415K chars total). Download the full file or copy to clipboard to get everything.
Repository: dmarov/chamd
Branch: master
Commit: 5e5ca227cc6d
Files: 54
Total size: 397.1 KB
Directory structure:
gitextract_ndahrtj5/
├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── scripts/
│ ├── builder.js
│ ├── context.js
│ ├── multibuilder.js
│ ├── paths.js
│ └── utils.js
├── src/
│ ├── DBKDrvr.c
│ ├── DBKDrvr.h
│ ├── DBKFunc.c
│ ├── DBKFunc.h
│ ├── IOPLDispatcher.c
│ ├── IOPLDispatcher.h
│ ├── amd64/
│ │ ├── dbkfunca.asm
│ │ ├── debuggera.asm
│ │ ├── noexceptionsa.asm
│ │ ├── ultimapa.asm
│ │ ├── vmxhelpera.asm
│ │ └── vmxoffloada.asm
│ ├── debugger.c
│ ├── debugger.h
│ ├── deepkernel.c
│ ├── deepkernel.h
│ ├── extradefines.h
│ ├── extraimports.h
│ ├── interruptHook.c
│ ├── interruptHook.h
│ ├── memscan.c
│ ├── memscan.h
│ ├── noexceptions.c
│ ├── noexceptions.h
│ ├── processlist.c
│ ├── processlist.h
│ ├── segmentinfo.asm
│ ├── threads.c
│ ├── threads.h
│ ├── ultimap.c
│ ├── ultimap.h
│ ├── ultimap2/
│ │ ├── apic.c
│ │ └── apic.h
│ ├── ultimap2.c
│ ├── ultimap2.h
│ ├── vmxhelper.c
│ ├── vmxhelper.h
│ ├── vmxoffload.c
│ └── vmxoffload.h
├── templates/
│ ├── CMakeLists.txt.tpl
│ ├── chamd.inf.tpl
│ ├── driver64.dat.tpl
│ └── makecat.cdf.tpl
└── wdk/
└── FindWDK.cmake
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true
================================================
FILE: .gitignore
================================================
build
.cache
.env
node_modules
src/CMakeLists.txt
dist
dists
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Dmitry Marov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Chamd (Chameleon DBK64)
## Modified Driver Based on Cheat Engine DBK64
This project provides a modified version of the Cheat Engine DBK64 kernel driver aimed at bypassing detection by anti-cheat systems.
It has been tested with EAC and BattlEye, potentially working with other systems as well.
Current version is based on Cheat Engine version 7.5

*As shown below, the driver successfully bypasses EAC detection in Robocraft.*
## 0. Important Warning
Even if you manage to use this driver successfully, it does not guarantee that you will not be suspected of cheating.
The usage of this software and any actions outlined in this document are entirely at your own risk.
Please note that using these instructions **poses a significant security risk** to your system.
It is highly recommended to use an isolated computer for this purpose. Additionally, isolating the machine within a local network may further enhance security.
## 1. System Requirements and Preparation
- **Operating System**: Windows 11 only. This method will not work on Windows 10.
- **Disable Anti-Virus Software**: Turn off Virus and Threat Protection in Windows settings, as well as any other anti-virus or anti-malware programs. These can block the required files
- Install **Cheat Engine 7.5** by compiling it from [source](https://github.com/cheat-engine/cheat-engine/releases/tag/7.5), which is preferred method, or using the [installer](https://www.cheatengine.org/downloads.php).
## 2. Obtain your driver
2.1. **Download the Compiled Driver**
Visit [GitHub](https://github.com/dmarov/chamd/releases/tag/v1.4) to download the compiled driver, which includes a multibuild file.
2.2. **Extract the Archive**
Once downloaded, extract the archive containing over 1000+ drivers. This extensive number of drivers is strategically provided to minimize the chances of multiple users using the same
driver instance, thereby reducing detection risk.
2.3. **Select and Copy the Driver**
From the extracted files, choose any one random driver. Copy all three associated files to the directory where `cheatengine-x86_64.exe` is located.
Why Multiple Drivers?
Using a unique driver decreases the chances of your setup being flagged or blacklisted by anti-cheat systems.
The way anti-cheat works, is that it develops signatures for popular cheats and flags it in the database. Of cousre there's more to anti-cheat.
For better reliability, consider compiling your own driver following the instructions in Section 7. This process creates a custom driver, reducing the chances of
detection.
## 3. Bypassing **Digital Signature Enforcement**
At this point you have driver signed with untrusted certificate.
There are a few options to load it.
In this section the method based on bypass of **Patchguard** and **Digital Signature Enforcement** will be explained.
Refer to section 8 for some extra method.
- [Video tutorial 1](https://www.youtube.com/watch?v=EJGuJp2fqpM)
- [Video tutorial 2](https://www.youtube.com/watch?v=zsw3xoG3zgs)
3.1. Create bootable usb drive
3.1.1. Download [EfiGuard](https://github.com/Mattiwatti/EfiGuard/releases/) version >= 1.4.
3.1.2. Mount you usb drive. 2GB drive should be more than enough.
3.1.3. Format your usb drive as `FAT32`. **be carefull to format the correct device**, because it will erase all data on USB drive
3.1.4. Partition your device as bootable `GPT` with `EFI` partition.
**be carefull to partition the correct device!!!**
Open command prompt as administrator and perform the following commands:
```shell
diskpart
list disk // detect your USB drive
select disk {put number of your USB drive here} // SELECTING CORRECT DISK!!!
list disk // make sure correct disk is selected
clean // wipe out your drive
create partition primary size=512 // create EFI partition
list partitions // created partition shoud be displayed
select partition 1 // select created partition
active // mark partition as active
format quick fs=fat32 // create filesystem
assign // disk should be mounted
exit
```
3.1.5. Copy files to USB drive
Copy `EFI` directory from the extracted archive to the root of created partition.
3.1.6. Rename bootloader
Locate `EFI/Boot/Loader.efi` on the USB drive, than rename it to `EFI/Boot/bootx64.efi`.
3.2. Boot your system from USB drive.
Restart your computer and enter the UEFI settings (usually by pressing F2, F12, or DEL during startup).
Set the first boot option to your USB drive (UEFI). The second option should be your windows drive (UEFI).
Ensure Secure Boot is disabled since EFIGuard rootkit isn't signed.
3.3. Copy files for digital signature enforcement bypass
3.3.1. In the directory containing `cheatengine-x86_64.exe`, create a new file named `run.bat` with the following content:
```shell
"%~dp0\EfiDSEFix.exe" -d
start /d "%~dp0" cheatengine-x86_64.exe
timeout /t 20
"%~dp0\EfiDSEFix.exe" -e
```
Before doing that, make sure that file explored is not configured to hide known file extensions.
3.3.2. Copy `EfiDSEFix.exe` from the archive to the same directory as `cheatengine-x86_64.exe`.
## 4. Configure Cheat Engine
Make sure that
`Edit` > `Settings` > `Extra` > `Query memory region routines` is checked
`Edit` > `Settings` > `Extra` > `Read/Write process memory` is checked
Click `OK`.
It might end up with errors. Close Cheat Engine.
## 5. Run Cheat Engine.
### If you followed section 3:
Run `run.bat` as Administrator.
Do not close the window that pops out manually!!! Wait for it to close automatically.
After the driver has been successfully loaded, you can directly run `cheatengine-x86_64.exe` without needing to execute `run.bat`.
### If you followed section 8:
Run `cheatengine-x86_64.exe`
## 6. Congratulations
You have successfully loaded the DBK64 driver signed with an untrusted certificate.
This allows kernel mode anti-cheat (EAC) to permit starting the game and performing operations on the
game memory. Note: The last tested version was confirmed on EAC as of April 19, 2025.
## 7. [Extra] Compile the driver from source
Anti-cheat systems may collect signatures of suspicious drivers used by a small number of users to block them. To mitigate this, it is recommended to compile your own version of the
driver with a unique signature.
#### **Note:**
Use PowerShell or Cmder for these steps.
[Video Tutorial](https://www.youtube.com/watch?v=7ARwpxZPpE8)
7.1. Clone this repository
```shell
git clone https://github.com/dmarov/chamd.git
cd chamd
```
Ensure you have Git installed on your system before cloning.
7.2. Install [nodejs](https://nodejs.org/en/). Version `>=19` is required.
7.3. Install packages
Run the following command in your terminal:
```shell
npm install
```
This will install all required packages for building the driver.
7.4. Copy `.env.tpl` to `.env`
Create a copy of the template environment file by running:
```shell
cp .env.tpl .env
```
7.5. Optionaly set `CHAMD_DBK_DRIVER_NAME` in `.env`.
Edit the `.env` file and set the `CHAMD_DBK_DRIVER_NAME` variable to a unique name if desired.
Example:
```env
CHAMD_DBK_DRIVER_NAME=mysupercooldrv
```
7.6. Install Visual Studio
Install **Visual Studio 2022** (Community or Enterprise) with support for C++ development.
[Download Visual Studio](https://visualstudio.microsoft.com/downloads/)
Ensure you select the following components during installation:
- **Desktop Development with C++**
- **MSVC v143 (C++ Compiler)**
7.7. Install [Windows SDK and WDK](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)
Carefully follow the instructions from the link. It is important that SDK and WDK have the same version.
Correct versions of spectre mitigated libraries should be installed in the process.
7.8. Install openssl. The most straightforward way is to use Chocolatey package manager.
```shell
choco install openssl
```
This command has to be performed as Admininstrator.
7.9. Run build
```shell
npm run all
```
Note:
You can use [EV certificate](https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/code-signing-cert-manage)
to sign driver. You could skip digital signature enforcement bypass this way. They are costly though and can be revoked when misused.
7.10. Copy all files from the 'dist' directory to directory where `cheatengine-x86_64.exe`
is located.
7.11. If you've managed to compile this driver successfully and want to share few
randomized copies then run `npm run multibuild 10`. `dist` directory will
contain `10` randomized drivers.
Then go to section 3.
## 8. [Extra] Another Method of dealing with *Digital Signature Enforcement*
If you want to bypass digital signature enforcement temporarily (for testing purposes only), follow these steps:
8.1. Enable Test Signing Mode:
```shell
bcdedit /set testsigning on
```
This command modifies the boot configuration to allow loading of unsigned or self-signed drivers.
8.2. Reboot Your System:
The changes take effect after a system reboot.
8.3. Proceed with Section 4:
Load the driver as outlined in section 4.
8.4. Disable Test Signing Mode:
After testing, disable test signing mode to restore normal security settings.
```shell
bcdedit /set testsigning off
```
Enabling test signing mode is intended for development and troubleshooting purposes only.
It temporarily reduces the system's security by allowing unsigned drivers to load.
This method does not work with anti-cheat systems, as they typically enforce strict driver signature requirements.
================================================
FILE: package.json
================================================
{
"type": "module",
"dependencies": {
"dotenv": "^10.0.0",
"handlebars": "^4.7.7"
},
"scripts": {
"all": "node --unhandled-rejections=strict ./scripts/builder.js all",
"purge": "node --unhandled-rejections=strict ./scripts/builder.js purge",
"compile": "node --unhandled-rejections=strict ./scripts/builder.js compile",
"geninf": "node --unhandled-rejections=strict ./scripts/builder.js geninf",
"sign": "node --unhandled-rejections=strict ./scripts/builder.js sign",
"multibuild": "node --unhandled-rejections=strict ./scripts/multibuilder.js"
}
}
================================================
FILE: scripts/builder.js
================================================
import dotenv from 'dotenv';
import Context from './context.js';
import generateRandomName from './utils.js';
import path from 'path';
import { __dirname } from './paths.js';
const env = dotenv.config().parsed;
const driverName = env.CHAMD_DBK_DRIVER_NAME ?? generateRandomName();
const args = process.argv.slice(2);
const command = args[0];
const distDir = path.normalize(__dirname + '\\..\\dist\\');
const context = new Context(driverName, distDir);
await Context.purgeDir(distDir);
switch (command) {
case 'all':
await context.all();
break;
case 'purge':
await context.purge();
break;
case 'compile':
await context.generateCmakeFile();
await context.compile();
break;
case 'geninf':
await context.createInfFile();
await context.stampInfFile();
break;
case 'sign':
await context.signDriver();
await context.createInfFile();
break;
}
================================================
FILE: scripts/context.js
================================================
import path from 'path';
import fs from 'fs';
import handlebars from 'handlebars';
import { spawn } from 'child_process';
import { __dirname } from './paths.js';
export default class Context {
buildDir = path.normalize(__dirname + '\\..\\build\\');
vcvarsCommunityPath = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat';
vcvarsEnterprisePath = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat';
vcPath = null;
cmakeTplPath = path.normalize(__dirname + '\\..\\templates\\CMakeLists.txt.tpl');
infTplPath = path.normalize(__dirname + '\\..\\templates\\chamd.inf.tpl');
makeCatTplPath = path.normalize(__dirname + '\\..\\templates\\makecat.cdf.tpl');
datTplPath = path.normalize(__dirname + '\\..\\templates\\driver64.dat.tpl');
datPath = `${this.buildDir}driver64.dat`;
srcDir = path.normalize(__dirname + '\\..\\src\\');
cmakeConfigPath = this.srcDir + 'CMakeLists.txt';
constructor(driverName, distDir) {
this.distDir = distDir;
this.driverName = driverName
.replace(/[^a-z0-9_]/gi, '')
.toLowerCase();
const communityVs = fs.existsSync(this.vcvarsCommunityPath);
const enterpriseVs = fs.existsSync(this.vcvarsEnterprisePath);
if (communityVs) {
this.vcPath = this.vcvarsCommunityPath;
}
if (enterpriseVs) {
this.vcPath = this.vcvarsEnterprisePath;
}
this.makeCatPath = `${this.buildDir}${this.driverName}.cdf`;
}
async all() {
console.log(`Generating ${this.driverName} driver ...`);
await this.purge();
await this.generateCmakeFile();
await this.compile();
await this.createMakeCatFile();
await this.makeCatFile();
await this.signDriver();
await this.createDriverDatFile();
await this.install();
await this.clearBuildDir();
console.log(`Success!!!`);
console.log(`Now copy all files from ${this.distDir} to directory where cheatengine.exe is located`);
}
async purge() {
await this.clearBuildDir();
if (!fs.existsSync(this.cmakeConfigPath)) {
return;
}
fs.rmSync(this.cmakeConfigPath);
}
static async purgeDir(dir) {
if (!fs.existsSync(dir)) {
return;
}
fs.rmSync(dir, { recursive: true })
}
async generateCmakeFile() {
await this.templateToFile(
this.cmakeTplPath,
this.cmakeConfigPath,
{
DRIVER_NAME: this.driverName,
}
);
}
async templateToFile(src, dist, vars) {
const templateContent = fs.readFileSync(src, 'utf-8');
const template = handlebars.compile(templateContent);
const res = template(vars)
fs.writeFileSync(dist, res);
}
async compile() {
console.log('Compiling');
if (this.vcPath === null) {
throw new Error('Visual studio not found');
}
if (!fs.existsSync(this.buildDir)) {
fs.mkdirSync(this.buildDir);
}
const cmd = `"${this.vcPath}" amd64 && cd "${this.buildDir}" && cmake -G "Visual Studio 17 2022" -A x64 -T v143 "${this.srcDir}" && cmake --build . --config Release`;
await this.execute(cmd, this.buildDir);
}
async createMakeCatFile() {
console.log('Creating makecat file');
await this.templateToFile(
this.makeCatTplPath,
this.makeCatPath, {
DRIVER_NAME: this.driverName,
},
);
}
async makeCatFile() {
console.log('Makeing cat file');
const cmd = `"${this.vcPath}" amd64 && MakeCat.exe -v .\\${this.driverName}.cdf`
await this.execute(cmd, this.buildDir);
}
async signDriver() {
console.log('Signing driver');
const openssl = `openssl req -nodes -newkey rsa:2048 -keyout ${this.driverName}.key -out ${this.driverName}.csr -subj "/CN=${this.driverName}.com/O=${this.driverName} LTD./C=US"`
const crt = `openssl x509 -signkey ${this.driverName}.key -in ${this.driverName}.csr -req -days 365 -out ${this.driverName}.crt`;
const pfx = `openssl pkcs12 -export -out ${this.driverName}.pfx -inkey ${this.driverName}.key -in ${this.driverName}.crt -password pass:`;
const vc = `"${this.vcPath}" amd64`;
const signtool = `signtool sign /fd SHA256 -f "./${this.driverName}.pfx" -t "http://timestamp.digicert.com" -v "${this.driverName}.cat"`;
const cmd = `${openssl} && ${crt} && ${pfx} && ${vc} && ${signtool}`;
await this.execute(cmd, this.buildDir);
}
async execute(cmd, cwd, params = []) {
console.log(`!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!`);
console.log(`Executing: ${cmd}`);
return new Promise((res, rej) => {
const proc = spawn(cmd, params, {
cwd,
shell: true,
});
proc.stderr.setEncoding('utf-8');
proc.stdout.pipe(process.stdout);
proc.stderr.pipe(process.stderr);
proc.on('close', (code) => {
code == 0 ? res() : rej();
});
});
}
async createDriverDatFile() {
console.log('Creating dat file');
await this.templateToFile(
this.datTplPath,
this.datPath, {
DRIVER_NAME: this.driverName,
},
);
}
async install() {
console.log('Installing');
if (!fs.existsSync(this.distDir)) {
fs.mkdirSync(this.distDir, { recursive: true });
}
fs.copyFileSync(
`${this.buildDir}${this.driverName}.sys`,
`${this.distDir}${this.driverName}.sys`
);
fs.copyFileSync(
`${this.buildDir}${this.driverName}.cat`,
`${this.distDir}${this.driverName}.cat`
);
fs.copyFileSync(
`${this.buildDir}driver64.dat`,
`${this.distDir}driver64.dat`
);
}
async clearBuildDir() {
await Context.purgeDir(this.buildDir);
}
}
================================================
FILE: scripts/multibuilder.js
================================================
import Context from './context.js';
import generateRandomName from './utils.js';
import path from 'path';
import http from 'http';
import { __dirname } from './paths.js';
const args = process.argv.slice(2);
const cnt = args[0] ? parseInt(args[0]) : 5;
const distDir = path.normalize(__dirname + '\\..\\dist\\');
async function getRandomWord() {
return new Promise((res, rej) => {
const options = {
host: 'random-word-api.herokuapp.com',
path: '/word'
};
const callback = function(response) {
let str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
res(str);
});
}
const req = http.request(options, callback);
req.on('error', function (e) {
rej(e);
});
req.end();
});
}
await Context.purgeDir(distDir);
const max = 15;
const min = 4;
for (let i = 0; i < cnt; i++) {
const len = min + Math.floor(Math.random() * (max - min));
let name = generateRandomName(len);
try {
const result = await getRandomWord();
name = JSON.parse(result)[0]
.replace(/[^a-z0-9_]/gi, '')
.toLowerCase();
} catch(e) {
console.log(e);
}
const context = new Context(name, distDir + name + '\\');
await context.all();
}
================================================
FILE: scripts/paths.js
================================================
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
export const __dirname = path.dirname(__filename);
================================================
FILE: scripts/utils.js
================================================
export default (length) => {
let result = '';
const characters = 'abcdefghijklmnopqrstuvwxyz';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
================================================
FILE: src/DBKDrvr.c
================================================
#pragma warning( disable: 4100 4101 4103 4189)
#include "DBKFunc.h"
#include <ntifs.h>
#include <windef.h>
#include "DBKDrvr.h"
#include "deepkernel.h"
#include "processlist.h"
#include "memscan.h"
#include "threads.h"
#include "vmxhelper.h"
#include "debugger.h"
#include "vmxoffload.h"
#include "IOPLDispatcher.h"
#include "interruptHook.h"
#include "ultimap.h"
#include "ultimap2.h"
#include "noexceptions.h"
#include "ultimap2\apic.h"
#if (AMD64 && TOBESIGNED)
#include "sigcheck.h"
#endif
#ifdef CETC
#include "cetc.h"
#endif
void UnloadDriver(PDRIVER_OBJECT DriverObject);
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
#ifndef AMD64
//no api hooks for x64
//-----NtUserSetWindowsHookEx----- //prevent global hooks
typedef ULONG (NTUSERSETWINDOWSHOOKEX)(
IN HANDLE hmod,
IN PUNICODE_STRING pstrLib OPTIONAL,
IN DWORD idThread,
IN int nFilterType,
IN PVOID pfnFilterProc,
IN DWORD dwFlags
);
NTUSERSETWINDOWSHOOKEX OldNtUserSetWindowsHookEx;
ULONG NtUserSetWindowsHookEx_callnumber;
//HHOOK NewNtUserSetWindowsHookEx(IN HANDLE hmod,IN PUNICODE_STRING pstrLib OPTIONAL,IN DWORD idThread,IN int nFilterType, IN PROC pfnFilterProc,IN DWORD dwFlags);
typedef NTSTATUS (*ZWSUSPENDPROCESS)
(
IN ULONG ProcessHandle // Handle to the process
);
ZWSUSPENDPROCESS ZwSuspendProcess;
NTSTATUS ZwCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PVOID UserStack,
IN BOOLEAN CreateSuspended);
//PVOID GetApiEntry(ULONG FunctionNumber);
#endif
typedef NTSTATUS(*PSRCTNR)(__in PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine);
PSRCTNR PsRemoveCreateThreadNotifyRoutine2;
typedef NTSTATUS(*PSRLINR)(__in PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);
PSRLINR PsRemoveLoadImageNotifyRoutine2;
UNICODE_STRING uszDeviceString;
PVOID BufDeviceString=NULL;
void hideme(PDRIVER_OBJECT DriverObject)
{
#ifndef AMD64
typedef struct _MODULE_ENTRY {
LIST_ENTRY le_mod;
DWORD unknown[4];
DWORD base;
DWORD driver_start;
DWORD unk1;
UNICODE_STRING driver_Path;
UNICODE_STRING driver_Name;
} MODULE_ENTRY, *PMODULE_ENTRY;
PMODULE_ENTRY pm_current;
pm_current = *((PMODULE_ENTRY*)((DWORD)DriverObject + 0x14)); //eeeeew
*((PDWORD)pm_current->le_mod.Blink) = (DWORD) pm_current->le_mod.Flink;
pm_current->le_mod.Flink->Blink = pm_current->le_mod.Blink;
HiddenDriver=TRUE;
#endif
}
int testfunction(int p1,int p2)
{
DbgPrint("Hello\nParam1=%d\nParam2=%d\n",p1,p2);
return 0x666;
}
void* functionlist[1];
char paramsizes[1];
int registered=0;
#ifdef DEBUG1
VOID TestPassive(UINT_PTR param)
{
DbgPrint("passive cpu call for cpu %d\n", KeGetCurrentProcessorNumber());
}
VOID TestDPC(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
EFLAGS e=getEflags();
DbgPrint("Defered cpu call for cpu %d (Dpc=%p IF=%d IRQL=%d)\n", KeGetCurrentProcessorNumber(), Dpc, e.IF, KeGetCurrentIrql());
}
#endif
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
/*++
Routine Description:
This routine is called when the driver is loaded by NT.
Arguments:
DriverObject - Pointer to driver object created by system.
RegistryPath - Pointer to the name of the services node for this driver.
Return Value:
The function value is the final status from the initialization operation.
--*/
{
NTSTATUS ntStatus;
PVOID BufDriverString = NULL, BufProcessEventString = NULL, BufThreadEventString = NULL;
UNICODE_STRING uszDriverString;
UNICODE_STRING uszProcessEventString;
UNICODE_STRING uszThreadEventString;
PDEVICE_OBJECT pDeviceObject;
HANDLE reg = 0;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING temp;
char wbuf[100];
WORD this_cs, this_ss, this_ds, this_es, this_fs, this_gs;
ULONG cr4reg;
criticalSection csTest;
HANDLE Ultimap2Handle;
KernelCodeStepping = 0;
KernelWritesIgnoreWP = 0;
this_cs = getCS();
this_ss = getSS();
this_ds = getDS();
this_es = getES();
this_fs = getFS();
this_gs = getGS();
temp.Buffer = (PWCH)wbuf;
temp.Length = 0;
temp.MaximumLength = 100;
//DbgPrint("Loading driver\n");
if (RegistryPath)
{
//DbgPrint("Registry path = %S\n", RegistryPath->Buffer);
InitializeObjectAttributes(&oa, RegistryPath, OBJ_KERNEL_HANDLE, NULL, NULL);
ntStatus = ZwOpenKey(®, KEY_QUERY_VALUE, &oa);
if (ntStatus == STATUS_SUCCESS)
{
UNICODE_STRING A, B, C, D;
PKEY_VALUE_PARTIAL_INFORMATION bufA, bufB, bufC, bufD;
ULONG ActualSize;
//DbgPrint("Opened the key\n");
BufDriverString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
BufDeviceString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
BufProcessEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
BufThreadEventString = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100);
bufA = BufDriverString;
bufB = BufDeviceString;
bufC = BufProcessEventString;
bufD = BufThreadEventString;
RtlInitUnicodeString(&A, L"A");
RtlInitUnicodeString(&B, L"B");
RtlInitUnicodeString(&C, L"C");
RtlInitUnicodeString(&D, L"D");
if (ntStatus == STATUS_SUCCESS)
ntStatus = ZwQueryValueKey(reg, &A, KeyValuePartialInformation, bufA, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
if (ntStatus == STATUS_SUCCESS)
ntStatus = ZwQueryValueKey(reg, &B, KeyValuePartialInformation, bufB, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
if (ntStatus == STATUS_SUCCESS)
ntStatus = ZwQueryValueKey(reg, &C, KeyValuePartialInformation, bufC, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
if (ntStatus == STATUS_SUCCESS)
ntStatus = ZwQueryValueKey(reg, &D, KeyValuePartialInformation, bufD, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 100, &ActualSize);
if (ntStatus == STATUS_SUCCESS)
{
//DbgPrint("Read ok\n");
RtlInitUnicodeString(&uszDriverString, (PCWSTR)bufA->Data);
RtlInitUnicodeString(&uszDeviceString, (PCWSTR)bufB->Data);
RtlInitUnicodeString(&uszProcessEventString, (PCWSTR)bufC->Data);
RtlInitUnicodeString(&uszThreadEventString, (PCWSTR)bufD->Data);
//DbgPrint("DriverString=%S\n", uszDriverString.Buffer);
//DbgPrint("DeviceString=%S\n", uszDeviceString.Buffer);
//DbgPrint("ProcessEventString=%S\n", uszProcessEventString.Buffer);
//DbgPrint("ThreadEventString=%S\n", uszThreadEventString.Buffer);
}
else
{
ExFreePool(bufA);
ExFreePool(bufB);
ExFreePool(bufC);
ExFreePool(bufD);
//DbgPrint("Failed reading the value\n");
ZwClose(reg);
return STATUS_UNSUCCESSFUL;;
}
}
else
{
//DbgPrint("Failed opening the key\n");
return STATUS_UNSUCCESSFUL;;
}
}
else
loadedbydbvm = TRUE;
ntStatus = STATUS_SUCCESS;
if (!loadedbydbvm)
{
// Point uszDriverString at the driver name
#ifndef CETC
// Create and initialize device object
ntStatus = IoCreateDevice(DriverObject,
0,
&uszDriverString,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&pDeviceObject);
if (ntStatus != STATUS_SUCCESS)
{
//DbgPrint("IoCreateDevice failed\n");
ExFreePool(BufDriverString);
ExFreePool(BufDeviceString);
ExFreePool(BufProcessEventString);
ExFreePool(BufThreadEventString);
if (reg)
ZwClose(reg);
return ntStatus;
}
// Point uszDeviceString at the device name
// Create symbolic link to the user-visible name
ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);
if (ntStatus != STATUS_SUCCESS)
{
//DbgPrint("IoCreateSymbolicLink failed: %x\n", ntStatus);
// Delete device object if not successful
IoDeleteDevice(pDeviceObject);
ExFreePool(BufDriverString);
ExFreePool(BufDeviceString);
ExFreePool(BufProcessEventString);
ExFreePool(BufThreadEventString);
if (reg)
ZwClose(reg);
return ntStatus;
}
#endif
}
//when loaded by dbvm driver object is 'valid' so store the function addresses
//DbgPrint("DriverObject=%p\n", DriverObject);
// Load structure to point to IRP handlers...
DriverObject->DriverUnload = UnloadDriver;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
if (loadedbydbvm)
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchIoctlDBVM;
else
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
//Processlist init
#ifndef CETC
ProcessEventCount = 0;
ExInitializeResourceLite(&ProcesslistR);
#endif
CreateProcessNotifyRoutineEnabled = FALSE;
//threadlist init
ThreadEventCount = 0;
processlist = NULL;
#ifndef AMD64
//determine if PAE is used
cr4reg=(ULONG)getCR4();
if ((cr4reg & 0x20)==0x20)
{
PTESize=8; //pae
PAGE_SIZE_LARGE=0x200000;
MAX_PDE_POS=0xC0604000;
MAX_PTE_POS=0xC07FFFF8;
}
else
{
PTESize=4;
PAGE_SIZE_LARGE=0x400000;
MAX_PDE_POS=0xC0301000;
MAX_PTE_POS=0xC03FFFFC;
}
#else
PTESize = 8; //pae
PAGE_SIZE_LARGE = 0x200000;
//base was 0xfffff68000000000ULL
//to
MAX_PTE_POS = 0xFFFFF6FFFFFFFFF8ULL; // base + 0x7FFFFFFFF8
MAX_PDE_POS = 0xFFFFF6FB7FFFFFF8ULL; // base + 0x7B7FFFFFF8
#endif
#ifdef CETC
DbgPrint("Going to initialice CETC\n");
InitializeCETC();
#endif
//hideme(DriverObject); //ok, for those that see this, enabling this WILL fuck up try except routines, even in usermode you'll get a blue sreen
DbgPrint("Initializing debugger\n");
debugger_initialize();
// Return success (don't do the devicestring, I need it for unload)
DbgPrint("Cleaning up initialization buffers\n");
if (BufDriverString)
{
ExFreePool(BufDriverString);
BufDriverString = NULL;
}
if (BufProcessEventString)
{
ExFreePool(BufProcessEventString);
BufProcessEventString = NULL;
}
if (BufThreadEventString)
{
ExFreePool(BufThreadEventString);
BufThreadEventString = NULL;
}
if (reg)
{
ZwClose(reg);
reg = 0;
}
//fetch cpu info
{
DWORD r[4];
DWORD a;
__cpuid(r, 0);
DbgPrint("cpuid.0: r[1]=%x", r[1]);
if (r[1] == 0x756e6547) //GenuineIntel
{
__cpuid(r, 1);
a = r[0];
cpu_stepping = a & 0xf;
cpu_model = (a >> 4) & 0xf;
cpu_familyID = (a >> 8) & 0xf;
cpu_type = (a >> 12) & 0x3;
cpu_ext_modelID = (a >> 16) & 0xf;
cpu_ext_familyID = (a >> 20) & 0xff;
cpu_model = cpu_model + (cpu_ext_modelID << 4);
cpu_familyID = cpu_familyID + (cpu_ext_familyID << 4);
vmx_init_dovmcall(1);
setup_APIC_BASE(); //for ultimap
}
else
{
DbgPrint("Not an intel cpu");
if (r[1] == 0x68747541)
{
DbgPrint("This is an AMD\n");
vmx_init_dovmcall(0);
}
}
}
#ifdef DEBUG1
{
APIC y;
DebugStackState x;
DbgPrint("offset of LBR_Count=%d\n", (UINT_PTR)&x.LBR_Count - (UINT_PTR)&x);
DbgPrint("Testing forEachCpu(...)\n");
forEachCpu(TestDPC, NULL, NULL, NULL, NULL);
DbgPrint("Testing forEachCpuAsync(...)\n");
forEachCpuAsync(TestDPC, NULL, NULL, NULL, NULL);
DbgPrint("Testing forEachCpuPassive(...)\n");
forEachCpuPassive(TestPassive, 0);
DbgPrint("LVT_Performance_Monitor=%x\n", (UINT_PTR)&y.LVT_Performance_Monitor - (UINT_PTR)&y);
}
#endif
#ifdef DEBUG2
DbgPrint("No exceptions test:");
if (NoExceptions_Enter())
{
int o = 45678;
int x = 0, r = 0;
//r=NoExceptions_CopyMemory(&x, &o, sizeof(x));
r = NoExceptions_CopyMemory(&x, (PVOID)0, sizeof(x));
DbgPrint("o=%d x=%d r=%d", o, x, r);
DbgPrint("Leaving NoExceptions mode");
NoExceptions_Leave();
}
#endif
RtlInitUnicodeString(&temp, L"PsSuspendProcess");
PsSuspendProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);
RtlInitUnicodeString(&temp, L"PsResumeProcess");
PsResumeProcess = (PSSUSPENDPROCESS)MmGetSystemRoutineAddress(&temp);
return STATUS_SUCCESS;
}
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
// Check for SeDebugPrivilege. (So only processes with admin rights can use it)
LUID sedebugprivUID;
sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;
sedebugprivUID.HighPart=0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
if (SeSinglePrivilegeCheck(sedebugprivUID, UserMode))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
#ifdef AMD64
#ifdef TOBESIGNED
{
NTSTATUS s=SecurityCheck();
Irp->IoStatus.Status = s;
}
// DbgPrint("Returning %x (and %x)\n", Irp->IoStatus.Status, s);
#endif
#endif
}
else
{
DbgPrint("A process without SeDebugPrivilege tried to open the dbk driver\n");
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}
void UnloadDriver(PDRIVER_OBJECT DriverObject)
{
cleanupDBVM();
if (!debugger_stopDebugging())
{
DbgPrint("Can not unload the driver because of debugger\n");
return; //
}
debugger_shutdown();
ultimap_disable();
DisableUltimap2();
UnregisterUltimapPMI();
clean_APIC_BASE();
NoExceptions_Cleanup();
if ((CreateProcessNotifyRoutineEnabled) || (ImageNotifyRoutineLoaded))
{
PVOID x;
UNICODE_STRING temp;
RtlInitUnicodeString(&temp, L"PsRemoveCreateThreadNotifyRoutine");
PsRemoveCreateThreadNotifyRoutine2 = (PSRCTNR)MmGetSystemRoutineAddress(&temp);
RtlInitUnicodeString(&temp, L"PsRemoveCreateThreadNotifyRoutine");
PsRemoveLoadImageNotifyRoutine2 = (PSRLINR)MmGetSystemRoutineAddress(&temp);
RtlInitUnicodeString(&temp, L"ObOpenObjectByName");
x=MmGetSystemRoutineAddress(&temp);
DbgPrint("ObOpenObjectByName=%p\n",x);
if ((PsRemoveCreateThreadNotifyRoutine2) && (PsRemoveLoadImageNotifyRoutine2))
{
DbgPrint("Stopping processwatch\n");
if (CreateProcessNotifyRoutineEnabled)
{
DbgPrint("Removing process watch");
#if (NTDDI_VERSION >= NTDDI_VISTASP1)
PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx,TRUE);
#else
PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,TRUE);
#endif
DbgPrint("Removing thread watch");
PsRemoveCreateThreadNotifyRoutine2(CreateThreadNotifyRoutine);
}
if (ImageNotifyRoutineLoaded)
PsRemoveLoadImageNotifyRoutine2(LoadImageNotifyRoutine);
}
else return; //leave now!!!!!
}
DbgPrint("Driver unloading\n");
IoDeleteDevice(DriverObject->DeviceObject);
#ifdef CETC
#ifndef CETC_RELEASE
UnloadCETC(); //not possible in the final build
#endif
#endif
#ifndef CETC_RELEASE
DbgPrint("DeviceString=%S\n",uszDeviceString.Buffer);
{
NTSTATUS r = IoDeleteSymbolicLink(&uszDeviceString);
DbgPrint("IoDeleteSymbolicLink: %x\n", r);
}
ExFreePool(BufDeviceString);
#endif
CleanProcessList();
ExDeleteResourceLite(&ProcesslistR);
RtlZeroMemory(&ProcesslistR, sizeof(ProcesslistR));
#if (NTDDI_VERSION >= NTDDI_VISTA)
if (DRMHandle)
{
DbgPrint("Unregistering DRM handle");
ObUnRegisterCallbacks(DRMHandle);
DRMHandle = NULL;
}
#endif
}
================================================
FILE: src/DBKDrvr.h
================================================
#ifndef DBKDRVR_H
#define DBKDRVR_H
#define dbkversion 2000027
#endif
================================================
FILE: src/DBKFunc.c
================================================
#pragma warning( disable: 4103)
#include <ntifs.h>
#include <ntddk.h>
#include "DBKFunc.h"
/*
#include "vmxhelper.h"
#include "interruptHook.h"
*/
#ifdef TESTCOMPILE
//small bypass to make test compiles function (this compiler doesn't have CLI/STI )
void _enable() {}
void _disable() {}
#endif
void forEachCpuPassive(PF f, UINT_PTR param)
/*
calls a specific function for each cpu that runs in passive mode
*/
{
CCHAR cpunr;
KAFFINITY cpus, original;
ULONG cpucount;
//KeIpiGenericCall is not present in xp
//count cpus first KeQueryActiveProcessorCount is not present in xp)
cpucount=0;
cpus=KeQueryActiveProcessors();
original=cpus;
while (cpus)
{
if (cpus % 2)
cpucount++;
cpus=cpus / 2;
}
cpus=KeQueryActiveProcessors();
cpunr=0;
while (cpus)
{
if (cpus % 2)
{
//bit is set
#if (NTDDI_VERSION >= NTDDI_VISTA)
KAFFINITY oldaffinity;
#endif
KAFFINITY newaffinity;
//DbgPrint("Calling passive function for cpunr %d\n", cpunr);
//set affinity
newaffinity=(KAFFINITY)(1 << cpunr);
#if (NTDDI_VERSION >= NTDDI_VISTA)
oldaffinity=KeSetSystemAffinityThreadEx(newaffinity);
#else
//XP and earlier (this routine is not called often, only when the user asks explicitly
{
LARGE_INTEGER delay;
delay.QuadPart=-50; //short wait just to be sure... (the docs do not say that a switch happens imeadiatly for the no Ex version)
KeSetSystemAffinityThread(newaffinity);
KeDelayExecutionThread(UserMode, FALSE, &delay);
}
#endif
//call function
f(param);
#if (NTDDI_VERSION >= NTDDI_VISTA)
KeRevertToUserAffinityThreadEx(oldaffinity);
#endif
}
cpus=cpus / 2;
cpunr++;
}
#if (NTDDI_VERSION < NTDDI_VISTA)
KeSetSystemAffinityThread(original);
#endif
}
void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
{
PKDPC dpc;
if (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments
preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);
dpc = ExAllocatePool(NonPagedPool, sizeof(KDPC));
KeInitializeDpc(dpc, dpcfunction, DeferredContext);
KeSetTargetProcessorDpc(dpc, cpunr);
KeInsertQueueDpc(dpc, SystemArgument1, SystemArgument2);
KeFlushQueuedDpcs();
ExFreePool(dpc);
}
void forEachCpu(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
/*
calls a specified dpcfunction for each cpu on the system
*/
{
CCHAR cpunr;
KAFFINITY cpus;
ULONG cpucount;
PKDPC dpc;
int dpcnr;
//KeIpiGenericCall is not present in xp
//count cpus first KeQueryActiveProcessorCount is not present in xp)
cpucount=0;
cpus=KeQueryActiveProcessors();
while (cpus)
{
if (cpus % 2)
cpucount++;
cpus=cpus / 2;
}
dpc=ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);
cpus=KeQueryActiveProcessors();
cpunr=0;
dpcnr=0;
while (cpus)
{
if (cpus % 2)
{
//bit is set
//DbgPrint("Calling dpc routine for cpunr %d (dpc=%p)\n", cpunr, &dpc[dpcnr]);
if (preDPCCallback)
preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);
KeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);
KeSetTargetProcessorDpc (&dpc[dpcnr], cpunr);
KeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);
KeFlushQueuedDpcs();
dpcnr++;
}
cpus=cpus / 2;
cpunr++;
}
ExFreePool(dpc);
}
void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback)
/*
calls a specified dpcfunction for each cpu on the system
*/
{
CCHAR cpunr;
KAFFINITY cpus;
ULONG cpucount;
PKDPC dpc;
int dpcnr;
//KeIpiGenericCall is not present in xp
//count cpus first KeQueryActiveProcessorCount is not present in xp)
cpucount = 0;
cpus = KeQueryActiveProcessors();
while (cpus)
{
if (cpus % 2)
cpucount++;
cpus = cpus / 2;
}
dpc = ExAllocatePool(NonPagedPool, sizeof(KDPC)*cpucount);
cpus = KeQueryActiveProcessors();
cpunr = 0;
dpcnr = 0;
while (cpus)
{
if (cpus % 2)
{
//bit is set
//DbgPrint("Calling dpc routine for cpunr %d\n", cpunr);
if (preDPCCallback) //if preDPCCallback is set call it which may change the system arguments
preDPCCallback(cpunr, dpcfunction, DeferredContext, &SystemArgument1, &SystemArgument2);
KeInitializeDpc(&dpc[dpcnr], dpcfunction, DeferredContext);
KeSetTargetProcessorDpc(&dpc[dpcnr], cpunr);
KeInsertQueueDpc(&dpc[dpcnr], SystemArgument1, SystemArgument2);
dpcnr++;
}
cpus = cpus / 2;
cpunr++;
}
KeFlushQueuedDpcs();
ExFreePool(dpc);
}
//own critical section implementation for use when the os is pretty much useless (dbvm tech)
void spinlock(volatile LONG *lockvar)
{
while (1)
{
//it was 0, let's see if we can set it to 1
//race who can set it to 1:
if (_InterlockedExchange((volatile LONG *)lockvar, 1)==0)
return; //lock aquired, else continue loop
_mm_pause();
}
}
void csEnter(PcriticalSection CS)
{
EFLAGS oldstate=getEflags();
if ((CS->locked) && (CS->cpunr==cpunr()))
{
//already locked but the locker is this cpu, so allow, just increase lockcount
CS->lockcount++;
return;
}
disableInterrupts(); //disable interrupts to prevent taskswitch in same cpu
spinlock(&(CS->locked)); //sets CS->locked to 1
//here so the lock is aquired and locked is 1
CS->lockcount=1;
CS->cpunr=cpunr();
CS->oldIFstate=oldstate.IF;
}
void csLeave(PcriticalSection CS)
{
if ((CS->locked) && (CS->cpunr==cpunr()))
{
CS->lockcount--;
if (CS->lockcount==0)
{
//unlock
if (CS->oldIFstate)
enableInterrupts();
CS->cpunr=-1; //set to an cpunr
CS->locked=0;
}
}
}
int getCpuCount(void)
{
KAFFINITY ap=KeQueryActiveProcessors();
int count=0;
while (ap>0)
{
if (ap % 2)
count++;
ap=ap / 2;
}
return count;
}
int isPrefix(unsigned char b)
{
switch (b)
{
case 0x26:
case 0x2e:
case 0x36:
case 0x3e:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0xf0: //lock
case 0xf2: //repne
case 0xf3: //rep
return 1;
default:
return 0;
}
}
UINT64 getDR7(void)
{
return __readdr(7);
}
int cpunr(void)
{
DWORD x[4];
__cpuid(&x[0],1);
return (x[1] >> 24)+1;
}
EFLAGS getEflags(void)
{
UINT64 x=__getcallerseflags();
PEFLAGS y = (PEFLAGS)&x;
return *y;
}
UINT64 readMSR(DWORD msr)
{
return __readmsr(msr);
}
void setCR0(UINT64 newcr0)
{
__writecr0(newcr0);
}
UINT64 getCR0(void)
{
return __readcr0();
}
UINT64 getCR2(void)
{
return __readcr2();
}
void setCR3(UINT64 newCR3)
{
__writecr3((UINT_PTR)newCR3);
}
UINT64 getCR3(void)
{
return __readcr3();
}
void setCR4(UINT64 newcr4)
{
__writecr4(newcr4);
}
UINT64 getCR4(void)
{
return __readcr4();
}
void GetIDT(PIDT pIdt)
{
__sidt(pIdt);
}
void enableInterrupts(void)
{
#ifdef AMD64
_enable();
#else
__asm{sti};
#endif
}
void disableInterrupts(void)
{
#ifdef AMD64
_disable();
#else
__asm{cli};
#endif
}
UINT64 getTSC(void)
{
return __rdtsc();
}
#ifndef AMD64
//function declarations that can be done inline without needing an .asm file
_declspec( naked ) WORD getSS(void)
{
__asm
{
mov ax,ss
ret
}
}
_declspec( naked ) WORD getCS(void)
{
__asm
{
mov ax,cs
ret
}
}
_declspec( naked ) WORD getDS(void)
{
__asm
{
mov ax,ds
ret
}
}
_declspec( naked ) WORD getES(void)
{
__asm
{
mov ax,es
ret
}
}
_declspec( naked ) WORD getFS(void)
{
__asm
{
mov ax,fs
ret
}
}
_declspec( naked ) WORD getGS(void)
{
__asm
{
mov ax,gs
ret
}
}
_declspec( naked ) ULONG getRSP(void) //...
{
__asm
{
mov eax,esp
add eax,4 //don't add this call
ret
}
}
_declspec( naked ) ULONG getRBP(void)
{
__asm
{
mov eax,ebp
ret
}
}
_declspec( naked ) ULONG getRAX(void)
{
__asm
{
mov eax,eax
ret
}
}
_declspec( naked ) ULONG getRBX(void)
{
__asm
{
mov eax,ebx
ret
}
}
_declspec( naked ) ULONG getRCX(void)
{
__asm
{
mov eax,ecx
ret
}
}
_declspec( naked ) ULONG getRDX(void)
{
__asm
{
mov eax,edx
ret
}
}
_declspec( naked ) ULONG getRSI(void)
{
__asm
{
mov eax,esi
ret
}
}
_declspec( naked ) ULONG getRDI(void)
{
__asm
{
mov eax,edi
ret
}
}
_declspec( naked ) unsigned short GetTR(void)
{
__asm{
STR AX
ret
}
}
void GetGDT(PGDT pGdt)
{
__asm
{
MOV EAX, [pGdt]
SGDT [EAX]
}
}
_declspec( naked )WORD GetLDT()
{
__asm
{
SLDT ax
ret
}
}
#endif
================================================
FILE: src/DBKFunc.h
================================================
#ifndef DBKFUNC_H
#define DBKFUNC_H
#pragma warning( disable: 4214 )
#include <ntifs.h>
#include <ntstrsafe.h>
#include <windef.h>
#include "interruptHook.h"
#ifdef RELEASE
#define DbgPrint(...)
#endif
int _fltused;
typedef VOID F(UINT_PTR param);
typedef F *PF;
typedef VOID PREDPC_CALLBACK(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID DeferredContext, PVOID *SystemArgument1, PVOID *SystemArgument2);
typedef PREDPC_CALLBACK *PPREDPC_CALLBACK;
typedef struct _criticalSection
{
LONG locked;
int cpunr; //unique id for a cpu
int lockcount;
int oldIFstate;
} criticalSection, *PcriticalSection;
//ntosp.h
typedef
_Function_class_(KNORMAL_ROUTINE)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KNORMAL_ROUTINE(
_In_opt_ PVOID NormalContext,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2
);
typedef KNORMAL_ROUTINE *PKNORMAL_ROUTINE;
typedef
_Function_class_(KKERNEL_ROUTINE)
_IRQL_requires_max_(APC_LEVEL)
_IRQL_requires_min_(APC_LEVEL)
_IRQL_requires_(APC_LEVEL)
_IRQL_requires_same_
VOID
KKERNEL_ROUTINE(
_In_ struct _KAPC *Apc,
_Inout_ PKNORMAL_ROUTINE *NormalRoutine,
_Inout_ PVOID *NormalContext,
_Inout_ PVOID *SystemArgument1,
_Inout_ PVOID *SystemArgument2
);
typedef KKERNEL_ROUTINE *PKKERNEL_ROUTINE;
typedef
_Function_class_(KRUNDOWN_ROUTINE)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KRUNDOWN_ROUTINE(
_In_ struct _KAPC *Apc
);
typedef KRUNDOWN_ROUTINE *PKRUNDOWN_ROUTINE;
typedef
_IRQL_requires_same_
_Function_class_(KENUM_ROUTINE)
VOID
KENUM_ROUTINE(
_In_reads_(_Inexpressible_(Length)) PVOID Data,
_In_ ULONG Length,
_In_ PVOID Context
);
typedef KENUM_ROUTINE *PKENUM_ROUTINE;
typedef enum _KAPC_ENVIRONMENT {
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
} KAPC_ENVIRONMENT;
NTKERNELAPI
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KeEnumerateQueueApc(
_Inout_ PKTHREAD Thread,
_In_ PKENUM_ROUTINE CallbackRoutine,
_In_ PVOID Context,
_In_opt_ KPROCESSOR_MODE *ApcMode
);
NTKERNELAPI
_IRQL_requires_same_
_When_(Environment != OriginalApcEnvironment, __drv_reportError("Caution: "
"Using an APC environment other than the original environment can lead to "
"a system bugcheck if the target thread is attached to a process with APCs "
"disabled. APC environments should be used with care."))
VOID
KeInitializeApc(
_Out_ PRKAPC Apc,
_In_ PRKTHREAD Thread,
_In_ KAPC_ENVIRONMENT Environment,
_In_ PKKERNEL_ROUTINE KernelRoutine,
_In_opt_ PKRUNDOWN_ROUTINE RundownRoutine,
_In_opt_ PKNORMAL_ROUTINE NormalRoutine,
_In_opt_ KPROCESSOR_MODE ProcessorMode,
_In_opt_ PVOID NormalContext
);
NTKERNELAPI
_Must_inspect_result_
_IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_same_
BOOLEAN
KeInsertQueueApc(
_Inout_ PRKAPC Apc,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2,
_In_ KPRIORITY Increment
);
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
struct PTEStruct
{
unsigned P : 1; // present (1 = present)
unsigned RW : 1; // read/write
unsigned US : 1; // user/supervisor
unsigned PWT : 1; // page-level write-through
unsigned PCD : 1; // page-level cache disabled
unsigned A : 1; // accessed
unsigned Reserved : 1; // dirty
unsigned PS : 1; // page size (0 = 4-KB page)
unsigned G : 1; // global page
unsigned A1 : 1; // available 1 aka copy-on-write
unsigned A2 : 1; // available 2/ is 1 when paged to disk
unsigned A3 : 1; // available 3
unsigned PFN : 20; // page-frame number
};
//typedef struct PTEStruct *PPDPTE;
//typedef struct PTEStruct *PPDE;
//typedef struct PTEStruct *PPTE;
struct PTEStruct64
{
unsigned long long P : 1; // present (1 = present)
unsigned long long RW : 1; // read/write
unsigned long long US : 1; // user/supervisor
unsigned long long PWT : 1; // page-level write-through
unsigned long long PCD : 1; // page-level cache disabled
unsigned long long A : 1; // accessed
unsigned long long Reserved : 1; // dirty
unsigned long long PS : 1; // page size (0 = 4-KB page)
unsigned long long G : 1; // global page
unsigned long long A1 : 1; // available 1 aka copy-on-write
unsigned long long A2 : 1; // available 2/ is 1 when paged to disk
unsigned long long A3 : 1; // available 3
unsigned long long PFN : 52; // page-frame number
};
//typedef struct PTEStruct64 *PPDPTE_PAE;
//typedef struct PTEStruct64 *PPDE_PAE;
//typedef struct PTEStruct64 *PPTE_PAE;
typedef struct tagDebugregs
{
ULONG DR0;
ULONG DR1;
ULONG DR2;
ULONG DR3;
ULONG DR5;
ULONG DR6;
ULONG DR7;
} Debugregs;
typedef struct
{
unsigned CF :1; // 0
unsigned reserved1 :1; // 1
unsigned PF :1; // 2
unsigned reserved2 :1; // 3
unsigned AF :1; // 4
unsigned reserved3 :1; // 5
unsigned ZF :1; // 6
unsigned SF :1; // 7
unsigned TF :1; // 8
unsigned IF :1; // 9
unsigned DF :1; // 10
unsigned OF :1; // 11
unsigned IOPL :2; // 12+13
unsigned NT :1; // 14
unsigned reserved4 :1; // 15
unsigned RF :1; // 16
unsigned VM :1; // 17
unsigned AC :1; // 18
unsigned VIF :1; // 19
unsigned VIP :1; // 20
unsigned ID :1; // 21
unsigned reserved5 :10; // 22-31
#ifdef AMD64
unsigned reserved6 :8;
unsigned reserved7 :8;
unsigned reserved8 :8;
unsigned reserved9 :8;
#endif
} EFLAGS,*PEFLAGS;
typedef struct tagDebugReg7
{
unsigned L0 :1; // 0
unsigned G0 :1; // 1
unsigned L1 :1; // 2
unsigned G1 :1; // 3
unsigned L2 :1; // 4
unsigned G2 :1; // 5
unsigned L3 :1; // 6
unsigned G3 :1; // 7
unsigned GL :1; // 8
unsigned GE :1; // 9
unsigned undefined_1: 1; //1 10
unsigned RTM : 1; // 11
unsigned undefined_0: 1; //0 12
unsigned GD :1; // 13
unsigned undefined2 :2; // 00
unsigned RW0 :2;
unsigned LEN0 :2;
unsigned RW1 :2;
unsigned LEN1 :2;
unsigned RW2 :2;
unsigned LEN2 :2;
unsigned RW3 :2;
unsigned LEN3 :2;
#ifdef AMD64
unsigned undefined3 :8;
unsigned undefined4 :8;
unsigned undefined5 :8;
unsigned undefined6 :8;
#endif
} DebugReg7;
typedef struct DebugReg6
{
unsigned B0 :1;
unsigned B1 :1;
unsigned B2 :1;
unsigned B3 :1;
unsigned undefined1 :9; // 011111111
unsigned BD :1;
unsigned BS :1;
unsigned BT :1;
unsigned RTM : 1; //0=triggered
unsigned undefined2 :15; // 111111111111111
#ifdef AMD64
unsigned undefined3 :8;
unsigned undefined4 :8;
unsigned undefined5 :8;
unsigned undefined6 :8;
#endif
} DebugReg6;
#pragma pack(2) //allignment of 2 bytes
typedef struct tagGDT
{
WORD wLimit;
PVOID vector;
} GDT, *PGDT;
#pragma pack()
//UCHAR BufferSize;
void GetIDT(PIDT pIdt);
#ifdef AMD64
extern void _fxsave(volatile void *);
extern void GetGDT(PGDT pGdt);
extern WORD GetLDT();
extern WORD GetTR(void);
#else
void GetGDT(PGDT pGdt);
WORD GetLDT();
WORD GetTR(void);
#endif
UINT64 readMSR(DWORD msr);
UINT64 getDR7(void);
void setCR0(UINT64 newCR0);
UINT64 getCR0(void);
UINT64 getCR2(void);
void setCR3(UINT64 newCR3);
UINT64 getCR3(void);
UINT64 getCR4(void);
void setCR4(UINT64 newcr4);
UINT64 getTSC(void);
#ifdef AMD64
extern WORD getCS(void);
extern WORD getSS(void);
extern WORD getDS(void);
extern WORD getES(void);
extern WORD getFS(void);
extern WORD getGS(void);
extern UINT64 getRSP(void);
extern UINT64 getRBP(void);
extern UINT64 getRAX(void);
extern UINT64 getRBX(void);
extern UINT64 getRCX(void);
extern UINT64 getRDX(void);
extern UINT64 getRSI(void);
extern UINT64 getRDI(void);
#else
WORD getCS(void);
WORD getSS(void);
WORD getDS(void);
WORD getES(void);
WORD getFS(void);
WORD getGS(void);
ULONG getRSP(void);
ULONG getRBP(void);
ULONG getRAX(void);
ULONG getRBX(void);
ULONG getRCX(void);
ULONG getRDX(void);
ULONG getRSI(void);
ULONG getRDI(void);
#endif
extern UINT64 getR8(void);
extern UINT64 getR9(void);
extern UINT64 getR10(void);
extern UINT64 getR11(void);
extern UINT64 getR12(void);
extern UINT64 getR13(void);
extern UINT64 getR14(void);
extern UINT64 getR15(void);
extern UINT64 getAccessRights(UINT64 segment);
extern UINT64 getSegmentLimit(UINT64 segment);
int getCpuCount(void);
BOOL loadedbydbvm;
int PTESize;
UINT_PTR PAGE_SIZE_LARGE;
UINT_PTR MAX_PDE_POS;
UINT_PTR MAX_PTE_POS;
int cpu_stepping;
int cpu_model;
int cpu_familyID;
int cpu_type;
int cpu_ext_modelID;
int cpu_ext_familyID;
int KernelCodeStepping;
int KernelWritesIgnoreWP;
int isPrefix(unsigned char b);
EFLAGS getEflags(void);
int cpunr(void);
void disableInterrupts(void);
void enableInterrupts(void);
void csEnter(PcriticalSection CS);
void csLeave(PcriticalSection CS);
void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpu(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2, OPTIONAL PPREDPC_CALLBACK preDPCCallback);
void forEachCpuPassive(PF f, UINT_PTR param);
#endif;
================================================
FILE: src/IOPLDispatcher.c
================================================
#pragma warning( disable: 4100 4101 4103 4189)
#include "IOPLDispatcher.h"
#include "DBKFunc.h"
#include "DBKDrvr.h"
#include "memscan.h"
#include "deepkernel.h"
#include "processlist.h"
#include "threads.h"
#include "interruptHook.h"
#include "debugger.h"
#include "vmxhelper.h"
#include "vmxoffload.h"
#include "ultimap.h"
#include "ultimap2.h"
UINT64 PhysicalMemoryRanges=0; //initialized once, and used thereafter. If the user adds/removes ram at runtime, screw him and make him the reload the driver
UINT64 PhysicalMemoryRangesListSize=0;
#if (NTDDI_VERSION >= NTDDI_VISTA)
PVOID DRMHandle = NULL;
PEPROCESS DRMProcess = NULL;
PEPROCESS DRMProcess2 = NULL;
#endif
typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
GET_PROCESS_IMAGE_NAME PsGetProcessImageFileName;
/*
typedef struct
{
int listcount;
char cpunrs[255];
} CPULISTFILLSTRUCT, *PCPULISTFILLSTRUCT;
VOID GetCPUIDS_all(PCPULISTFILLSTRUCT p)
{
DbgPrint("GetCPUIDS_all(for cpu %d)\n", cpunr());
if (p->listcount<255)
{
p->cpunrs[p->listcount]=cpunr();
p->listcount++;
}
}
*/
NTSYSAPI NTSTATUS NTAPI ZwQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL);
void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
ULONG_PTR iswow64;
ExFreePool(Apc);
DbgPrint("My second kernelmode apc!!!!\n");
DbgPrint("SystemArgument1=%x\n",*(PULONG)SystemArgument1);
DbgPrint("SystemArgument2=%x\n", *(PULONG)SystemArgument2);
if (ZwQueryInformationProcess(ZwCurrentProcess(), ProcessWow64Information, &iswow64, sizeof(iswow64), NULL) == STATUS_SUCCESS)
{
#if (NTDDI_VERSION >= NTDDI_VISTA)
if (iswow64)
{
DbgPrint("WOW64 apc");
PsWrapApcWow64Thread(NormalContext, (PVOID*)NormalRoutine);
}
#endif
}
}
void nothing2(PVOID arg1, PVOID arg2, PVOID arg3)
{
return;
}
void mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
//kernelmode apc, always gets executed
PKAPC kApc;
LARGE_INTEGER Timeout;
kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
ExFreePool(Apc);
DbgPrint("My kernelmode apc!!!!(irql=%d)\n", KeGetCurrentIrql());
DbgPrint("NormalRoutine=%p\n",*(PUINT_PTR)NormalRoutine);
DbgPrint("NormalContext=%p\n",*(PUINT_PTR)NormalContext);
DbgPrint("SystemArgument1=%p\n",*(PUINT_PTR)SystemArgument1);
DbgPrint("SystemArgument2=%p\n",*(PUINT_PTR)SystemArgument2);
KeInitializeApc(kApc,
(PKTHREAD)PsGetCurrentThread(),
0,
(PKKERNEL_ROUTINE)mykapc2,
NULL,
(PKNORMAL_ROUTINE)*(PUINT_PTR)SystemArgument1,
UserMode,
(PVOID)*(PUINT_PTR)NormalContext
);
KeInsertQueueApc (kApc, (PVOID)*(PUINT_PTR)SystemArgument1, (PVOID)*(PUINT_PTR)SystemArgument2, 0);
//wait in usermode (so interruptable by a usermode apc)
Timeout.QuadPart = 0;
KeDelayExecutionThread(UserMode, TRUE, &Timeout);
return;
}
void nothing(PVOID arg1, PVOID arg2, PVOID arg3)
{
return;
}
void CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)
{
PKTHREAD kThread;
PKAPC kApc;
kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
kThread=(PKTHREAD)getPEThread(threadid);
DbgPrint("(PVOID)KThread=%p\n",kThread);
DbgPrint("addresstoexecute=%p\n", addresstoexecute);
KeInitializeApc(kApc,
kThread,
0,
(PKKERNEL_ROUTINE)mykapc,
NULL,
(PKNORMAL_ROUTINE)nothing,
KernelMode,
0
);
KeInsertQueueApc (kApc, addresstoexecute, addresstoexecute, 0);
}
#define PROCESS_TERMINATE (0x0001)
#define PROCESS_CREATE_THREAD (0x0002)
#define PROCESS_SET_SESSIONID (0x0004)
#define PROCESS_VM_OPERATION (0x0008)
#define PROCESS_VM_READ (0x0010)
#define PROCESS_VM_WRITE (0x0020)
#define PROCESS_DUP_HANDLE (0x0040)
#define PROCESS_CREATE_PROCESS (0x0080)
#define PROCESS_SET_QUOTA (0x0100)
#define PROCESS_SET_INFORMATION (0x0200)
#define PROCESS_QUERY_INFORMATION (0x0400)
#define PROCESS_SUSPEND_RESUME (0x0800)
#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
#if (NTDDI_VERSION >= NTDDI_VISTA)
OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
if (DRMProcess == NULL)
return OB_PREOP_SUCCESS;
if (PsGetCurrentProcess() == DRMProcess)
return OB_PREOP_SUCCESS;
if (OperationInformation->ObjectType == *PsThreadType)
{
if ((PsGetProcessId(DRMProcess) == PsGetThreadProcessId(OperationInformation->Object)) || ((DRMProcess2) && (PsGetProcessId(DRMProcess2) == PsGetThreadProcessId(OperationInformation->Object))))
{
//probably block it
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
//create handle
ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
DbgPrint("PID %d opened a handle to the a CE thread with access mask %x", PsGetCurrentProcessId(), da);
da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
}
else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
//duplicate handle
ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;
DbgPrint("PID %d duplicated a handle to a CE thread with access mask %x", PsGetCurrentProcessId(), da);
da = da & (THREAD_SET_LIMITED_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION);
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
}
}
}
return OB_PREOP_SUCCESS;
}
VOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
//DbgPrint("ProcessPostCallback");
}
OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation)
{
if (DRMProcess == NULL)
return OB_PREOP_SUCCESS;
//if (PsGetCurrentProcess() == DRMProcess)
// return OB_PREOP_SUCCESS;
if (OperationInformation->ObjectType == *PsProcessType)
{
if ((OperationInformation->Object == DRMProcess) || (OperationInformation->Object == DRMProcess2))
{
//probably block it
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE)
{
//create handle
ACCESS_MASK da = OperationInformation->Parameters->CreateHandleInformation.DesiredAccess;
DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);
da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);
//da = da & PROCESS_SUSPEND_RESUME;
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess = 0;// da;
}
else if (OperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE)
{
//duplicate handle
ACCESS_MASK da = OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess;
DbgPrint("PID %d(%p) opened a handle to the CE process(%p) with access mask %x", PsGetCurrentProcessId(), PsGetCurrentProcess(), DRMProcess, da);
da = da & (PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SUSPEND_RESUME);
//da = da & PROCESS_SUSPEND_RESUME;
OperationInformation->Parameters->DuplicateHandleInformation.DesiredAccess = 0;// da;
}
}
}
return OB_PREOP_SUCCESS;
}
VOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_INFORMATION OperationInformation)
{
//DbgPrint("ProcessPostCallback");
}
#endif
BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned)
/*
Called if dbvm has loaded the driver. Use this to setup a fake irp
*/
{
//allocate a in and out buffer
//setup a fake IRP
IRP FakeIRP;
BOOL r;
PVOID buffer;
buffer=ExAllocatePool(PagedPool, max(nInBufferSize, nOutBufferSize));
RtlCopyMemory(buffer, lpInBuffer, nInBufferSize);
DbgPrint("DispatchIoctlDBVM\n");
FakeIRP.AssociatedIrp.SystemBuffer=buffer;
FakeIRP.Flags=IoControlCode; //(ab)using an unused element
r=DispatchIoctl(DeviceObject, &FakeIRP)==STATUS_SUCCESS;
RtlCopyMemory(lpOutBuffer, buffer, nOutBufferSize);
ExFreePool(buffer);
return r;
}
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION irpStack=NULL;
LUID sedebugprivUID;
ULONG IoControlCode;
if (!loadedbydbvm)
{
irpStack=IoGetCurrentIrpStackLocation(Irp);
IoControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
}
else
IoControlCode=Irp->Flags;
//DbgPrint("DispatchIoctl. IoControlCode=%x\n", IoControlCode);
#ifdef TOBESIGNED
sedebugprivUID.LowPart=SE_DEBUG_PRIVILEGE;
sedebugprivUID.HighPart=0;
if (SeSinglePrivilegeCheck(sedebugprivUID, UserMode)==FALSE)
{
DbgPrint("DispatchIoctl called by a process without SeDebugPrivilege");
return STATUS_UNSUCCESSFUL;
}
#endif
switch(IoControlCode)
{
case IOCTL_CE_READMEMORY:
__try
{
struct input
{
UINT64 processid;
UINT64 startaddress;
WORD bytestoread;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ReadProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestoread,pinp) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
__except(1)
{
ntStatus = STATUS_UNSUCCESSFUL;
};
break;
case IOCTL_CE_WRITEMEMORY:
__try
{
struct input
{
UINT64 processid;
UINT64 startaddress;
WORD bytestowrite;
} *pinp,inp;
DbgPrint("sizeof(inp)=%d\n",sizeof(inp));
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=WriteProcessMemory((DWORD)pinp->processid,NULL,(PVOID)(UINT_PTR)pinp->startaddress,pinp->bytestowrite,(PVOID)((UINT_PTR)pinp+sizeof(inp))) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}
__except(1)
{
//something went wrong and I don't know what
ntStatus = STATUS_UNSUCCESSFUL;
};
break;
case IOCTL_CE_OPENPROCESS:
{
PEPROCESS selectedprocess = NULL;
ULONG processid=*(PULONG)Irp->AssociatedIrp.SystemBuffer;
HANDLE ProcessHandle = GetHandleForProcessID((HANDLE)processid);
struct out
{
UINT64 h;
BYTE Special;
} *POutput = Irp->AssociatedIrp.SystemBuffer;
ntStatus = STATUS_SUCCESS;
if (ProcessHandle == 0)
{
POutput->Special = 0;
__try
{
ProcessHandle = 0;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid), &selectedprocess) == STATUS_SUCCESS)
{
//DbgPrint("Calling ObOpenObjectByPointer\n");
ntStatus = ObOpenObjectByPointer(
selectedprocess,
0,
NULL,
PROCESS_ALL_ACCESS,
*PsProcessType,
KernelMode, //UserMode,
&ProcessHandle);
//DbgPrint("ntStatus=%x",ntStatus);
}
}
__except (1)
{
ntStatus = STATUS_UNSUCCESSFUL;
}
}
else
{
//DbgPrint("ProcessHandle=%x", (int)ProcessHandle);
POutput->Special = 1;
}
if (selectedprocess)
{
ObDereferenceObject(selectedprocess);
}
POutput->h=(UINT64)ProcessHandle;
break;
}
case IOCTL_CE_OPENTHREAD:
{
HANDLE ThreadHandle;
CLIENT_ID ClientID;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlZeroMemory(&ObjectAttributes,sizeof(OBJECT_ATTRIBUTES));
ntStatus=STATUS_SUCCESS;
ClientID.UniqueProcess=0;
ClientID.UniqueThread=(HANDLE)(UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer;
ThreadHandle=0;
__try
{
ThreadHandle=0;
ntStatus=ZwOpenThread(&ThreadHandle,PROCESS_ALL_ACCESS,&ObjectAttributes,&ClientID);
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)ThreadHandle;
break;
}
case IOCTL_CE_MAKEWRITABLE:
{
#ifdef AMD64
//untill I know how win64 handles paging, not implemented
#else
struct InputBuf
{
UINT64 StartAddress;
ULONG Size;
BYTE CopyOnWrite;
} *PInputBuf;
PInputBuf=Irp->AssociatedIrp.SystemBuffer;
ntStatus=MakeWritable((PVOID)(UINT_PTR)PInputBuf->StartAddress,PInputBuf->Size,(PInputBuf->CopyOnWrite==1)) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
#endif
break;
}
case IOCTL_CE_QUERY_VIRTUAL_MEMORY:
{
struct InputBuf
{
UINT64 ProcessID;
UINT64 StartAddress;
} *PInputBuf;
struct OutputBuf
{
UINT64 length;
DWORD protection;
} *POutputBuf;
UINT_PTR BaseAddress;
UINT_PTR length;
BOOL ShowResult=0;
ntStatus=STATUS_SUCCESS;
PInputBuf=Irp->AssociatedIrp.SystemBuffer;
POutputBuf=Irp->AssociatedIrp.SystemBuffer;
if (PInputBuf->StartAddress==(UINT64)0x12000)
ShowResult=1;
__try
{
ntStatus = GetMemoryRegionData((DWORD)PInputBuf->ProcessID, NULL, (PVOID)(UINT_PTR)(PInputBuf->StartAddress), &(POutputBuf->protection), &length, &BaseAddress);
}
__except(1)
{
DbgPrint("GetMemoryRegionData error");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
POutputBuf->length=(UINT64)length;
if (ShowResult)
{
DbgPrint("GetMemoryRegionData returned %x\n",ntStatus);
DbgPrint("protection=%x\n",POutputBuf->protection);
DbgPrint("length=%p\n",POutputBuf->length);
DbgPrint("BaseAddress=%p\n", BaseAddress);
}
break;
}
case IOCTL_CE_TEST: //just a test to see it's working
{
UNICODE_STRING test;
PVOID x;
QWORD a, b;
_disable();
a = __rdtsc();
b = __rdtsc();
_enable();
DbgPrint("%d\n", (int)(b - a));
break;
}
case IOCTL_CE_GETPETHREAD:
{
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)getPEThread((UINT_PTR)*(PULONG)Irp->AssociatedIrp.SystemBuffer);
ntStatus= STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETPEPROCESS:
{
DWORD processid=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;
PEPROCESS selectedprocess;
if (processid==0)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
else
{
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(processid),&selectedprocess)==STATUS_SUCCESS)
{
#ifdef AMD64
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(UINT64)selectedprocess;
#else
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=(DWORD)selectedprocess;
#endif
//DbgPrint("PEProcess=%llx\n", *(PUINT64)Irp->AssociatedIrp.SystemBuffer);
ObDereferenceObject(selectedprocess);
}
else
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
}
ntStatus= STATUS_SUCCESS;
break;
}
case IOCTL_CE_READPHYSICALMEMORY:
{
struct input
{
UINT64 startaddress;
UINT64 bytestoread;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_READPHYSICALMEMORY:pinp->startaddress=%x, pinp->bytestoread=%d", pinp->startaddress, pinp->bytestoread);
ntStatus = ReadPhysicalMemory((PVOID)(UINT_PTR)pinp->startaddress, (UINT_PTR)pinp->bytestoread, pinp);
break;
}
case IOCTL_CE_WRITEPHYSICALMEMORY:
{
HANDLE physmem;
UNICODE_STRING physmemString;
OBJECT_ATTRIBUTES attributes;
WCHAR physmemName[] = L"\\device\\physicalmemory";
UCHAR* memoryview;
RtlInitUnicodeString( &physmemString, physmemName );
InitializeObjectAttributes( &attributes, &physmemString, OBJ_CASE_INSENSITIVE, NULL, NULL );
ntStatus=ZwOpenSection( &physmem, SECTION_ALL_ACCESS, &attributes );
if (ntStatus==STATUS_SUCCESS)
{
//hey look, it didn't kill it
struct input
{
UINT64 startaddress;
UINT64 bytestoread;
} *pinp;
UCHAR* pinp2;
SIZE_T length;
PHYSICAL_ADDRESS viewBase;
UINT_PTR offset;
UINT_PTR toread;
pinp=Irp->AssociatedIrp.SystemBuffer;
pinp2=(UCHAR *)pinp;
viewBase.QuadPart = (ULONGLONG)(pinp->startaddress);
length=0x2000;//pinp->bytestoread;
toread=(UINT_PTR)pinp->bytestoread;
memoryview=NULL;
ntStatus=ZwMapViewOfSection(
physmem, //sectionhandle
NtCurrentProcess(), //processhandle
&memoryview, //BaseAddress
0L, //ZeroBits
length, //CommitSize
&viewBase, //SectionOffset
&length, //ViewSize
ViewShare,
0,
PAGE_READWRITE);
if (ntStatus==STATUS_SUCCESS)
{
offset=(UINT_PTR)(pinp->startaddress)-(UINT_PTR)viewBase.QuadPart;
RtlCopyMemory(&memoryview[offset],&pinp2[16],toread);
ZwUnmapViewOfSection(
NtCurrentProcess(), //processhandle
memoryview);
}
ZwClose(physmem);
}
break;
}
case IOCTL_CE_GETPHYSICALADDRESS:
{
struct input
{
UINT64 ProcessID;
UINT64 BaseAddress;
} *pinp;
PEPROCESS selectedprocess;
PHYSICAL_ADDRESS physical;
physical.QuadPart = 0;
ntStatus=STATUS_SUCCESS;
pinp=Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_GETPHYSICALADDRESS. ProcessID(%p)=%x BaseAddress(%p)=%x\n",&pinp->ProcessID, pinp->ProcessID, &pinp->BaseAddress, pinp->BaseAddress);
__try
{
//switch to the selected process
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(pinp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess,&apc_state);
__try
{
physical=MmGetPhysicalAddress((PVOID)(UINT_PTR)pinp->BaseAddress);
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
ObDereferenceObject(selectedprocess);
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
if (ntStatus==STATUS_SUCCESS)
{
//DbgPrint("physical.LowPart=%x",physical.LowPart);
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&physical.QuadPart,8);
}
break;
}
case IOCTL_CE_GETMEMORYRANGES:
{
struct output
{
UINT64 address;
UINT64 size;
} *poutp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_GETMEMORYRANGES\n");
if (PhysicalMemoryRanges==0)
{
__try
{
PPHYSICAL_MEMORY_RANGE mr=MmGetPhysicalMemoryRanges();
if (mr)
{
//find the end
int i;
PhysicalMemoryRanges=(UINT64)mr;
for (i=0; mr[i].NumberOfBytes.QuadPart || mr[i].BaseAddress.QuadPart; i++);
PhysicalMemoryRangesListSize=(UINT64)(&mr[i])-(UINT64)(&mr[0]);
}
}
__except(1)
{
//just in case this function decides to bug out in the future
}
}
poutp->address=PhysicalMemoryRanges;
poutp->size=PhysicalMemoryRangesListSize;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETSDTADDRESS:
{
DbgPrint("Obsolete\n");
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
case IOCTL_CE_GETCR0:
{
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=getCR0();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETCR4:
{
//seems CR4 isn't seen as a register...
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=(UINT64)getCR4();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETCR4:
{
//seems CR4 isn't seen as a register...
ULONG cr4reg=*(ULONG*)Irp->AssociatedIrp.SystemBuffer;
setCR4((UINT64)cr4reg);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETCR3:
{
UINT_PTR cr3reg=0;
PEPROCESS selectedprocess;
ntStatus=STATUS_SUCCESS;
//switch context to the selected process. (processid is stored in the systembuffer)
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(*(ULONG*)Irp->AssociatedIrp.SystemBuffer),&selectedprocess)==STATUS_SUCCESS)
{
__try
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess,&apc_state);
__try
{
cr3reg=(UINT_PTR)getCR3();
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
DbgPrint("cr3reg=%p\n",cr3reg);
*(UINT64*)Irp->AssociatedIrp.SystemBuffer=cr3reg;
break;
}
case IOCTL_CE_GETSDT:
{
//returns the address of KeServiceDescriptorTable
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
case IOCTL_CE_GETIDT:
{
//returns the address of the IDT of the current CPU
IDT idt;
RtlZeroMemory(&idt,sizeof(IDT));
GetIDT(&idt);
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8); //so that the 32-bit version doesn't have to deal with garbage at the end
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&idt,sizeof(IDT)); //copy idt
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETGDT:
{
//returns the address of the IDT of the current CPU
GDT gdt;
RtlZeroMemory(&gdt,sizeof(GDT));
GetGDT(&gdt);
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer,2+8);
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&gdt,sizeof(GDT)); //copy gdt
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_LAUNCHDBVM:
{
struct intput
{
UINT64 dbvmimgpath;
DWORD32 cpuid;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_LAUNCHDBVM\n");
initializeDBVM((PCWSTR)(UINT_PTR)pinp->dbvmimgpath);
if (pinp->cpuid == 0xffffffff) {
forEachCpu(vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);
cleanupDBVM();
}
else
forOneCpu((CCHAR)pinp->cpuid, vmxoffload_dpc, NULL, NULL, NULL, vmxoffload_override);
DbgPrint("Returned from vmxoffload()\n");
break;
}
case IOCTL_CE_HOOKINTS: //hooks the DEBUG interrupts
{
DbgPrint("IOCTL_CE_HOOKINTS\n");
forEachCpu(debugger_initHookForCurrentCPU_DPC, NULL, NULL, NULL, NULL);
ntStatus=STATUS_SUCCESS;
/*
DbgPrint("IOCTL_CE_HOOKINTS for cpu %d\n", cpunr());
if (debugger_initHookForCurrentCPU())
ntStatus=STATUS_SUCCESS;
else
ntStatus=STATUS_UNSUCCESSFUL;*/
break;
}
case IOCTL_CE_USERDEFINEDINTERRUPTHOOK:
{
struct intput
{
UINT64 interruptnumber;
UINT64 newCS;
UINT64 newRIP;
UINT64 addressofjumpback;
} *pinp;
DbgPrint("IOCTL_CE_USERDEFINEDINTERRUPTHOOK\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
inthook_HookInterrupt((unsigned char)(pinp->interruptnumber), (int)pinp->newCS, (ULONG_PTR)pinp->newRIP, (PJUMPBACK)(UINT_PTR)(pinp->addressofjumpback));
DbgPrint("After the hook\n");
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_UNHOOKALLINTERRUPTS:
{
int i;
DbgPrint("IOCTL_CE_UNHOOKALLINTERRUPTS for cpu %d\n",cpunr());
for (i=0; i<256; i++)
inthook_UnhookInterrupt((unsigned char)i);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETGLOBALDEBUGSTATE:
{
struct intput
{
BOOL newstate;
} *pinp;
pinp=Irp->AssociatedIrp.SystemBuffer;
debugger_setGlobalDebugState(pinp->newstate);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_DEBUGPROCESS:
{
struct input
{
DWORD ProcessID;
} *pinp;
DbgPrint("IOCTL_CE_DEBUGPROCESS\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
debugger_startDebugging(pinp->ProcessID);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_STOPDEBUGGING:
{
debugger_stopDebugging();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_STARTPROCESSWATCH:
{
NTSTATUS r = STATUS_SUCCESS;
DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");
ProcessWatcherOpensHandles = *(char *)Irp->AssociatedIrp.SystemBuffer != 0;
if (CreateProcessNotifyRoutineEnabled && WatcherProcess)
{
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
//still here
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
ProcessEventCount=0;
ExReleaseResourceLite(&ProcesslistR);
//DbgPrint("IOCTL_CE_STARTPROCESSWATCH\n");
CleanProcessList();
if ((r == STATUS_SUCCESS) && (CreateProcessNotifyRoutineEnabled == FALSE))
{
DbgPrint("calling PsSetCreateProcessNotifyRoutine\n");
#if (NTDDI_VERSION >= NTDDI_VISTASP1)
r=PsSetCreateProcessNotifyRoutineEx(CreateProcessNotifyRoutineEx, FALSE);
CreateProcessNotifyRoutineEnabled = r== STATUS_SUCCESS;
#else
CreateProcessNotifyRoutineEnabled = (PsSetCreateProcessNotifyRoutine(CreateProcessNotifyRoutine,FALSE)==STATUS_SUCCESS);
#endif
if (CreateProcessNotifyRoutineEnabled)
CreateThreadNotifyRoutineEnabled = (PsSetCreateThreadNotifyRoutine(CreateThreadNotifyRoutine) == STATUS_SUCCESS);
}
ntStatus=(CreateProcessNotifyRoutineEnabled) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
if (ntStatus==STATUS_SUCCESS)
DbgPrint("CreateProcessNotifyRoutineEnabled worked\n");
else
DbgPrint("CreateProcessNotifyRoutineEnabled failed (r=%x)\n",r);
break;
}
case IOCTL_CE_GETPROCESSEVENTS:
{
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ProcessEventCount;
RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ProcessEventdata[0],ProcessEventCount*sizeof(ProcessEventdta));
ProcessEventCount=0; //there's room for new events
ExReleaseResourceLite(&ProcesslistR);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETTHREADEVENTS:
{
ExAcquireResourceExclusiveLite(&ProcesslistR, TRUE);
*(PUCHAR)Irp->AssociatedIrp.SystemBuffer=ThreadEventCount;
RtlCopyMemory((PVOID)((UINT_PTR)Irp->AssociatedIrp.SystemBuffer+1),&ThreadEventData[0],ThreadEventCount*sizeof(ThreadEventDta));
ThreadEventCount=0; //there's room for new events
ExReleaseResourceLite(&ProcesslistR);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_CREATEAPC:
{
struct input
{
UINT64 threadid;
UINT64 addresstoexecute;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
CreateRemoteAPC((ULONG)inp->threadid,(PVOID)(UINT_PTR)inp->addresstoexecute);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SUSPENDTHREAD:
{
struct input
{
ULONG threadid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("CE_SUSPENDTHREAD\n");
DBKSuspendThread(inp->threadid);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_RESUMETHREAD:
{
struct input
{
ULONG threadid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("CE_RESUMETHREAD\n");
DBKResumeThread(inp->threadid);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SUSPENDPROCESS:
{
struct input
{
ULONG processid;
} *inp;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_SUSPENDPROCESS\n");
if (PsSuspendProcess)
{
PEPROCESS selectedprocess;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = PsSuspendProcess(selectedprocess);
ObDereferenceObject(selectedprocess);
}
else
ntStatus = STATUS_NOT_FOUND;
}
else
ntStatus = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_CE_RESUMEPROCESS:
{
struct input
{
ULONG processid;
} *inp;
inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_RESUMEPROCESS\n");
if (PsResumeProcess)
{
PEPROCESS selectedprocess;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->processid), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = PsResumeProcess(selectedprocess);
ObDereferenceObject(selectedprocess);
}
else
ntStatus = STATUS_NOT_FOUND;
}
else
ntStatus = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_CE_ALLOCATEMEM:
{
struct input
{
UINT64 ProcessID;
UINT64 BaseAddress;
UINT64 Size;
UINT64 AllocationType;
UINT64 Protect;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp=Irp->AssociatedIrp.SystemBuffer;
BaseAddress=(PVOID)(UINT_PTR)inp->BaseAddress;
RegionSize=(SIZE_T)(inp->Size);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID),&selectedprocess)==STATUS_SUCCESS)
{
__try
{
KAPC_STATE apc_state;
RtlZeroMemory(&apc_state,sizeof(apc_state));
KeAttachProcess((PVOID)selectedprocess); //local process is much more fun!!!!
DbgPrint("Switched Process\n");
__try
{
DbgPrint("Calling ZwAllocateVirtualMemory\n");
DbgPrint("Before call: BaseAddress=%p\n", BaseAddress);
DbgPrint("Before call: RegionSize=%x\n", RegionSize);
ntStatus=ZwAllocateVirtualMemory((HANDLE)-1, &BaseAddress, 0, &RegionSize, (ULONG)inp->AllocationType, (ULONG)inp->Protect);
if ((ntStatus==STATUS_SUCCESS) && (HiddenDriver))
{
//initialize the memory with crap so it becomes paged
int i;
char *x;
x=BaseAddress;
for (i=0; i < (int)RegionSize;i++)
x[i]=(unsigned char)i;
}
DbgPrint("ntStatus=%x\n", ntStatus);
DbgPrint("BaseAddress=%p\n",BaseAddress);
DbgPrint("RegionSize=%x\n",RegionSize);
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)BaseAddress;
}
__finally
{
KeDetachProcess();
}
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
break;
}
case IOCTL_CE_ALLOCATEMEM_NONPAGED:
{
struct input
{
ULONG Size;
} *inp;
PVOID address;
int size;
inp=Irp->AssociatedIrp.SystemBuffer;
size=inp->Size;
address=ExAllocatePool(NonPagedPool,size);
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=0;
*(PUINT_PTR)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)address;
if (address==0)
ntStatus=STATUS_UNSUCCESSFUL;
else
{
DbgPrint("Alloc success. Cleaning memory... (size=%d)\n",size);
DbgPrint("address=%p\n", address);
RtlZeroMemory(address, size);
ntStatus=STATUS_SUCCESS;
}
break;
}
case IOCTL_CE_FREE_NONPAGED:
{
struct input
{
UINT64 Address;
} *inp;
inp = Irp->AssociatedIrp.SystemBuffer;
ExFreePool((PVOID)(UINT_PTR)inp->Address);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_MAP_MEMORY:
{
struct input
{
UINT64 FromPID;
UINT64 ToPID;
UINT64 address;
DWORD size;
} *inp;
struct output
{
UINT64 FromMDL;
UINT64 Address;
} *outp;
KAPC_STATE apc_state;
PEPROCESS selectedprocess;
PMDL FromMDL=NULL;
inp = Irp->AssociatedIrp.SystemBuffer;
outp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_MAP_MEMORY\n");
DbgPrint("address %x size %d\n", inp->address, inp->size);
ntStatus = STATUS_UNSUCCESSFUL;
if (inp->FromPID)
{
//switch
DbgPrint("From PID %d\n", inp->FromPID);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->FromPID), &selectedprocess) == STATUS_SUCCESS)
{
__try
{
RtlZeroMemory(&apc_state, sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess, &apc_state);
__try
{
FromMDL=IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
if (FromMDL)
MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except (1)
{
DbgPrint("Exception\n");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
}
else
{
DbgPrint("From kernel or self\n", inp->FromPID);
__try
{
FromMDL = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, inp->size, FALSE, FALSE, NULL);
if (FromMDL)
{
DbgPrint("IoAllocateMdl success\n");
MmProbeAndLockPages(FromMDL, KernelMode, IoReadAccess);
}
}
__except (1)
{
DbgPrint("Exception\n");
if (FromMDL)
{
IoFreeMdl(FromMDL);
FromMDL = NULL;
}
}
}
if (FromMDL)
{
DbgPrint("FromMDL is valid\n");
if (inp->ToPID)
{
//switch
DbgPrint("To PID %d\n", inp->ToPID);
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ToPID), &selectedprocess) == STATUS_SUCCESS)
{
__try
{
RtlZeroMemory(&apc_state, sizeof(apc_state));
KeStackAttachProcess((PVOID)selectedprocess, &apc_state);
__try
{
outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
outp->FromMDL = (UINT64)FromMDL;
ntStatus = STATUS_SUCCESS;
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
}
__except (1)
{
DbgPrint("Exception part 2\n");
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
ObDereferenceObject(selectedprocess);
}
}
else
{
DbgPrint("To kernel or self\n", inp->FromPID);
__try
{
outp->Address = (UINT64)MmMapLockedPagesSpecifyCache(FromMDL, UserMode, MmWriteCombined, NULL, FALSE, NormalPagePriority);
outp->FromMDL = (UINT64)FromMDL;
ntStatus = STATUS_SUCCESS;
}
__except (1)
{
DbgPrint("Exception part 2\n");
}
}
}
else
DbgPrint("FromMDL==NULL\n");
break;
}
case IOCTL_CE_UNMAP_MEMORY:
{
struct output
{
UINT64 FromMDL;
UINT64 Address;
} *inp;
PMDL mdl;
inp = Irp->AssociatedIrp.SystemBuffer;
mdl = (PMDL)(UINT_PTR)inp->FromMDL;
MmUnmapLockedPages((PMDL)(UINT_PTR)inp->Address, mdl);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
ntStatus = STATUS_SUCCESS; //no BSOD means success ;)
break;
}
case IOCTL_CE_LOCK_MEMORY:
{
struct
{
UINT64 ProcessID;
UINT64 address;
UINT64 size;
} *inp;
struct
{
UINT64 mdl;
} *outp;
KAPC_STATE apc_state;
PEPROCESS selectedprocess;
DbgPrint("IOCTL_CE_LOCK_MEMORY");
inp = Irp->AssociatedIrp.SystemBuffer;
outp = Irp->AssociatedIrp.SystemBuffer;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
PMDL mdl = NULL;
KeStackAttachProcess(selectedprocess, &apc_state);
__try
{
mdl = IoAllocateMdl((PVOID)(UINT_PTR)inp->address, (ULONG)inp->size, FALSE, FALSE, NULL);
if (mdl)
{
__try
{
MmProbeAndLockPages(mdl, UserMode, IoReadAccess);
DbgPrint("MmProbeAndLockPages succeeded");
}
__except (1)
{
DbgPrint("MmProbeAndLockPages failed");
IoFreeMdl(mdl);
ntStatus = STATUS_UNSUCCESSFUL;
break;
}
}
}
__finally
{
KeUnstackDetachProcess(&apc_state);
}
outp->mdl = (UINT_PTR)mdl;
DbgPrint("Locked the page\n");
ntStatus = STATUS_SUCCESS;
}
break;
}
case IOCTL_CE_UNLOCK_MEMORY:
{
struct
{
UINT64 mdl;
} *inp;
DbgPrint("IOCTL_CE_UNLOCK_MEMORY");
inp = Irp->AssociatedIrp.SystemBuffer;
MmUnlockPages((PMDL)(UINT_PTR)inp->mdl);
IoFreeMdl((PMDL)(UINT_PTR)inp->mdl);
break;
}
case IOCTL_CE_GETPROCADDRESS:
{
struct input
{
UINT64 s;
} *inp;
UNICODE_STRING y;
UINT64 result;
PVOID x;
inp=Irp->AssociatedIrp.SystemBuffer;
RtlInitUnicodeString(&y, (PCWSTR)(UINT_PTR)(inp->s));
x=MmGetSystemRoutineAddress(&y);
result=(UINT64)x;
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&result,8);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETPROCESSNAMEADDRESS:
{
struct input
{
UINT64 PEPROCESS;
} *inp;
struct output
{
UINT64 Address;
} *outp;
UNICODE_STRING temp;
inp=Irp->AssociatedIrp.SystemBuffer;
outp=Irp->AssociatedIrp.SystemBuffer;
RtlInitUnicodeString(&temp, L"PsGetProcessImageFileName");
PsGetProcessImageFileName=(GET_PROCESS_IMAGE_NAME)MmGetSystemRoutineAddress(&temp);
if (PsGetProcessImageFileName!=NULL)
{
outp->Address=(UINT_PTR)PsGetProcessImageFileName((PEPROCESS)((UINT_PTR)(inp->PEPROCESS)));
ntStatus=STATUS_SUCCESS;
}
else
{
DbgPrint("PsGetProcessImageFileName==NULL");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
/*x
case IOCTL_CE_MAKEKERNELCOPY:
{
struct input
{
ULONG Base;
ULONG KernelSize;
} *inp;
DbgPrint("IOCTL_CE_MAKEKERNELCOPY");
inp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=makeKernelCopy(inp->Base, inp->KernelSize);
break;
}
*/
case IOCTL_CE_CONTINUEDEBUGEVENT:
{
struct input
{
BOOL handled;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_CONTINUEDEBUGEVENT\n");
ntStatus=debugger_continueDebugEvent(inp->handled);
break;
}
case IOCTL_CE_WAITFORDEBUGEVENT:
{
struct input
{
ULONG timeout;
} *inp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=debugger_waitForDebugEvent(inp->timeout);
break;
}
case IOCTL_CE_GETDEBUGGERSTATE:
{
DbgPrint("IOCTL_CE_GETDEBUGGERSTATE\n");
__try
{
ntStatus=debugger_getDebuggerState((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer));
}
__except(1)
{
DbgPrint("Exception happened\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
DbgPrint("ntStatus=%x rax=%x\n",ntStatus, ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
break;
}
case IOCTL_CE_SETDEBUGGERSTATE:
{
DbgPrint("IOCTL_CE_SETDEBUGGERSTATE: state->rax=%x\n", ((PDebugStackState)(Irp->AssociatedIrp.SystemBuffer))->rax);
__try
{
ntStatus=debugger_setDebuggerState((PDebugStackState)Irp->AssociatedIrp.SystemBuffer);
}
__except(1)
{
DbgPrint("Exception happened\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_SETKERNELSTEPABILITY:
{
struct input
{
int state;
} *inp=Irp->AssociatedIrp.SystemBuffer;
KernelCodeStepping=inp->state;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_WRITESIGNOREWP:
{
KernelWritesIgnoreWP = *(BYTE*)Irp->AssociatedIrp.SystemBuffer;
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_GD_SETBREAKPOINT:
{
struct input
{
BOOL active;
int debugregspot;
UINT64 address;
DWORD breakType;
DWORD breakLength;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("sizeof(struct input)=%d\n",sizeof(struct input));
//DbgPrint("address=%llx breakType=%d breakLength=%d\n",inp->address, inp->breakType,inp->breakLength);
if (inp->active)
{
DbgPrint("activating breapoint %d\n", inp->debugregspot);
ntStatus=debugger_setGDBreakpoint(inp->debugregspot, (UINT_PTR)inp->address, (BreakType)inp->breakType, (BreakLength)inp->breakLength);
}
else
{
DbgPrint("Deactivating breakpoint :%d\n", inp->debugregspot);
ntStatus=debugger_unsetGDBreakpoint(inp->debugregspot);
}
break;
}
case IOCTL_CE_TOUCHDEBUGREGISTER: //used after setting a global debug breakpoint
{
debugger_touchDebugRegister(0);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_SETSTORELBR:
{
BOOL newstate=*(PBOOL)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("Calling debugger_setStoreLBR(%d)\n", newstate);
debugger_setStoreLBR(newstate);
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_EXECUTE_CODE:
{
typedef NTSTATUS (*PARAMETERLESSFUNCTION)(UINT64 parameters);
PARAMETERLESSFUNCTION functiontocall;
struct input
{
UINT64 functionaddress; //function address to call
UINT64 parameters;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_EXECUTE_CODE\n");
functiontocall=(PARAMETERLESSFUNCTION)(UINT_PTR)(inp->functionaddress);
__try
{
ntStatus=functiontocall(inp->parameters);
DbgPrint("Still alive\n");
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
DbgPrint("Exception occured\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_GETVERSION:
{
DbgPrint("IOCTL_CE_GETVERSION. Version=%d\n",dbkversion);
*(PULONG)Irp->AssociatedIrp.SystemBuffer=dbkversion;
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_READMSR:
{
DWORD msr=*(PDWORD)Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_READMSR: msr=%x\n", msr);
__try
{
*(PUINT64)Irp->AssociatedIrp.SystemBuffer=__readmsr(msr);
//DbgPrint("Output: %llx\n",*(PUINT64)Irp->AssociatedIrp.SystemBuffer);
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_WRITEMSR:
{
struct input
{
UINT64 msr;
UINT64 value;
} *inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_WRITEMSR:\n");
DbgPrint("msr=%llx\n", inp->msr);
DbgPrint("value=%llx\n", inp->value);
__try
{
__writemsr(inp->msr, inp->value );
ntStatus=STATUS_SUCCESS;
}
__except(1)
{
DbgPrint("Error while writing value\n");
ntStatus=STATUS_UNSUCCESSFUL;
}
break;
}
case IOCTL_CE_ULTIMAP2:
{
struct input
{
UINT32 PID;
UINT32 Size;
UINT32 RangeCount;
UINT32 NoPMI;
UINT32 UserMode;
UINT32 KernelMode;
URANGE Ranges[8];
WCHAR OutputPath[200];
} *inp = Irp->AssociatedIrp.SystemBuffer;
int i;
DbgPrint("IOCTL_CE_ULTIMAP2");
for (i = 0; i < (int)(inp->RangeCount); i++)
DbgPrint("%d=%p -> %p", i, (PVOID)(UINT_PTR)inp->Ranges[i].StartAddress, (PVOID)(UINT_PTR)inp->Ranges[i].EndAddress);
SetupUltimap2(inp->PID, inp->Size, inp->OutputPath, inp->RangeCount, inp->Ranges, inp->NoPMI, inp->UserMode, inp->KernelMode);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_WAITFORDATA:
{
ULONG timeout = *(ULONG *)Irp->AssociatedIrp.SystemBuffer;
PULTIMAP2DATAEVENT output = Irp->AssociatedIrp.SystemBuffer;
output->Address = 0;
ntStatus = ultimap2_waitForData(timeout, output);
break;
}
case IOCTL_CE_ULTIMAP2_LOCKFILE:
{
int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
ultimap2_LockFile(cpunr);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_RELEASEFILE:
{
int cpunr = *(int *)Irp->AssociatedIrp.SystemBuffer;
ultimap2_ReleaseFile(cpunr);
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_GETTRACESIZE:
{
*(UINT64*)Irp->AssociatedIrp.SystemBuffer = ultimap2_GetTraceFileSize();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_RESETTRACESIZE:
{
ultimap2_ResetTraceFileSize();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP2_CONTINUE:
{
int cpunr=*(int*)Irp->AssociatedIrp.SystemBuffer;
ntStatus = ultimap2_continue(cpunr);
break;
}
case IOCTL_CE_ULTIMAP2_FLUSH:
{
ntStatus = ultimap2_flushBuffers();
break;
}
case IOCTL_CE_ULTIMAP2_PAUSE:
{
ntStatus = ultimap2_pause();
break;
}
case IOCTL_CE_ULTIMAP2_RESUME:
{
ntStatus = ultimap2_resume();
break;
}
case IOCTL_CE_DISABLEULTIMAP2:
{
DisableUltimap2();
break;
}
case IOCTL_CE_ULTIMAP:
{
#pragma pack(1)
struct input
{
UINT64 targetCR3;
UINT64 dbgctl;
UINT64 dsareasize;
BOOL savetofile;
int HandlerCount;
WCHAR filename[200];
} *inp=Irp->AssociatedIrp.SystemBuffer;
#pragma pack()
DbgPrint("IOCTL_CE_ULTIMAP:\n");
DbgPrint("ultimap(%I64x, %I64x, %d):\n", (UINT64)inp->targetCR3, (UINT64)inp->dbgctl, inp->dsareasize);
if (inp->savetofile)
DbgPrint("filename=%S\n", &inp->filename[0]);
ntStatus=ultimap(inp->targetCR3, inp->dbgctl, (int)inp->dsareasize, inp->savetofile, &inp->filename[0], inp->HandlerCount);
break;
}
case IOCTL_CE_ULTIMAP_DISABLE:
{
ultimap_disable();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_WAITFORDATA:
{
ULONG timeout=*(ULONG *)Irp->AssociatedIrp.SystemBuffer;
PULTIMAPDATAEVENT output=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ultimap_waitForData(timeout, output);
break;
}
case IOCTL_CE_ULTIMAP_CONTINUE:
{
PULTIMAPDATAEVENT input=Irp->AssociatedIrp.SystemBuffer;
ntStatus=ultimap_continue(input);
break;
}
case IOCTL_CE_ULTIMAP_FLUSH:
{
ultimap_flushBuffers();
ntStatus=STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_PAUSE:
{
ultimap_pause();
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_ULTIMAP_RESUME:
{
ultimap_resume();
ntStatus = STATUS_SUCCESS;
break;
}
/*
case IOCTL_CE_GETCPUIDS:
{
CPULISTFILLSTRUCT x;
forEachCpuPassive(GetCPUIDS_all,&x);
}*/
case IOCTL_CE_STARTACCESMONITOR:
{
//this is used instead of writeProcessMemory for speed reasons (the reading out is still done with readProcessMemory because of easier memory management)
struct input
{
UINT64 ProcessID;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp=Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_STARTACCESMONITOR(%d)\n", inp->ProcessID);
ntStatus = STATUS_UNSUCCESSFUL;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
ntStatus = markAllPagesAsNeverAccessed(selectedprocess);
ObDereferenceObject(selectedprocess);
}
break;
}
case IOCTL_CE_ENUMACCESSEDMEMORY:
{
struct input
{
UINT64 ProcessID;
} *inp;
PEPROCESS selectedprocess;
PVOID BaseAddress;
SIZE_T RegionSize;
inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_ENUMACCESSEDMEMORY(%d)\n", inp->ProcessID);
ntStatus = STATUS_UNSUCCESSFUL;
if (PsLookupProcessByProcessId((PVOID)(UINT_PTR)(inp->ProcessID), &selectedprocess) == STATUS_SUCCESS)
{
*(int *)Irp->AssociatedIrp.SystemBuffer = enumAllAccessedPages(selectedprocess);
ObDereferenceObject(selectedprocess);
}
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_GETACCESSEDMEMORYLIST:
{
int ListSizeInBytes = *(int *)Irp->AssociatedIrp.SystemBuffer;
PPRANGE List = (PPRANGE)Irp->AssociatedIrp.SystemBuffer;
DbgPrint("IOCTL_CE_GETACCESSEDMEMORYLIST\n");
getAccessedPageList(List, ListSizeInBytes);
DbgPrint("return from IOCTL_CE_GETACCESSEDMEMORYLIST\n");
ntStatus = STATUS_SUCCESS;
break;
}
case IOCTL_CE_INITIALIZE:
{
//find the KeServiceDescriptorTableShadow
struct input
{
UINT64 AddressOfWin32K;
UINT64 SizeOfWin32K;
UINT64 NtUserBuildHwndList_callnumber;
UINT64 NtUserQueryWindow_callnumber;
UINT64 NtUserFindWindowEx_callnumber;
UINT64 NtUserGetForegroundWindow_callnumber;
UINT64 ActiveLinkOffset;
UINT64 ProcessNameOffset;
UINT64 DebugportOffset;
UINT64 ProcessEvent;
UINT64 ThreadEvent;
} *pinp;
DbgPrint("IOCTL_CE_INITIALIZE\n");
pinp=Irp->AssociatedIrp.SystemBuffer;
ntStatus=STATUS_SUCCESS;
//referencing event handles to objects
ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ProcessEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ProcessEvent, NULL);
ObReferenceObjectByHandle((HANDLE)(UINT_PTR)pinp->ThreadEvent, EVENT_ALL_ACCESS, NULL,KernelMode, &ThreadEvent, NULL);
*(UINT_PTR*)Irp->AssociatedIrp.SystemBuffer=(UINT_PTR)0;
break;
}
case IOCTL_CE_VMXCONFIG:
{
#pragma pack(1)
struct input
{
ULONG Virtualization_Enabled;
QWORD Password1;
ULONG Password2;
QWORD Password3;
} *pinp;
#pragma pack()
DbgPrint("IOCTL_CE_VMXCONFIG called\n");
ntStatus=STATUS_SUCCESS;
pinp=Irp->AssociatedIrp.SystemBuffer;
if (pinp->Virtualization_Enabled)
{
vmx_password1=pinp->Password1;
vmx_password2=pinp->Password2;
vmx_password3=pinp->Password3;
DbgPrint("new passwords are: %p-%x-%p\n", (void*)vmx_password1, vmx_password2, (void*)vmx_password3);
__try
{
vmx_version=vmx_getversion();
DbgPrint("Still here, so vmx is loaded. vmx_version=%x\n",vmx_version);
vmxusable = 1;
}
__except(1)
{
DbgPrint("Exception happened. This means no vmx installed, or one of the passwords is wrong\n");
ntStatus = STATUS_UNSUCCESSFUL;
vmxusable = 0;
};
}
else
{
DbgPrint("Virtualization_Enabled=0\n");
vmxusable=0;
}
break;
}
case IOCTL_CE_ENABLE_DRM:
{
#if (NTDDI_VERSION >= NTDDI_VISTA)
struct
{
QWORD PreferedAltitude;
QWORD ProtectedProcess;
} *inp = Irp->AssociatedIrp.SystemBuffer;
DbgPrint("inp->PreferedAltitude=%p", inp->PreferedAltitude);
DbgPrint("inp->PreferedAltitude=%p", inp->ProtectedProcess);
if (DRMProcess)
{
//check if this process has been terminated
LARGE_INTEGER timeout;
timeout.QuadPart = -500000;
ntStatus=KeWaitForSingleObject(DRMProcess, UserRequest, UserMode, FALSE, &timeout);
if (ntStatus != STATUS_SUCCESS)
break;
}
DRMProcess = PsGetCurrentProcess();
if (inp->ProtectedProcess)
{
if (DRMProcess != (PEPROCESS)((UINT_PTR)inp->ProtectedProcess))
DRMProcess2 = (PEPROCESS)((UINT_PTR)inp->ProtectedProcess);
}
DbgPrint("DRMProcess=%p", DRMProcess);
DbgPrint("DRMProcess2=%p", DRMProcess2);
if (DRMHandle == NULL)
{
WCHAR wcAltitude[10];
UNICODE_STRING usAltitude;
OB_CALLBACK_REGISTRATION r;
LARGE_INTEGER tc;
OB_OPERATION_REGISTRATION obr[2];
int RandomVal = (int)(inp->PreferedAltitude);
int trycount = 0;
if (RandomVal == 0)
{
tc.QuadPart = 0;
KeQueryTickCount(&tc);
RandomVal = 1000 + (tc.QuadPart % 50000);
}
DbgPrint("Activating CE's super advanced DRM"); //yeah right....
DbgPrint("RandomVal=%d", RandomVal);
RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);
DbgPrint("wcAltitude=%S", wcAltitude);
RtlInitUnicodeString(&usAltitude, wcAltitude);
r.Version = OB_FLT_REGISTRATION_VERSION;
r.Altitude = usAltitude;
r.RegistrationContext = NULL;
obr[0].ObjectType = PsProcessType;
obr[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
obr[0].PreOperation = ProcessPreCallback;
obr[0].PostOperation = ProcessPostCallback;
obr[1].ObjectType = PsThreadType;
obr[1].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
obr[1].PreOperation = ThreadPreCallback;
obr[1].PostOperation = ThreadPostCallback;
r.OperationRegistration = obr;
r.OperationRegistrationCount = 2;
ntStatus = ObRegisterCallbacks(&r, &DRMHandle);
while ((ntStatus == STATUS_FLT_INSTANCE_ALTITUDE_COLLISION) && (trycount<10))
{
RandomVal++;
RtlStringCbPrintfW(wcAltitude, sizeof(wcAltitude) - 2, L"%d", RandomVal);
RtlInitUnicodeString(&usAltitude, wcAltitude);
r.Altitude = usAltitude;
trycount++;
ntStatus = ObRegisterCallbacks(&r, &DRMHandle);
}
DbgPrint("ntStatus=%X", ntStatus);
}
else
ntStatus = STATUS_SUCCESS;
#else
ntStatus = STATUS_NOT_IMPLEMENTED;
#endif
break;
}
case IOCTL_CE_GET_PEB:
{
KAPC_STATE oldstate;
PEPROCESS ep = *(PEPROCESS *)Irp->AssociatedIrp.SystemBuffer;
//DbgPrint("IOCTL_CE_GET_PEB");
KeStackAttachProcess((PKPROCESS)ep, &oldstate);
__try
{
ULONG r;
PROCESS_BASIC_INFORMATION pbi;
//DbgPrint("Calling ZwQueryInformationProcess");
ntStatus = ZwQueryInformationProcess(ZwCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &r);
if (ntStatus==STATUS_SUCCESS)
{
//DbgPrint("pbi.UniqueProcessId=%x\n", (int)pbi.UniqueProcessId);
//DbgPrint("pbi.PebBaseAddress=%p\n", (PVOID)pbi.PebBaseAddress);
*(QWORD *)Irp->AssociatedIrp.SystemBuffer = (QWORD)(pbi.PebBaseAddress);
}
else
DbgPrint("ZwQueryInformationProcess failed");
}
__finally
{
KeUnstackDetachProcess(&oldstate);
}
break;
}
case IOCTL_CE_QUERYINFORMATIONPROCESS:
{
struct
{
QWORD processid;
QWORD ProcessInformationAddress;
QWORD ProcessInformationClass;
QWORD ProcessInformationLength;
} *inp = Irp->AssociatedIrp.SystemBuffer;
struct
{
QWORD result;
QWORD returnLength;
char data;
} *outp = Irp->AssociatedIrp.SystemBuffer;
PEPROCESS selectedprocess;
DbgPrint("IOCTL_CE_QUERYINFORMATIONPROCESS");
if (inp->processid == 0)
{
DbgPrint("Still works\n");
ntStatus = STATUS_SUCCESS;
break;
}
__try
{
if (PsLookupProcessByProcessId((HANDLE)(UINT_PTR)inp->processid, &selectedprocess) == STATUS_SUCCESS)
{
KAPC_STATE oldstate;
KeStackAttachProcess((PKPROCESS)selectedprocess, &oldstate);
__try
{
ULONG returnLength;
if (inp->ProcessInformationAddress == 0)
{
DbgPrint("NULL ProcessInformationAddress");
outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, NULL, (ULONG)inp->ProcessInformationLength, &returnLength);
}
else
outp->result = ZwQueryInformationProcess(NtCurrentProcess(), inp->ProcessInformationClass, &(outp->data), (ULONG)inp->ProcessInformationLength, &returnLength);
DbgPrint("outp->result=%x", outp->result);
outp->returnLength = returnLength;
DbgPrint("outp->returnLength=%x", outp->returnLength);
ntStatus = STATUS_SUCCESS;
}
__finally
{
KeUnstackDetachProcess(&oldstate);
}
ObDereferenceObject(selectedprocess);
}
else
{
DbgPrint("Failed to find pid %x", inp->processid);
ntStatus = STATUS_EXPIRED_HANDLE;
}
}
__except (1)
{
DbgPrint("Exception");
ntStatus = STATUS_EXPIRED_HANDLE;
}
break;
}
case IOCTL_CE_NTPROTECTVIRTUALMEMORY:
{
break;
}
case IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM:
{
PHYSICAL_ADDRESS LowAddress, HighAddress, SkipBytes;
PMDL mdl;
QWORD pagecount = *(QWORD*)Irp->AssociatedIrp.SystemBuffer;
PFN_NUMBER *pfnlist;
DbgPrint("IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM(%d)\n", pagecount);
if (!vmxusable)
{
DbgPrint("This only works when DBVM is present\n");
ntStatus = STATUS_INVALID_DEVICE_STATE;
break;
}
LowAddress.QuadPart = 0;
HighAddress.QuadPart = 0xffffffffffffffffI64;
SkipBytes.QuadPart = 0;
mdl = MmAllocatePagesForMdlEx(LowAddress, HighAddress, SkipBytes, (SIZE_T)pagecount * 4096, MmCached, MM_ALLOCATE_REQUIRE_CONTIGUOUS_CHUNKS | MM_ALLOCATE_FULLY_REQUIRED); //do not free this, EVER
if (mdl)
{
int i;
PDBVMOffloadMemInfo mi;
pagecount = MmGetMdlByteCount(mdl) / 4096;
DbgPrint("Allocated %d pages\n", pagecount);
pfnlist = MmGetMdlPfnArray(mdl);
if (pfnlist)
{
//convert the pfnlist to a list dbvm understands, and go in blocks of 32
mi = ExAllocatePool(PagedPool, sizeof(DBVMOffloadMemInfo));
if (mi)
{
mi->List = ExAllocatePool(PagedPool, sizeof(UINT64) * 32);
if (mi->List)
{
mi->Count = 0;
for (i = 0; i < pagecount; i++)
{
mi->List[mi->Count] = pfnlist[i] << 12;
mi->Count++;
if (mi->Count == 32)
{
int j;
int r = vmx_add_memory(mi->List, mi->Count);
DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);
for (j = 0; j < mi->Count; j++)
{
DbgPrint("%d : %p\n", j, (void*)((UINT_PTR)mi->List[j]));
}
mi->Count = 0;
}
}
if (mi->Count)
{
int r = vmx_add_memory(mi->List, mi->Count);
DbgPrint("vmx_add_memory for %d pages returned %d\n", mi->Count, r);
}
ExFreePool(mi->List);
}
else
DbgPrint("Failure allocating mi->List");
ExFreePool(mi);
}
else
DbgPrint("Failure allocting mi");
}
else
DbgPrint("Failure getting pfn list");
ExFreePool(mdl); //only free the mdl, the rest belongs to dbvm now
ntStatus = STATUS_SUCCESS;
}
else
{
DbgPrint("Failure allocating MDL");
ntStatus = STATUS_MEMORY_NOT_ALLOCATED;
}
break;
}
default:
DbgPrint("Unhandled IO request: %x\n", IoControlCode);
break;
}
Irp->IoStatus.Status = ntStatus;
// Set # of bytes to copy back to user-mode...
if (irpStack) //only NULL when loaded by dbvm
{
if (ntStatus == STATUS_SUCCESS)
Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
else
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return ntStatus;
}
================================================
FILE: src/IOPLDispatcher.h
================================================
#ifndef IOPLDISPACTCHER_H
#define IOPLDISPACTCHER_H
#include "DBKfunc.h"
#define IOCTL_UNKNOWN_BASE FILE_DEVICE_UNKNOWN
#define IOCTL_CE_READMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0801, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0802, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_QUERY_VIRTUAL_MEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0803, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_TEST CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0804, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPEPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0805, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_READPHYSICALMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0806, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEPHYSICALMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0807, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPHYSICALADDRESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0808, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_PROTECTME CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0809, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR3 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETCR3 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETSDT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_INITIALIZE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DONTPROTECTME CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETIDT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x080f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_HOOKINTS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0810, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DEBUGPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0811, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_RETRIEVEDEBUGDATA CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0812, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STARTPROCESSWATCH CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0813, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCESSEVENTS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0814, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETTHREADEVENTS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0815, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETVERSION CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0816, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR4 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0817, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_OPENTHREAD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0818, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_MAKEWRITABLE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0819, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//obsolete: #define IOCTL_CE_DEBUGPROCESS_CHANGEREG CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STOPDEBUGGING CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//obsolete: #define IOCTL_CE_STOP_DEBUGPROCESS_CHANGEREG CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_USEALTERNATEMETHOD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_ISUSINGALTERNATEMETHOD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ALLOCATEMEM CTL_CODE(IOCTL_UNKNOWN_BASE, 0x081f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_CREATEAPC CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0820, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPETHREAD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0821, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SUSPENDTHREAD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0822, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMETHREAD CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0823, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SUSPENDPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0824, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_RESUMEPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0825, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ALLOCATEMEM_NONPAGED CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0826, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCADDRESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0827, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//#define IOCTL_CE_SETSDTADDRESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0828, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETSDTADDRESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0829, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETGDT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETCR4 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETTR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_VMXCONFIG CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETCR0 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_USERDEFINEDINTERRUPTHOOK CTL_CODE(IOCTL_UNKNOWN_BASE, 0x082f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETGLOBALDEBUGSTATE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0830, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_CONTINUEDEBUGEVENT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0831, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WAITFORDEBUGEVENT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0832, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETDEBUGGERSTATE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0833, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETDEBUGGERSTATE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0834, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GD_SETBREAKPOINT CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0835, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_TOUCHDEBUGREGISTER CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0836, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_LAUNCHDBVM CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNHOOKALLINTERRUPTS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_EXECUTE_CODE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETPROCESSNAMEADDRESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETKERNELSTEPABILITY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_READMSR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x083f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITEMSR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0840, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_SETSTORELBR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0841, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0842, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_DISABLE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0843, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_WAITFORDATA CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0844, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_CONTINUE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0845, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_FLUSH CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0846, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETMEMORYRANGES CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0847, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_STARTACCESMONITOR CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0848, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ENUMACCESSEDMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0849, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GETACCESSEDMEMORYLIST CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_WRITESIGNOREWP CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_FREE_NONPAGED CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_MAP_MEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNMAP_MEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x084f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_DISABLEULTIMAP2 CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0850, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_WAITFORDATA CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0851, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_CONTINUE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0852, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_FLUSH CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0853, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_PAUSE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RESUME CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_LOCKFILE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0856, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RELEASEFILE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0857, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_PAUSE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0858, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP_RESUME CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0859, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_GETTRACESIZE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ULTIMAP2_RESETTRACESIZE CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085b, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ENABLE_DRM CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085c, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_GET_PEB CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085d, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_QUERYINFORMATIONPROCESS CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085e, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_NTPROTECTVIRTUALMEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x085f, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_LOCK_MEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0860, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_UNLOCK_MEMORY CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0861, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_CE_ALLOCATE_MEMORY_FOR_DBVM CTL_CODE(IOCTL_UNKNOWN_BASE, 0x0862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
extern PVOID DRMHandle;
#define SYSTEMSERVICE(_function) KeServiceDescriptorTable->ServiceTable[ *(PULONG)((PUCHAR)_function+1)]
#define SYSTEMSERVICELINK(_function) KeServiceDescriptorTable->ServiceTable[*((PUCHAR)(*(PULONG)*((PULONG)((PUCHAR)_function+2)))+1)]
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCode, PVOID lpInBuffer, DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, PDWORD lpBytesReturned);
#endif
================================================
FILE: src/amd64/dbkfunca.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument
;I should probably start converting to inrinsics
_TEXT SEGMENT 'CODE'
PUBLIC getCS
getCS:
mov ax,cs
ret
PUBLIC getSS
getSS:
mov ax,ss
ret
PUBLIC getDS
getDS:
mov ax,ds
ret
PUBLIC getES
getES:
mov ax,es
ret
PUBLIC getFS
getFS:
mov ax,fs
ret
PUBLIC getGS
getGS:
mov ax,gs
ret
PUBLIC GetTR
GetTR:
STR AX
ret
PUBLIC GetLDT
GetLDT:
SLDT ax
ret
PUBLIC GetGDT
GetGDT:
SGDT [rcx]
ret
PUBLIC _fxsave
_fxsave:
fxsave [rcx]
ret
PUBLIC getRSP
getRSP:
mov rax,rsp
add rax,8 ;undo the call push
ret
PUBLIC getRBP
getRBP:
push rbp
pop rax
ret
PUBLIC getRAX
getRAX:
ret
PUBLIC getRBX
getRBX:
mov rax,rbx
ret
PUBLIC getRCX
getRCX:
mov rax,rcx
ret
PUBLIC getRDX
getRDX:
mov rax,rdx
ret
PUBLIC getRSI
getRSI:
mov rax,rsi
ret
PUBLIC getRDI
getRDI:
mov rax,rdi
ret
PUBLIC getR8
getR8:
mov rax,r8
ret
PUBLIC getR9
getR9:
mov rax,r9
ret
PUBLIC getR10
getR10:
mov rax,r10
ret
PUBLIC getR11
getR11:
mov rax,r11
ret
PUBLIC getR12
getR12:
mov rax,r12
ret
PUBLIC getR13
getR13:
mov rax,r13
ret
PUBLIC getR14
getR14:
mov rax,r14
ret
PUBLIC getR15
getR15:
mov rax,r15
ret
PUBLIC getAccessRights
getAccessRights:
xor rax,rax
lar rax,rcx
jnz getAccessRights_invalid
shr rax,8
and rax,0f0ffh
ret
getAccessRights_invalid:
mov rax,010000h
ret
PUBLIC getSegmentLimit
getSegmentLimit:
xor rax,rax
lsl rax,rcx
ret
_TEXT ENDS
END
================================================
FILE: src/amd64/debuggera.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument
CALLBACK struct
A qword ?
S qword ?
CALLBACK ends
ASMENTRY_STACK struct ;keep this 16 byte aligned
Scratchspace qword ?
Scratchspace2 qword ?
Scratchspace3 qword ?
Scratchspace4 qword ?
Originalmxcsr qword ?
OriginalRAX qword ? ;0
OriginalRBX qword ? ;1
OriginalRCX qword ? ;2
OriginalRDX qword ? ;3
OriginalRSI qword ? ;4
OriginalRDI qword ? ;5
OriginalRBP qword ? ;6
OriginalRSP qword ? ;7 not really 'original'
OriginalR8 qword ? ;8
OriginalR9 qword ? ;9
OriginalR10 qword ? ;10
OriginalR11 qword ? ;11
OriginalR12 qword ? ;12
OriginalR13 qword ? ;13
OriginalR14 qword ? ;14
OriginalR15 qword ? ;15
OriginalES qword ? ;16
OriginalDS qword ? ;17
OriginalSS qword ? ;18
fxsavespace db 512 dup(?) ;fpu state
;errorcode/returnaddress ;19
;4096 bytes
;eip ;20
;cs ;21
;eflags
;esp
;ss
ASMENTRY_STACK ends
_TEXT SEGMENT 'CODE'
EXTERN interrupt1_centry : proc
EXTERN Int1JumpBackLocation : CALLBACK
PUBLIC interrupt1_asmentry
interrupt1_asmentry:
;save stack position
push [Int1JumpBackLocation.A] ;push an errorcode on the stack so the stackindex enum type can stay the same relative to interrupts that do have an errorcode (int 14). Also helps with variable interrupt handlers
sub rsp,4096 ;functions like setThreadContext adjust the stackframe entry directly. I can't have that messing up my own stack
cld
;stack is aligned at this point
sub rsp,SIZEOF ASMENTRY_STACK
mov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp
lea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
mov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax
mov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi
mov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi
mov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp
mov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8
mov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9
mov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10
mov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11
mov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12
mov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13
mov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14
mov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15
fxsave (ASMENTRY_STACK PTR [rsp]).fxsavespace
mov ax,ds
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax
mov ax,es
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax
mov ax,ss
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax
mov ax,2bh
mov ds,ax
mov es,ax
mov ax,18h
mov ss,ax
; rbp= pointer to OriginalRAX
cmp qword ptr [rbp+8*21+512+4096],010h ;check if origin is in kernelmode (check ss)
je skipswap1 ;if so, skip the swapgs
swapgs ;swap gs with the kernel version
skipswap1:
stmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
mov (ASMENTRY_STACK PTR [rsp]).scratchspace2,1f80h
ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace2
mov rcx,rbp
call interrupt1_centry
ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
cmp qword ptr [rbp+8*21+512+4096],10h ;was it a kernelmode interrupt ?
je skipswap2 ;if so, skip the swapgs part
swapgs ;swap back
skipswap2:
cmp al,1
;restore state
fxrstor (ASMENTRY_STACK PTR [rsp]).fxsavespace
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS
mov ds,ax
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES
mov es,ax
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS
mov ss,ax
mov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
mov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX
mov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX
mov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX
mov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI
mov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI
mov r8, (ASMENTRY_STACK PTR [rsp]).OriginalR8
mov r9, (ASMENTRY_STACK PTR [rsp]).OriginalR9
mov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10
mov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11
mov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12
mov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13
mov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14
mov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15
je skip_original_int1
;stack unwind
mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
add rsp,SIZEOF ASMENTRY_STACK
add rsp,4096
;at this point [rsp] holds the original int1 handler
ret ; used to be add rsp,8 ;+8 for the push 0
;todo: do a jmp [Int1JumpBackLocationCPUNR] and have 256 Int1JumpBackLocationCPUNR's and each cpu goes to it's own interrupt1_asmentry[cpunr]
;jmp [Int1JumpBackLocation.A] ;<-works fine
skip_original_int1:
;stack unwind
mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
add rsp,SIZEOF ASMENTRY_STACK
add rsp,4096
add rsp,8 ;+8 for the push
iretq
_TEXT ENDS
END
================================================
FILE: src/amd64/noexceptionsa.asm
================================================
_TEXT SEGMENT 'CODE'
PUBLIC NoException14
NoException14:
;Security cookies sucks, so getjmp/longjmp are not usable
;So, just falling back to an exceptionless Copy command instead
;or disassemble the instruction RIP points at
;rsp=errorcode
;rsp+8=rip
;rsp+10=cs ;20
;rsp+18=eflags
;rsp+20=rsp
;rsp+28=ss
add rsp,8 ;skip the errorcode
push rax ;push rax -state as above again
mov rax,ExceptionlessCopy_Exception
mov [rsp+8],rax
pop rax
iretq ;go to the designated return address
PUBLIC ExceptionlessCopy_Internal
;rcx=destination
;rdx=source
;r8=size in bytes
ExceptionlessCopy_Internal:
push rbp
mov rbp,rsp
;[rbp] = old rbp value
;[rbp+8] = return address
;[rbp+10h] - [rbp+30h] = scratchspace
mov [rbp+10h],rsi
mov [rbp+18h],rdi
mov rsi,rdx
mov rdi,rcx
mov rcx,r8
rep movsb ;todo: split this up into movsq, movsd, movsw, movsd, or some of those other string routines
;on exception just exit
ExceptionlessCopy_Exception:
mov rsi,[rbp+10h]
mov rdi,[rbp+18h]
sub r8,rcx ;decrease the number of bytes left from the total amount of bytes to get the total bytes written
mov rax,r8
pop rbp
ret
_TEXT ENDS
END
================================================
FILE: src/amd64/ultimapa.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument
CALLBACK struct
A qword ?
S qword ?
CALLBACK ends
ASMENTRY_STACK struct ;keep this 16 byte aligned
Scratchspace qword ? ;0
Scratchspace2 qword ? ;8
Scratchspace3 qword ? ;0
Scratchspace4 qword ? ;8
Originalmxcsr qword ?
OriginalRAX qword ?
OriginalRBX qword ?
OriginalRCX qword ?
OriginalRDX qword ?
OriginalRSI qword ?
OriginalRDI qword ?
OriginalRBP qword ?
OriginalRSP qword ? ;not really 'original'
OriginalR8 qword ?
OriginalR9 qword ?
OriginalR10 qword ?
OriginalR11 qword ?
OriginalR12 qword ?
OriginalR13 qword ?
OriginalR14 qword ?
OriginalR15 qword ?
OriginalES qword ?
OriginalDS qword ?
OriginalSS qword ?
ASMENTRY_STACK ends
_TEXT SEGMENT 'CODE'
EXTERN perfmon_interrupt_centry : proc
EXTERN perfmonJumpBackLocation : CALLBACK
PUBLIC perfmon_interrupt
perfmon_interrupt:
;save stack position
cld
push 0 ;push an errorcode on the stack so the stackindex enum type can stay the same relative to interrupts that do have an errorcode (int 14)
;stack is aligned at this point
sub rsp, 4096
sub rsp,SIZEOF ASMENTRY_STACK
mov (ASMENTRY_STACK PTR [rsp]).OriginalRBP,rbp
lea rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRAX ;make rbp point to the start of the structure
mov (ASMENTRY_STACK PTR [rsp]).OriginalRAX,rax
mov (ASMENTRY_STACK PTR [rsp]).OriginalRBX,rbx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRCX,rcx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRDX,rdx
mov (ASMENTRY_STACK PTR [rsp]).OriginalRSI,rsi
mov (ASMENTRY_STACK PTR [rsp]).OriginalRDI,rdi
mov (ASMENTRY_STACK PTR [rsp]).OriginalRSP,rsp
mov (ASMENTRY_STACK PTR [rsp]).OriginalR8,r8
mov (ASMENTRY_STACK PTR [rsp]).OriginalR9,r9
mov (ASMENTRY_STACK PTR [rsp]).OriginalR10,r10
mov (ASMENTRY_STACK PTR [rsp]).OriginalR11,r11
mov (ASMENTRY_STACK PTR [rsp]).OriginalR12,r12
mov (ASMENTRY_STACK PTR [rsp]).OriginalR13,r13
mov (ASMENTRY_STACK PTR [rsp]).OriginalR14,r14
mov (ASMENTRY_STACK PTR [rsp]).OriginalR15,r15
mov ax,ds
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS,ax
mov ax,es
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES,ax
mov ax,ss
mov word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS,ax
mov ax,2bh
mov ds,ax
mov es,ax
mov ax,18h
mov ss,ax
cmp qword ptr [rbp+8*21+4096],010h ;check if origin is in kernelmode (check ss)
je skipswap1 ;if so, skip the swapgs
swapgs ;swap gs with the kernel version (not to self fix when called from inside kernel)
skipswap1:
stmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
mov (ASMENTRY_STACK PTR [rsp]).scratchspace,1f80h
ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).scratchspace
;mov rcx,rbp
call perfmon_interrupt_centry
ldmxcsr dword ptr (ASMENTRY_STACK PTR [rsp]).Originalmxcsr
cmp qword ptr [rbp+8*21+4096],10h ;was it a kernelmode interrupt ?
je skipswap2 ;if so, skip the swapgs part
swapgs ;swap back
skipswap2:
cmp al,1
;restore state
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalDS
mov ds,ax
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalES
mov es,ax
mov ax,word ptr (ASMENTRY_STACK PTR [rsp]).OriginalSS
mov ss,ax
mov rax,(ASMENTRY_STACK PTR [rsp]).OriginalRAX
mov rbx,(ASMENTRY_STACK PTR [rsp]).OriginalRBX
mov rcx,(ASMENTRY_STACK PTR [rsp]).OriginalRCX
mov rdx,(ASMENTRY_STACK PTR [rsp]).OriginalRDX
mov rsi,(ASMENTRY_STACK PTR [rsp]).OriginalRSI
mov rdi,(ASMENTRY_STACK PTR [rsp]).OriginalRDI
mov r8,(ASMENTRY_STACK PTR [rsp]).OriginalR8
mov r9,(ASMENTRY_STACK PTR [rsp]).OriginalR9
mov r10,(ASMENTRY_STACK PTR [rsp]).OriginalR10
mov r11,(ASMENTRY_STACK PTR [rsp]).OriginalR11
mov r12,(ASMENTRY_STACK PTR [rsp]).OriginalR12
mov r13,(ASMENTRY_STACK PTR [rsp]).OriginalR13
mov r14,(ASMENTRY_STACK PTR [rsp]).OriginalR14
mov r15,(ASMENTRY_STACK PTR [rsp]).OriginalR15
je skip_original_perfmon
jmp skip_original_perfmon
;stack unwind
mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
add rsp,SIZEOF ASMENTRY_STACK ;+8 for the push 0
add rsp,8
add rsp,4096
jmp [perfmonJumpBackLocation.A] ;<-works fine
skip_original_perfmon:
;stack unwind
mov rbp,(ASMENTRY_STACK PTR [rsp]).OriginalRBP
add rsp,SIZEOF ASMENTRY_STACK ;+8 for the push 0
add rsp,4096
add rsp,8
;jump to when the stack has been completly restored to what it was at interrupt time
;push rax
;push rbx
;unmask the perfmon interrupt
;mov rax,0fffffffffffe0330h
;mov rbx,[rax]
;and rbx,0ffh
;mov [rax],rbx
;End of interrupt
;mov rax,0fffffffffffe00b0h
;xor rbx,rbx
;mov [rax],rbx ;set EOI to 0
;pop rbx
;pop rax
iretq
_TEXT ENDS
END
================================================
FILE: src/amd64/vmxhelpera.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument
;vmcall: rdx = password1 info(rax)->password(@offset 4)=password 2
;vmcall(info)
extern vmx_password1 : QWORD
extern vmx_password3 : QWORD
_TEXT SEGMENT 'CODE'
PUBLIC dovmcall_intel
dovmcall_intel:
mov rax,rcx
mov rdx,vmx_password1
mov rcx,vmx_password3
vmcall
ret
PUBLIC dovmcall_amd
dovmcall_amd:
mov rax,rcx
mov rdx,vmx_password1
mov rcx,vmx_password3
vmmcall
ret
_TEXT ENDS
END
================================================
FILE: src/amd64/vmxoffloada.asm
================================================
;RCX: 1st integer argument
;RDX: 2nd integer argument
;R8: 3rd integer argument
;R9: 4th integer argument
GDTDesc STRUCT
Limit WORD ?
Base QWORD ?
GDTDesc ENDS
S_ORIGINALSTATE STRUCT
_cpucount QWORD ?
_originalEFER QWORD ?
_originalLME QWORD ?
_idtbase QWORD ?
_idtlimit QWORD ?
_gdtbase QWORD ?
_gdtlimit QWORD ?
_cr0 QWORD ?
_cr2 QWORD ?
_cr3 QWORD ?
_cr4 QWORD ?
_dr7 QWORD ?
_rip QWORD ?
_rax QWORD ?
_rbx QWORD ?
_rcx QWORD ?
_rdx QWORD ?
_rsi QWORD ?
_rdi QWORD ?
_rbp QWORD ?
_rsp QWORD ?
_r8 QWORD ?
_r9 QWORD ?
_r10 QWORD ?
_r11 QWORD ?
_r12 QWORD ?
_r13 QWORD ?
_r14 QWORD ?
_r15 QWORD ?
_rflags QWORD ?
_cs QWORD ?
_ss QWORD ?
_ds QWORD ?
_es QWORD ?
_fs QWORD ?
_gs QWORD ?
_tr QWORD ?
_ldt QWORD ?
_cs_AccessRights QWORD ?
_ss_AccessRights QWORD ?
_ds_AccessRights QWORD ?
_es_AccessRights QWORD ?
_fs_AccessRights QWORD ?
_gs_AccessRights QWORD ?
_cs_Limit QWORD ?
_ss_Limit QWORD ?
_ds_Limit QWORD ?
_es_Limit QWORD ?
_fs_Limit QWORD ?
_gs_Limit QWORD ?
_fsbase QWORD ?
_gsbase QWORD ?
S_ORIGINALSTATE ENDS
PS_ORIGNALSTATE TYPEDEF PTR S_ORIGINALSTATE
EXTERN NewGDTDescriptor: GDTDesc
EXTERN NewGDTDescriptorVA: QWORD
EXTERN DBVMPML4PA: QWORD
EXTERN TemporaryPagingSetupPA: QWORD
EXTERN enterVMM2PA: QWORD
EXTERN originalstatePA: QWORD
EXTERN enterVMM2: QWORD
EXTERN originalstate: PS_ORIGNALSTATE
EXTERN vmmPA: QWORD
_TEXT SEGMENT 'CODE'
PUBLIC JTAGBP
JTAGBP:
db 0f1h
ret
PUBLIC enterVMM
enterVMM:
begin:
;switch to identity mapped pagetable
mov cr3,rdx
jmp short weee
weee:
nop
nop
;now jump to the physical address (identity mapped to the same virtual address)
mov rax,secondentry
mov r8,enterVMM
sub rax,r8
add rax,rsi ;add the physical address to the offset location
jmp rax
secondentry:
;contrary to the 32-bit setup, we don't disable paging to make the switch to 64-bit, we're already there
;we can just set the CR3 value
;----------TEST----------
; waitforready:
; mov dx,0ec05h
; in al,dx
; and al,20h
; cmp al,20h
; jne waitforready
;
; mov dx,0ec00h
; mov al,'1'
; out dx,al
;^^^^^^^^TEST^^^^^^^^
;enable PAE and PSE (just to make sure)
mov eax,30h
mov cr4,rax
mov cr3,rcx
nop
nop
jmp short weee2
weee2:
nop
nop
mov rbx,0
mov ds,bx
mov es,bx
mov fs,bx
mov gs,bx
mov ss,bx
mov rax,cr0
or eax,10000h
mov cr0,rax ;enable WP bit
nop
nop
nop
nop
;db 0f1h ;jtag
nop
nop
nop
jmp fword ptr [vmmjump]
;jmp fword ptr [vmmjump] ;one thing that I don't mind about x64, relative addressing, so no need to change it by me
extrastorage:
nop
nop
nop
nop
nop
vmmjump:
dd 00400000h
dw 50h
detectionstring:
db 0ceh
db 0ceh
db 0ceh
db 0ceh
db 0ceh
db 0ceh
db 0ceh
PUBLIC enterVMMPrologue
enterVMMPrologue:
cli ;goodbye interrupts
push rbx
mov rbx,originalstate
mov (S_ORIGINALSTATE PTR [rbx])._rax,rax
pop rbx
mov rax,originalstate
mov (S_ORIGINALSTATE PTR [rax])._rbx,rbx
mov (S_ORIGINALSTATE PTR [rax])._rcx,rcx
mov (S_ORIGINALSTATE PTR [rax])._rdx,rdx
mov (S_ORIGINALSTATE PTR [rax])._rsi,rsi
mov (S_ORIGINALSTATE PTR [rax])._rdi,rdi
mov (S_ORIGINALSTATE PTR [rax])._rbp,rbp
mov (S_ORIGINALSTATE PTR [rax])._rsp,rsp
mov (S_ORIGINALSTATE PTR [rax])._r8,r8
mov (S_ORIGINALSTATE PTR [rax])._r9,r9
mov (S_ORIGINALSTATE PTR [rax])._r10,r10
mov (S_ORIGINALSTATE PTR [rax])._r11,r11
mov (S_ORIGINALSTATE PTR [rax])._r12,r12
mov (S_ORIGINALSTATE PTR [rax])._r13,r13
mov (S_ORIGINALSTATE PTR [rax])._r14,r14
mov (S_ORIGINALSTATE PTR [rax])._r15,r15
mov rbx,enterVMMEpilogue
mov (S_ORIGINALSTATE PTR [rax])._rip,rbx
;jmp enterVMMEpilogue ;test to see if the loader is bugged
;still here, loader didn't crash, start executing the move to the dbvm environment
xchg bx,bx ;bochs break
mov rbx,NewGDTDescriptorVA
lgdt fword ptr [rbx]
mov rcx,DBVMPML4PA
mov rdx,TemporaryPagingSetupPA
mov rsi,enterVMM2PA
jmp [enterVMM2]
PUBLIC enterVMMEpilogue
enterVMMEpilogue:
nop
nop
push rax
push rbx
push rcx
push rdx
cpuid
pop rdx
pop rcx
pop rbx
pop rax
nop
nop
nop
mov r8,originalstate
;mov rbx,(S_ORIGINALSTATE PTR [r8])._tr
;ltr bx
mov rbx,(S_ORIGINALSTATE PTR [r8])._ss
mov ss,bx
mov rbx,(S_ORIGINALSTATE PTR [r8])._ds
mov ds,bx
mov rbx,(S_ORIGINALSTATE PTR [r8])._es
mov es,bx
mov rbx,(S_ORIGINALSTATE PTR [r8])._fs
mov fs,bx
mov rbx,(S_ORIGINALSTATE PTR [r8])._gs
mov gs,bx
mov rcx,0c0000100h
mov rax,(S_ORIGINALSTATE PTR [r8])._fsbase
mov rdx,rax
shr rdx,32
wrmsr
mov rcx,0c0000101h
mov rax,(S_ORIGINALSTATE PTR [r8])._gsbase
mov rdx,rax
shr rdx,32
wrmsr
mov rax,originalstate
mov rbx,(S_ORIGINALSTATE PTR [rax])._rbx
mov rcx,(S_ORIGINALSTATE PTR [rax])._rcx
mov rdx,(S_ORIGINALSTATE PTR [rax])._rdx
mov rsi,(S_ORIGINALSTATE PTR [rax])._rsi
mov rdi,(S_ORIGINALSTATE PTR [rax])._rdi
mov rbp,(S_ORIGINALSTATE PTR [rax])._rbp
mov rsp,(S_ORIGINALSTATE PTR [rax])._rsp
mov r8,(S_ORIGINALSTATE PTR [rax])._r8
mov r9,(S_ORIGINALSTATE PTR [rax])._r9
mov r10,(S_ORIGINALSTATE PTR [rax])._r10
mov r11,(S_ORIGINALSTATE PTR [rax])._r11
mov r12,(S_ORIGINALSTATE PTR [rax])._r12
mov r13,(S_ORIGINALSTATE PTR [rax])._r13
mov r14,(S_ORIGINALSTATE PTR [rax])._r14
mov r15,(S_ORIGINALSTATE PTR [rax])._r15
mov rax,(S_ORIGINALSTATE PTR [rax])._rax
;crashtest
;mov rax,0deadh
;mov [rax],rax
;sti
ret
nop
nop
nop
_TEXT ENDS
END
================================================
FILE: src/debugger.c
================================================
/*
debugger.c:
This unit will handle all debugging related code, from hooking, to handling interrupts
todo: this whole thing can be moved to a few simple lines in dbvm...
*/
#pragma warning( disable: 4100 4103 4189)
#include <ntifs.h>
#include <windef.h>
#include "DBKFunc.h"
#include "interruptHook.h"
#include "debugger.h"
#include "vmxhelper.h"
#ifdef AMD64
extern void interrupt1_asmentry( void ); //declared in debuggera.asm
#else
void interrupt1_asmentry( void );
#endif
volatile struct
{
BOOL isDebugging; //TRUE if a process is currently being debugged
BOOL stoppingTheDebugger;
DWORD debuggedProcessID; //The processID that is currently debugger
struct {
BOOL active;
UINT_PTR address; //Up to 4 addresses to break on
BreakType breakType; //What type of breakpoint for each seperate address
BreakLength breakLength; //How many bytes does this breakpoint look at
} breakpoint[4];
//...
BOOL globalDebug; //If set all threads of every process will raise an interrupt on taskswitch
//while debugging:
UINT_PTR *LastStackPointer;
UINT_PTR *LastRealDebugRegisters;
HANDLE LastThreadID;
BOOL CausedByDBVM;
BOOL handledlastevent;
//BOOL storeLBR;
//int storeLBR_max;
//UINT_PTR *LastLBRStack;
volatile struct {
UINT_PTR DR0;
UINT_PTR DR1;
UINT_PTR DR2;
UINT_PTR DR3;
UINT_PTR DR6;
UINT_PTR DR7;
UINT_PTR reserved;
volatile int inEpilogue; //if set the global debug bit does no faking
} FakedDebugRegisterState[256];
char b[1];
//volatile BYTE DECLSPEC_ALIGN(16) fxstate[512];
BOOL isSteppingTillClear; //when set the user has entered single stepping mode. This is a one thread only thing, so when it's active and another single step happens, discard it
} DebuggerState;
KEVENT debugger_event_WaitForContinue; //event for kernelmode. Waits till it's set by usermode (usermode function: DBK_Continue_Debug_Event sets it)
KEVENT debugger_event_CanBreak; //event for kernelmode. Waits till a break has been handled so a new one can enter
KEVENT debugger_event_WaitForDebugEvent; //event for usermode. Waits till it's set by a debugged event
DebugReg7 debugger_dr7_getValue(void);
void debugger_dr7_setValue(DebugReg7 value);
DebugReg6 debugger_dr6_getValue(void);
JUMPBACK Int1JumpBackLocation;
typedef struct _SavedStack
{
BOOL inuse;
QWORD stacksnapshot[600];
} SavedStack, *PSavedStack;
criticalSection StacksCS;
int StackCount;
PSavedStack *Stacks;
void debugger_dr7_setGD(int state)
{
DebugReg7 _dr7=debugger_dr7_getValue();
_dr7.GD=state; //usually 1
debugger_dr7_setValue(_dr7);
}
void debugger_dr0_setValue(UINT_PTR value)
{
__writedr(0,value);
}
UINT_PTR debugger_dr0_getValue(void)
{
return __readdr(0);
}
void debugger_dr1_setValue(UINT_PTR value)
{
__writedr(1,value);
}
UINT_PTR debugger_dr1_getValue(void)
{
return __readdr(1);
}
void debugger_dr2_setValue(UINT_PTR value)
{
__writedr(2,value);
}
UINT_PTR debugger_dr2_getValue(void)
{
return __readdr(2);
}
void debugger_dr3_setValue(UINT_PTR value)
{
__writedr(3,value);
}
UINT_PTR debugger_dr3_getValue(void)
{
return __readdr(3);
}
void debugger_dr6_setValue(UINT_PTR value)
{
__writedr(6,value);
}
void debugger_dr7_setValue(DebugReg7 value)
{
UINT_PTR temp=*(UINT_PTR *)&value;
__writedr(7,temp);
}
void debugger_dr7_setValueDword(UINT_PTR value)
{
__writedr(7,value);
}
UINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just typecast the DebugReg7 to a dword...
{
return __readdr(7);
}
DebugReg7 debugger_dr7_getValue(void)
{
UINT_PTR temp=debugger_dr7_getValueDword();
return *(DebugReg7 *)&temp;
}
UINT_PTR debugger_dr6_getValueDword(void)
{
return __readdr(6);
}
DebugReg6 debugger_dr6_getValue(void)
{
UINT_PTR temp=debugger_dr6_getValueDword();
return *(DebugReg6 *)&temp;
}
void debugger_touchDebugRegister(UINT_PTR param)
{
//DbgPrint("Touching debug register. inepilogue=\n", DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue);
debugger_dr0_setValue(debugger_dr0_getValue());
}
void debugger_initialize(void)
{
//DbgPrint("Initializing debugger events\n");
KeInitializeEvent(&debugger_event_WaitForContinue, SynchronizationEvent, FALSE);
KeInitializeEvent(&debugger_event_CanBreak, SynchronizationEvent, TRUE); //true so the first can enter
KeInitializeEvent(&debugger_event_WaitForDebugEvent, SynchronizationEvent, FALSE);
//DbgPrint("DebuggerState.fxstate=%p\n",DebuggerState.fxstate);
StackCount = getCpuCount() * 4;
Stacks = (PSavedStack*)ExAllocatePool(NonPagedPool, StackCount*sizeof(PSavedStack));
int i;
for (i = 0; i < StackCount; i++)
{
Stacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
RtlZeroMemory(Stacks[i], sizeof(SavedStack));
}
}
void debugger_shutdown(void)
{
if (Stacks)
{
int i;
for (i = 0; i < StackCount; i++)
{
if (Stacks[i])
{
ExFreePool(Stacks[i]);
Stacks[i] = NULL;
}
}
ExFreePool(Stacks);
Stacks = NULL;
}
}
void debugger_growstack()
//called in passive mode
{
if (Stacks)
{
KIRQL oldIRQL=KeRaiseIrqlToDpcLevel();
csEnter(&StacksCS);
enableInterrupts(); //csEnter disables it, but we need it
int newStackCount = StackCount * 2;
int i;
PSavedStack *newStacks;
newStacks = (PSavedStack*)ExAllocatePool(NonPagedPool, newStackCount * sizeof(PSavedStack));
if (newStacks)
{
for (i = 0; i < StackCount; i++)
newStacks[i] = Stacks[i];
for (i = StackCount; i < newStackCount; i++)
{
newStacks[i] = (PSavedStack)ExAllocatePool(NonPagedPool, sizeof(SavedStack));
if (newStacks[i])
RtlZeroMemory(newStacks[i], sizeof(SavedStack));
else
{
ExFreePool(newStacks);
csLeave(&StacksCS);
KeLowerIrql(oldIRQL);
return;
}
}
ExFreePool(Stacks);
Stacks = newStacks;
}
csLeave(&StacksCS);
KeLowerIrql(oldIRQL);
}
}
void debugger_setInitialFakeState(void)
{
//DbgPrint("setInitialFakeState for cpu %d\n",cpunr());
DebuggerState.FakedDebugRegisterState[cpunr()].DR0=debugger_dr0_getValue();
DebuggerState.FakedDebugRegisterState[cpunr()].DR1=debugger_dr1_getValue();
DebuggerState.FakedDebugRegisterState[cpunr()].DR2=debugger_dr2_getValue();
DebuggerState.FakedDebugRegisterState[cpunr()].DR3=debugger_dr3_getValue();
DebuggerState.FakedDebugRegisterState[cpunr()].DR6=debugger_dr6_getValueDword();
DebuggerState.FakedDebugRegisterState[cpunr()].DR7=debugger_dr7_getValueDword();
}
VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
debugger_initHookForCurrentCPU();
}
int debugger_removeHookForCurrentCPU(UINT_PTR params)
{
//DbgPrint("Unhooking int1 for this cpu\n");
return inthook_UnhookInterrupt(1);
}
int debugger_initHookForCurrentCPU(void)
/*
Must be called for each cpu
*/
{
int result=TRUE;
//DbgPrint("Hooking int1 for cpu %d\n", cpunr());
result=inthook_HookInterrupt(1,getCS() & 0xfff8, (ULONG_PTR)interrupt1_asmentry, &Int1JumpBackLocation);
#ifdef AMD64
if (result)
{
;//DbgPrint("hooked int1. Int1JumpBackLocation=%x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
}
else
{
//DbgPrint("Failed hooking interrupt 1\n");
return result;
}
#endif
if (DebuggerState.globalDebug)
{
//set the fake state
//debugger_setInitialFakeState();
//DbgPrint("Setting GD bit for cpu %d\n",cpunr());
debugger_dr7_setGD(1); //enable the GD flag
}
/*if (DebuggerState.storeLBR)
{
//DbgPrint("Enabling LBR logging. IA32_DEBUGCTL was %x\n", __readmsr(0x1d9));
__writemsr(0x1d9, __readmsr(0x1d9) | 1);
//DbgPrint("Enabling LBR logging. IA32_DEBUGCTL is %x\n", __readmsr(0x1d9));
}*/
return result;
}
void debugger_setStoreLBR(BOOL state)
{
return; //disabled for now
/*
//if (state)
// DbgPrint("Setting storeLBR to true\n");
//else
// DbgPrint("Setting storeLBR to false\n");
DebuggerState.storeLBR=state; //it's not THAT crucial to disable/enable it
DebuggerState.storeLBR_max=0;
switch (cpu_model)
{
case 0x2a:
case 0x1a:
case 0x1e:
case 0x1f:
case 0x2e:
case 0x25:
case 0x2c:
DebuggerState.storeLBR_max=16;
break;
case 0x17:
case 0x1d:
case 0x0f:
DebuggerState.storeLBR_max=4;
break;
case 0x1c:
DebuggerState.storeLBR_max=8;
break;
}
//DbgPrint("Because your cpu_model=%d I think that your storeLBR_max=%d\n", cpu_model, DebuggerState.storeLBR_max);
*/
}
int debugger_setGlobalDebugState(BOOL state)
//call this BEFORE debugging, if already debugging, the user must call this for each cpu
{
//DbgPrint("debugger_setGlobalDebugState(%d)\n",state);
if (state)
DebuggerState.globalDebug=state; //on enable set this first
if (inthook_isHooked(1))
{
int oldEpilogueState=DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue;
//DbgPrint("Int 1 is hooked,%ssetting GD\n",(state ? "":"un"));
//DbgPrint("oldEpilogueState=%d\n",oldEpilogueState);
//debugger_setInitialFakeState();
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=TRUE;
DebuggerState.globalDebug=state;
debugger_dr7_setGD(state);
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=oldEpilogueState;
DebuggerState.FakedDebugRegisterState[cpunr()].DR7=0x400;
debugger_dr7_setValueDword(0x400);
}
return TRUE;
}
int debugger_startDebugging(DWORD debuggedProcessID)
/*
Call this AFTER the interrupts are hooked
*/
{
//DbgPrint("debugger_startDebugging. Processid=%x\n",debuggedProcessID);
Int1JumpBackLocation.eip=inthook_getOriginalEIP(1);
Int1JumpBackLocation.cs=inthook_getOriginalCS(1);
#ifdef AMD64
//DbgPrint("Int1 jump back = %x:%llx\n", Int1JumpBackLocation.cs, Int1JumpBackLocation.eip);
#endif
DebuggerState.isDebugging=TRUE;
DebuggerState.debuggedProcessID=debuggedProcessID;
return TRUE;
}
int debugger_stopDebugging(void)
{
int i;
//DbgPrint("Stopping the debugger if it is running\n");
DebuggerState.stoppingTheDebugger=TRUE;
if (DebuggerState.globalDebug)
{
//touch the global debug for each debug processor
//DbgPrint("Touching the debug registers\n");
forEachCpuPassive(debugger_touchDebugRegister, 0);
}
DebuggerState.globalDebug=FALSE; //stop when possible, saves speed
DebuggerState.isDebugging=FALSE;
for (i=0; i<4; i++)
DebuggerState.breakpoint[i].active=FALSE;
//unhook all processors
forEachCpuPassive(debugger_removeHookForCurrentCPU, 0);
return TRUE;
}
int debugger_unsetGDBreakpoint(int breakpointnr)
{
int result=DebuggerState.breakpoint[breakpointnr].active;
DebuggerState.breakpoint[breakpointnr].active=FALSE;
return result; //returns true if it was active
}
int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl)
/*
Will register a specific breakpoint. If global debug is used it'll set this debug register accordingly
*/
{
//DbgPrint("debugger_setGDBreakpoint(%d, %x, %d, %d)\n", breakpointnr, Address, bt, bl);
DebuggerState.breakpoint[breakpointnr].active=TRUE;
DebuggerState.breakpoint[breakpointnr].address=Address;
DebuggerState.breakpoint[breakpointnr].breakType=bt;
DebuggerState.breakpoint[breakpointnr].breakLength=bl;
return TRUE;
}
NTSTATUS debugger_waitForDebugEvent(ULONG timeout)
{
NTSTATUS r;
LARGE_INTEGER wait;
//DbgPrint("debugger_waitForDebugEvent with timeout of %d\n",timeout);
//-10000000LL=1 second
//-10000LL should be 1 millisecond
//-10000LL
wait.QuadPart=-10000LL * timeout;
if (timeout==0xffffffff) //infinite wait
r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, NULL);
else
r=KeWaitForSingleObject(&debugger_event_WaitForDebugEvent, UserRequest, KernelMode, TRUE, &wait);
if (r==STATUS_SUCCESS)
return r;
else
return STATUS_UNSUCCESSFUL;
}
NTSTATUS debugger_continueDebugEvent(BOOL handled)
/*
Only call this by one thread only, and only when there's actually a debug eevnt in progress
*/
{
//DbgPrint("debugger_continueDebugEvent\n");
DebuggerState.handledlastevent=handled;
KeSetEvent(&debugger_event_WaitForContinue, 0,FALSE);
return STATUS_SUCCESS;
}
UINT_PTR *debugger_getLastStackPointer(void)
{
return DebuggerState.LastStackPointer;
}
NTSTATUS debugger_getDebuggerState(PDebugStackState state)
{
//DbgPrint("debugger_getDebuggerState\n");
state->threadid=(UINT64)DebuggerState.LastThreadID;
state->causedbydbvm = (UINT64)DebuggerState.CausedByDBVM;
if (DebuggerState.LastStackPointer)
{
state->rflags=(UINT_PTR)DebuggerState.LastStackPointer[si_eflags];
state->rax=DebuggerState.LastStackPointer[si_eax];
state->rbx=DebuggerState.LastStackPointer[si_ebx];
state->rcx=DebuggerState.LastStackPointer[si_ecx];
state->rdx=DebuggerState.LastStackPointer[si_edx];
state->rsi=DebuggerState.LastStackPointer[si_esi];
state->rdi=DebuggerState.LastStackPointer[si_edi];
state->rbp=DebuggerState.LastStackPointer[si_ebp];
#ifdef AMD64
//fill in the extra registers
state->r8=DebuggerState.LastStackPointer[si_r8];
state->r9=DebuggerState.LastStackPointer[si_r9];
state->r10=DebuggerState.LastStackPointer[si_r10];
state->r11=DebuggerState.LastStackPointer[si_r11];
state->r12=DebuggerState.LastStackPointer[si_r12];
state->r13=DebuggerState.LastStackPointer[si_r13];
state->r14=DebuggerState.LastStackPointer[si_r14];
state->r15=DebuggerState.LastStackPointer[si_r15];
memcpy(state->fxstate, (void *)&DebuggerState.LastStackPointer[si_xmm], 512);
#endif
//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
{
//priv level change, so the stack info was pushed as well
state->rsp=DebuggerState.LastStackPointer[si_esp];
state->ss=DebuggerState.LastStackPointer[si_ss];
}
else
{
//kernelmode stack, yeah, it's really useless here since changing it here only means certain doom, but hey...
state->rsp=(UINT_PTR)(DebuggerState.LastStackPointer)-4;
state->ss=getSS();; //unchangeble by the user
}
state->rip=DebuggerState.LastStackPointer[si_eip];
state->cs=DebuggerState.LastStackPointer[si_cs];
state->ds=DebuggerState.LastStackPointer[si_ds];
state->es=DebuggerState.LastStackPointer[si_es];
#ifdef AMD64
state->fs=0;
state->gs=0;
#else
state->fs=DebuggerState.LastStackPointer[si_fs];
state->gs=DebuggerState.LastStackPointer[si_gs];
#endif
state->dr0=DebuggerState.LastRealDebugRegisters[0];
state->dr1=DebuggerState.LastRealDebugRegisters[1];
state->dr2=DebuggerState.LastRealDebugRegisters[2];
state->dr3=DebuggerState.LastRealDebugRegisters[3];
state->dr6=DebuggerState.LastRealDebugRegisters[4];
state->dr7=DebuggerState.LastRealDebugRegisters[5];
/*if (DebuggerState.storeLBR)
{
//DbgPrint("Copying the LBR stack to usermode\n");
//DbgPrint("storeLBR_max=%d\n", DebuggerState.storeLBR_max);
for (state->LBR_Count=0; state->LBR_Count<DebuggerState.storeLBR_max; state->LBR_Count++ )
{
//DbgPrint("DebuggerState.LastLBRStack[%d]=%x\n", state->LBR_Count, DebuggerState.LastLBRStack[state->LBR_Count]);
state->LBR[state->LBR_Count]=DebuggerState.LastLBRStack[state->LBR_Count];
if (state->LBR[state->LBR_Count]==0) //no need to copy once a 0 has been reached
break;
}
}
else*/
state->LBR_Count=0;
return STATUS_SUCCESS;
}
else
{
//DbgPrint("debugger_getDebuggerState was called while DebuggerState.LastStackPointer was still NULL");
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS debugger_setDebuggerState(PDebugStackState state)
{
if (DebuggerState.LastStackPointer)
{
DebuggerState.LastStackPointer[si_eflags]=(UINT_PTR)state->rflags;
//DbgPrint("have set eflags to %x\n",DebuggerState.LastStackPointer[si_eflags]);
DebuggerState.LastStackPointer[si_eax]=(UINT_PTR)state->rax;
DebuggerState.LastStackPointer[si_ebx]=(UINT_PTR)state->rbx;
DebuggerState.LastStackPointer[si_ecx]=(UINT_PTR)state->rcx;
DebuggerState.LastStackPointer[si_edx]=(UINT_PTR)state->rdx;
DebuggerState.LastStackPointer[si_esi]=(UINT_PTR)state->rsi;
DebuggerState.LastStackPointer[si_edi]=(UINT_PTR)state->rdi;
DebuggerState.LastStackPointer[si_ebp]=(UINT_PTR)state->rbp;
//generally speaking, NOTHING should touch the esp register, but i'll provide it anyhow
if ((DebuggerState.LastStackPointer[si_cs] & 3) == 3) //if usermode code segment
{
//priv level change, so the stack info was pushed as well
DebuggerState.LastStackPointer[si_esp]=(UINT_PTR)state->rsp;
//don't mess with ss
}
else
{
//no change in kernelmode allowed
}
DebuggerState.LastStackPointer[si_eip]=(UINT_PTR)state->rip;
DebuggerState.LastStackPointer[si_cs]=(UINT_PTR)state->cs;
DebuggerState.LastStackPointer[si_ds]=(UINT_PTR)state->ds;
DebuggerState.LastStackPointer[si_es]=(UINT_PTR)state->es;
#ifndef AMD64
DebuggerState.LastStackPointer[si_fs]=(UINT_PTR)state->fs;
DebuggerState.LastStackPointer[si_gs]=(UINT_PTR)state->gs;
#else //don't touch fs or gs in 64-bit
DebuggerState.LastStackPointer[si_r8]=(UINT_PTR)state->r8;
DebuggerState.LastStackPointer[si_r9]=(UINT_PTR)state->r9;
DebuggerState.LastStackPointer[si_r10]=(UINT_PTR)state->r10;
DebuggerState.LastStackPointer[si_r11]=(UINT_PTR)state->r11;
DebuggerState.LastStackPointer[si_r12]=(UINT_PTR)state->r12;
DebuggerState.LastStackPointer[si_r13]=(UINT_PTR)state->r13;
DebuggerState.LastStackPointer[si_r14]=(UINT_PTR)state->r14;
DebuggerState.LastStackPointer[si_r15]=(UINT_PTR)state->r15;
memcpy((void *)&DebuggerState.LastStackPointer[si_xmm], state->fxstate, 512);
#endif
if (!DebuggerState.globalDebug)
{
//no idea why someone would want to use this method, but it's in (for NON globaldebug only)
//updating this array too just so the user can see it got executed. (it eases their state of mind...)
DebuggerState.LastRealDebugRegisters[0]=(UINT_PTR)state->dr0;
DebuggerState.LastRealDebugRegisters[1]=(UINT_PTR)state->dr1;
DebuggerState.LastRealDebugRegisters[2]=(UINT_PTR)state->dr2;
DebuggerState.LastRealDebugRegisters[3]=(UINT_PTR)state->dr3;
DebuggerState.LastRealDebugRegisters[4]=(UINT_PTR)state->dr6;
DebuggerState.LastRealDebugRegisters[5]=(UINT_PTR)state->dr7;
//no setting of the DebugRegs here
}
}
else
{
//DbgPrint("debugger_setDebuggerState was called while DebuggerState.LastStackPointer was still NULL");
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs, UINT_PTR *LBR_Stack, int causedbyDBVM)
//Notice: This routine is called when interrupts are enabled and the GD bit has been set if globaL DEBUGGING HAS BEEN USED
//Interrupts are enabled and should be at passive level, so taskswitching is possible
{
NTSTATUS r=STATUS_UNSUCCESSFUL;
int handled=0; //0 means let the OS handle it
LARGE_INTEGER timeout;
timeout.QuadPart=-100000;
//DbgPrint("breakpointHandler for kernel breakpoints\n");
#ifdef AMD64
//DbgPrint("cs=%x ss=%x ds=%x es=%x fs=%x gs=%x\n",getCS(), getSS(), getDS(), getES(), getFS(), getGS());
//DbgPrint("fsbase=%llx gsbase=%llx gskernel=%llx\n", readMSR(0xc0000100), readMSR(0xc0000101), readMSR(0xc0000102));
//DbgPrint("rbp=%llx\n", getRBP());
//DbgPrint("gs:188=%llx\n", __readgsqword(0x188));
//DbgPrint("causedbyDBVM=%d\n", causedbyDBVM);
#endif
if (KeGetCurrentIrql()==0)
{
//crititical section here
if ((stackpointer[si_cs] & 3)==0)
{
//DbgPrint("Going to wait in a kernelmode routine\n");
}
//block other threads from breaking until this one has been handled
while (r != STATUS_SUCCESS)
{
r=KeWaitForSingleObject(&debugger_event_CanBreak,Executive, KernelMode, FALSE, NULL);
//check r and handle specific events
//DbgPrint("Woke up. r=%x\n",r);
}
if ((stackpointer[si_cs] & 3)==0)
{
//DbgPrint("Woke up in a kernelmode routine\n");
}
//We're here, let's notify the usermode debugger of our situation
//first store the stackpointer so it can be manipulated externally
DebuggerState.LastStackPointer=stackpointer;
DebuggerState.LastRealDebugRegisters=currentdebugregs;
/*DebuggerState.LastLBRStack=LBR_Stack;*/
DebuggerState.LastThreadID=PsGetCurrentThreadId();
DebuggerState.CausedByDBVM = causedbyDBVM;
//notify usermode app that this thread has halted due to a debug event
KeSetEvent(&debugger_event_WaitForDebugEvent,0,FALSE);
//wait for event from usermode that debgu event has been handled
//KeWaitForSingleObject();
//continue with state
while (1)
{
//LARGE_INTEGER wt;
NTSTATUS s=STATUS_UNSUCCESSFUL;
//wt.QuadPart=-10000000LL;
//s=KeDelayExecutionThread(KernelMode, FALSE, &wt);
//DbgPrint("Waiting...\n");
while (s != STATUS_SUCCESS)
{
s=KeWaitForSingleObject(&debugger_event_WaitForContinue, Executive, KernelMode, FALSE, NULL);
//DbgPrint("KeWaitForSingleObject=%x\n",s);
}
if (s==STATUS_SUCCESS)
{
if (DebuggerState.handledlastevent)
{
//DbgPrint("handledlastevent=TRUE");
handled=1;
}
else
handled=0;
break;
}
}
DebuggerState.LastStackPointer=NULL; //NULL the stackpointer so routines know it should not be called
//i'm done, let other threads catch it
KeSetEvent(&debugger_event_CanBreak, 0, FALSE);
//DbgPrint("Returning after a wait. handled=%d and eflags=%x\n",handled, stackpointer[si_eflags]);
if ((stackpointer[si_cs] & 3)==0) //check rpl of cs
{
//DbgPrint("and in kernelmode\n");
}
return handled;
}
else
{
//DbgPrint("Breakpoint wasn't at passive level. Screw this, i'm not going to break here\n");
return 1;
}
}
int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
{
HANDLE CurrentProcessID=PsGetCurrentProcessId();
UINT_PTR originaldr6=currentdebugregs[4];
DebugReg6 _dr6=*(DebugReg6 *)¤tdebugregs[4];
UINT_PTR LBR_Stack[16]; //max 16
// DebugReg7 _dr7=*(DebugReg7 *)¤tdebugregs[5];
int causedbyDBVM = vmxusable && vmx_causedCurrentDebugBreak();
/*
if (cpu_familyID==0x6)
{
if (DebuggerState.storeLBR)
{
//fetch the lbr stack
int MSR_LASTBRANCH_TOS=0x1c9;
int MSR_LASTBRANCH_0=0x40;
int i;
int count;
i=(int)__readmsr(MSR_LASTBRANCH_TOS);
count=0;
while (count<DebuggerState.storeLBR_max)
{
UINT64 x;
x=__readmsr(MSR_LASTBRANCH_0+i);
LBR_Stack[count]=(UINT_PTR)x;
__writemsr(MSR_LASTBRANCH_0+i,0); //it has been read out, so can be erased now
count++;
i++;
i=i % DebuggerState.storeLBR_max;
}
}
}
*/
//DbgPrint("interrupt1_handler(%p). DR6=%x (%x) DR7=%x %x:%p\n", interrupt1_handler, originaldr6, debugger_dr6_getValueDword(), debugger_dr7_getValueDword(), stackpointer[si_cs], (void*)(stackpointer[si_eip]));
//check if this break should be handled or not
if (DebuggerState.globalDebug)
{
//DbgPrint("DebuggerState.globalDebug=TRUE\n");
//global debugging is being used
if (_dr6.BD)
{
_dr6.BD = 0;
debugger_dr6_setValue(*(UINT_PTR *)&_dr6);
//The debug registers are being accessed, emulate it with DebuggerState.FakedDebugRegisterState[cpunr()].DRx
if ((stackpointer[si_cs] & 3)==0)
{
int instructionPointer;
#ifdef AMD64
int prefixpointer;
#endif
int currentcpunr = cpunr();
int debugregister;
int generalpurposeregister;
unsigned char *instruction = (unsigned char *)stackpointer[si_eip];
//unset this flag in DR6
_dr6.BD = 0;
debugger_dr6_setValue(*(UINT_PTR *)&_dr6);
if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
{
((EFLAGS *)&stackpointer[si_eflags])->RF = 1; //repeat this instruction and don't break
return 2;
}
//DbgPrint("handler: Setting fake dr6 to %x\n",*(UINT_PTR *)&_dr6);
DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = *(UINT_PTR *)&_dr6;
for (instructionPointer = 0; instruction[instructionPointer] != 0x0f; instructionPointer++); //find the start of the instruction, skipping prefixes etc...
//we now have the start of the instruction.
//Find out which instruction it is, and which register is used
debugregister = (instruction[instructionPointer + 2] >> 3) & 7;
generalpurposeregister = instruction[instructionPointer + 2] & 7;
#ifdef AMD64
for (prefixpointer = 0; prefixpointer < instructionPointer; prefixpointer++)
{
//check for a REX.B prefix (0x40 + 0x1 : 0x41)
if ((instruction[prefixpointer] & 0x41) == 0x41)
{
//rex.b prefix is used, r8 to r15 are being accessed
generalpurposeregister += 8;
}
}
#endif
//DbgPrint("debugregister=%d, generalpurposeregister=%d\n",debugregister,generalpurposeregister);
if (instruction[instructionPointer + 1] == 0x21)
{
UINT_PTR drvalue = 0;
//DbgPrint("read opperation\n");
//21=read
switch (debugregister)
{
case 0:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
//DbgPrint("Reading DR0 (returning %x real %x)\n", drvalue, currentdebugregs[0]);
break;
case 1:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
break;
case 2:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
break;
case 3:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
break;
case 4:
case 6:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
//DbgPrint("reading dr6 value:%x\n",drvalue);
break;
case 5:
case 7:
drvalue = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
break;
default:
//DbgPrint("Invalid debugregister\n");
drvalue = 0;
break;
}
switch (generalpurposeregister)
{
case 0:
stackpointer[si_eax] = drvalue;
break;
case 1:
stackpointer[si_ecx] = drvalue;
break;
case 2:
stackpointer[si_edx] = drvalue;
break;
case 3:
stackpointer[si_ebx] = drvalue;
break;
case 4:
if ((stackpointer[si_cs] & 3) == 3) //usermode dr access ?
stackpointer[si_esp] = drvalue;
else
stackpointer[si_stack_esp] = drvalue;
break;
case 5:
stackpointer[si_ebp] = drvalue;
break;
case 6:
stackpointer[si_esi] = drvalue;
break;
case 7:
stackpointer[si_edi] = drvalue;
break;
#ifdef AMD64
case 8:
stackpointer[si_r8] = drvalue;
break;
case 9:
stackpointer[si_r9] = drvalue;
break;
case 10:
stackpointer[si_r10] = drvalue;
break;
case 11:
stackpointer[si_r11] = drvalue;
break;
case 12:
stackpointer[si_r12] = drvalue;
break;
case 13:
stackpointer[si_r13] = drvalue;
break;
case 14:
stackpointer[si_r14] = drvalue;
break;
case 15:
stackpointer[si_r15] = drvalue;
break;
#endif
}
}
else
if (instruction[instructionPointer + 1] == 0x23)
{
//23=write
UINT_PTR gpvalue = 0;
//DbgPrint("Write operation\n");
switch (generalpurposeregister)
{
case 0:
gpvalue = stackpointer[si_eax];
break;
case 1:
gpvalue = stackpointer[si_ecx];
break;
case 2:
gpvalue = stackpointer[si_edx];
break;
case 3:
gpvalue = stackpointer[si_ebx];
break;
case 4:
if ((stackpointer[si_cs] & 3) == 3)
gpvalue = stackpointer[si_esp];
break;
case 5:
gpvalue = stackpointer[si_ebp];
break;
case 6:
gpvalue = stackpointer[si_esi];
break;
case 7:
gpvalue = stackpointer[si_edi];
break;
#ifdef AMD64
case 8:
gpvalue = stackpointer[si_r8];
break;
case 9:
gpvalue = stackpointer[si_r9];
break;
case 10:
gpvalue = stackpointer[si_r10];
break;
case 11:
gpvalue = stackpointer[si_r11];
break;
case 12:
gpvalue = stackpointer[si_r12];
break;
case 13:
gpvalue = stackpointer[si_r13];
break;
case 14:
gpvalue = stackpointer[si_r14];
break;
case 15:
gpvalue = stackpointer[si_r15];
break;
default:
//DbgPrint("Invalid register value\n");
break;
#endif
}
//gpvalue now contains the value to set the debug register
switch (debugregister)
{
case 0:
//DbgPrint("Writing DR0. Original value=%x new value=%x\n", currentdebugregs[0], gpvalue);
debugger_dr0_setValue(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR0 = debugger_dr0_getValue();
break;
case 1:
debugger_dr1_setValue(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR1 = debugger_dr1_getValue();
break;
case 2:
debugger_dr2_setValue(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR2 = debugger_dr2_getValue();
break;
case 3:
debugger_dr3_setValue(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR3 = debugger_dr3_getValue();
break;
case 4:
case 6:
//DbgPrint("Setting dr6 to %x (was %x)\n", gpvalue, DebuggerState.FakedDebugRegisterState[cpunr()].DR6);
_dr6 = *(DebugReg6 *)&gpvalue;
//if (_dr6.BD) DbgPrint("Some code wants to set the BD flag to 1\n");
debugger_dr6_setValue(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();
if (_dr6.BD)
{
_dr6.BD = 0;
debugger_dr6_setValue(gpvalue);
}
break;
case 5:
case 7:
//make sure it doesn't set the GD flag here
//DbgPrint("DR7 write\n");
//if (generalpurposeregister == 15)
//{
// while (1); //patchguard
//}
//if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue)
//{
// DbgPrint("Was in epilogue\n");
//}
//check for invalid bits and raise a GPF if invalid
gpvalue = (gpvalue | 0x400) & (~(1 << 13)); //unset the GD value
//gpvalue=0xf0401;
debugger_dr7_setValueDword(gpvalue);
DebuggerState.FakedDebugRegisterState[cpunr()].DR7 = debugger_dr7_getValueDword();
break;
}
}
else
{
//DbgPrint("Some unknown instruction accessed the debug registers?\n");
//if (CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
// DbgPrint("Happened inside the target process\n");
//DbgPrint("interrupt1_handler dr6=%x (original=%x) dr7=%d\n",_dr6, originaldr6, _dr7);
//DbgPrint("eip=%x\n",stackpointer[si_eip]);
}
//adjust eip to after this instruction
stackpointer[si_eip] += instructionPointer + 3; //0f xx /r
return 1; //don't tell windows about it
}
else
{
//DbgPrint("DR6.BD == 1 in USERMODE! WTF\n");
_dr6.BD = 0;
debugger_dr6_setValue(*(UINT_PTR *)&_dr6);
DebuggerState.FakedDebugRegisterState[cpunr()].DR6 = debugger_dr6_getValueDword();
}
}
}
if (DebuggerState.isSteppingTillClear) //this doesn't really work because when the state comes back to interruptable the system has a critical section lock on the GUI, so yeah... I really need a DBVM display driver for this
{
if ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))
{
((PEFLAGS)&stackpointer[si_eflags])->TF = 1;
((PEFLAGS)&stackpointer[si_eflags])->RF = 1;
debugger_dr6_setValue(0xffff0ff0);
return 1;
}
DebuggerState.isSteppingTillClear = FALSE;
}
if (DebuggerState.isDebugging)
{
//DbgPrint("DebuggerState.isDebugging\n");
//check if this should break
if (CurrentProcessID == (HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID)
{
UINT_PTR originaldebugregs[6];
UINT64 oldDR7 = getDR7();
if ((((PEFLAGS)&stackpointer[si_eflags])->IF == 0) || (KeGetCurrentIrql() != PASSIVE_LEVEL))
{
//There's no way to display the state to the usermode part of CE
//DbgPrint("int1 at unstoppable location");
if (!KernelCodeStepping)
{
((PEFLAGS)&stackpointer[si_eflags])->TF = 0; //just give up stepping
// DbgPrint("Quitting this");
}
else
{
// DbgPrint("Stepping until valid\n");
((PEFLAGS)&stackpointer[si_eflags])->TF = 1; //keep going until a valid state
DebuggerState.isSteppingTillClear = TRUE; //Just in case a taskswitch happens right after enabling passive level with interrupts
}
((PEFLAGS)&stackpointer[si_eflags])->RF = 1;
debugger_dr6_setValue(0xffff0ff0);
return 1;
}
DebuggerState.isSteppingTillClear = FALSE;
//DbgPrint("CurrentProcessID==(HANDLE)(UINT_PTR)DebuggerState.debuggedProcessID\n");
if (DebuggerState.globalDebug)
{
originaldebugregs[0] = DebuggerState.FakedDebugRegisterState[cpunr()].DR0;
originaldebugregs[1] = DebuggerState.FakedDebugRegisterState[cpunr()].DR1;
originaldebugregs[2] = DebuggerState.FakedDebugRegisterState[cpunr()].DR2;
originaldebugregs[3] = DebuggerState.FakedDebugRegisterState[cpunr()].DR3;
originaldebugregs[4] = DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
originaldebugregs[5] = DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
}
//DbgPrint("BP in target process\n");
//no extra checks if it's caused by the debugger or not. That is now done in the usermode part
//if (*(PEFLAGS)(&stackpointer[si_eflags]).IF)
/*
if (((PEFLAGS)&stackpointer[si_eflags])->IF==0)
{
//DbgPrint("Breakpoint while interrupts are disabled: %x\n",stackpointer[si_eip]);
//An breakpoint happened while IF was 0. Step through the code untill IF is 1
((PEFLAGS)&stackpointer[si_eflags])->RF=1;
((PEFLAGS)&stackpointer[si_eflags])->TF=1; //keep going until IF=1
DbgPrint("IF==0\n");
return 1; //don't handle it but also don't tell windows
}*/
//set the real debug registers to what it is according to the guest (so taskswitches take over these values) .... shouldn't be needed as global debug is on which fakes that read...
if (DebuggerState.globalDebug)
{
//enable the GD flag for taskswitches that will occur as soon as interrupts are enabled
//this also means: DO NOT EDIT THE DEBUG REGISTERS IN GLOBAL DEBUG MODE at this point. Only in the epilogue
if (!DebuggerState.stoppingTheDebugger) //This is set when the driver is unloading. So do NOT set it back then
debugger_dr7_setGD(DebuggerState.globalDebug);
}
else
{
//unset ALL debug registers before enabling taskswitching. Just re-enable it when back when interrupts are disabled again
debugger_dr7_setValueDword(0x400);
debugger_dr0_setValue(0);
debugger_dr1_setValue(0);
debugger_dr2_setValue(0);
debugger_dr3_setValue(0);
debugger_dr6_setValue(0xffff0ff0);
}
//start the windows taskswitching mode
//if (1) return 1;
//save the state of the thread to a place that won't get overwritten
//todo: breaks 32-bit
//int i;
BOOL NeedsToGrowStackList = FALSE;
PSavedStack SelectedStackEntry = NULL;
/*
csEnter(&StacksCS);
for (i = 0; i < StackCount; i++)
{
if (Stacks[i]->inuse == FALSE)
{
SelectedStackEntry = Stacks[i];
SelectedStackEntry->inuse = TRUE;
RtlCopyMemory(SelectedStackEntry->stacksnapshot, stackpointer, 600 * 8);
if (i > StackCount / 2)
NeedsToGrowStackList = TRUE;
break;
}
}
csLeave(&StacksCS);
enableInterrupts();
//grow stack if needed
if (NeedsToGrowStackList)
debugger_growstack();
*/
{
int rs=1;
//DbgPrint("calling breakpointHandler_kernel\n");
if (SelectedStackEntry == NULL) //fuck
rs = breakpointHandler_kernel(stackpointer, currentdebugregs, LBR_Stack, causedbyDBVM);
else
rs = breakpointHandler_kernel((UINT_PTR *)(SelectedStackEntry->stacksnapshot), currentdebugregs, LBR_Stack, causedbyDBVM);
//DbgPrint("After handler\n");
/*
if (SelectedStackEntry) //restore the stack
{
RtlCopyMemory(stackpointer, SelectedStackEntry->stacksnapshot, 600 * 8);
SelectedStackEntry->inuse = FALSE;
}
*/
//DbgPrint("rs=%d\n",rs);
disableInterrupts();
//restore the
//we might be on a different CPU now
if (DebuggerState.globalDebug)
{
DebuggerState.FakedDebugRegisterState[cpunr()].DR0=originaldebugregs[0];
DebuggerState.FakedDebugRegisterState[cpunr()].DR1=originaldebugregs[1];
DebuggerState.FakedDebugRegisterState[cpunr()].DR2=originaldebugregs[2];
DebuggerState.FakedDebugRegisterState[cpunr()].DR3=originaldebugregs[3];
DebuggerState.FakedDebugRegisterState[cpunr()].DR6=originaldebugregs[4];
DebuggerState.FakedDebugRegisterState[cpunr()].DR7=originaldebugregs[5];
}
else
{
/*if (getDR7() != oldDR7)
{
DbgPrint("Something changed DR7. old=%llx new=%llx\n",oldDR7, getDR7());
}*/
//set the debugregisters to what they where set to before taskswitching was enable
//with global debug this is done elsewhere
debugger_dr0_setValue(currentdebugregs[0]);
debugger_dr1_setValue(currentdebugregs[1]);
debugger_dr2_setValue(currentdebugregs[2]);
debugger_dr3_setValue(currentdebugregs[3]);
debugger_dr6_setValue(currentdebugregs[4]);
if ((currentdebugregs[5] >> 13) & 1)
{
// DbgPrint("WTF? GD is 1 in currentdebugregs[5]: %llx\n", currentdebugregs[5]);
}
else
debugger_dr7_setValue(*(DebugReg7 *)¤tdebugregs[5]);
}
return rs;
}
}
else
{
//DbgPrint("Not the debugged process (%x != %x)\n",CurrentProcessID,DebuggerState.debuggedProcessID );
//check if this break is due to a breakpoint ce has set. (during global debug threadsurfing))
//do that by checking if the breakpoint condition exists in the FAKE dr7 registers
//if so, let windows handle it, if not, it is caused by ce, which then means, skip (so execute normally)
if (DebuggerState.globalDebug)
{
DebugReg6 dr6=debugger_dr6_getValue();
DebugReg7 dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
//real dr6 //fake dr7
if ((dr6.B0) && (!(dr7.L0 || dr7.G0))) { /*DbgPrint("setting RF because of B0\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } //break caused by DR0 and not expected by the current process, ignore this bp and continue
if ((dr6.B1) && (!(dr7.L1 || dr7.G1))) { /*DbgPrint("setting RF because of B1\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } // ... DR1 ...
if ((dr6.B2) && (!(dr7.L2 || dr7.G2))) { /*DbgPrint("setting RF because of B2\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } // ... DR2 ...
if ((dr6.B3) && (!(dr7.L3 || dr7.G3))) { /*DbgPrint("setting RF because of B3\n");*/ ((PEFLAGS)&stackpointer[si_eflags])->RF=1; return 1; } // ... DR3 ...
}
if (causedbyDBVM)
return 1; //correct PA, bad PID, ignore BP
if (DebuggerState.isSteppingTillClear) //shouldn't happen often
{
//DbgPrint("That thing that shouldn\'t happen often happened\n");
((PEFLAGS)&stackpointer[si_eflags])->TF = 0;
DebuggerState.isSteppingTillClear = 0;
return 1; //ignore
}
//DbgPrint("Returning unhandled. DR6=%x", debugger_dr6_getValueDword());
return 0; //still here, so let windows handle it
}
}
else
return 0; //Let windows handle it
//get the current processid
//is it being debugged
//if yes, check if the breakpoint is something done by me
//if no, exit
}
int interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-bit stackpointer
{
UINT_PTR before;//,after;
UINT_PTR currentdebugregs[6]; //used for determining if the current bp is caused by the debugger or not
int handled=0; //if 0 at return, the interupt will be passed down to the operating system
QWORD naddress;
//DbgPrint("interrupt1_centry cpunr=%d esp=%x\n",cpunr(), getRSP());
//bsod crashfix, but also disables kernelmode stepping
IDT idt;
GetIDT(&idt);
naddress = idt.vector[1].wLowOffset + (idt.vector[1].wHighOffset << 16);
#ifdef AMD64
naddress += ((UINT64)idt.vector[1].TopOffset << 32);
#endif
stackpointer[si_errorcode] = (UINT_PTR)naddress; //the errorcode is used as address to call the original function if needed
/*
if (Int1JumpBackLocation.eip != naddress) //no, just fucking no (patchguard will replace all inthandlers with invalid ones and then touch dr7)
{
//todo: the usual, but make sure not to use dbgprint or anything that could trigger a software int
if (DebuggerState.globalDebug)
{
debugger_dr7_setGD(DebuggerState.globalDebug);
stackpointer[si_eip] += 4;
return 1;
}
}
*/
before=getRSP();
//Fetch current debug registers
currentdebugregs[0]=debugger_dr0_getValue();
currentdebugregs[1]=debugger_dr1_getValue();
currentdebugregs[2]=debugger_dr2_getValue();
currentdebugregs[3]=debugger_dr3_getValue();
currentdebugregs[4]=debugger_dr6_getValueDword();
currentdebugregs[5]=debugger_dr7_getValueDword();
handled=interrupt1_handler(stackpointer, currentdebugregs);
//epilogue:
//At the end when returning:
//
//--------------------------------------------------------------------------
//--------------EPILOGUE (AFTER HAVING HANDLED THE BREAKPOINT)--------------
//--------------------------------------------------------------------------
//
disableInterrupts(); //just making sure..
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
debugger_dr7_setGD(0); //make sure the GD bit is disabled (int1 within int1, oooh the fun..., and yes, THIS itself will cause one too)
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1; //just be sure...
//if (inthook_isDBVMHook(1))
//{
//update the int1 return address, could have been changed
//DbgPrint("This was a dbvm hook. Changing if the interrupt return address is still valid\n");
// Int1JumpBackLocation.cs=idt.vector[1].wSelector;
// naddress=idt.vector[1].wLowOffset+(idt.vector[1].wHighOffset << 16);
#ifdef AMD64
// naddress+=((UINT64)idt.vector[1].TopOffset << 32);
#endif
//}
if (DebuggerState.globalDebug) //DR's are only accesses when there are DR's(no idea how it handles breakpoints in a different process...), so set them in each thread even those that don't belong original: && (PsGetCurrentProcessId()==(HANDLE)DebuggerState.debuggedProcessID))
{
//set the breakpoint in this thread.
DebugReg6 dr6=debugger_dr6_getValue();
//DebugReg7 dr7=debugger_dr7_getValue();
DebugReg6 _dr6=*(DebugReg6 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR6;
DebugReg7 _dr7=*(DebugReg7 *)&DebuggerState.FakedDebugRegisterState[cpunr()].DR7;
int debugregister=0, breakpoint=0;
//first clear the DR6 bits caused by the debugger
if (!handled)
{
//it's going to get sent to windows
if (dr6.BD && _dr7.GD) _dr6.BD=1; //should already have been done, but what the heck...
if (dr6.B0 && (_dr7.L0 || _dr7.G0)) _dr6.B0=1;
if (dr6.B1 && (_dr7.L1 || _dr7.G1)) _dr6.B1=1;
if (dr6.B2 && (_dr7.L2 || _dr7.G2)) _dr6.B2=1;
if (dr6.B3 && (_dr7.L3 || _dr7.G3)) _dr6.B3=1;
_dr6.BS=dr6.BS;
_dr6.BT=dr6.BT;
//DbgPrint("epilogue: Setting fake dr6 to %x (fake=%x)\n",*(DWORD *)&dr6, *(DWORD *)&_dr6);
}
debugger_dr6_setValue(0xffff0ff0);
//set the debug registers of active breakpoints. Doesn't have to be in the specified order. Just find an unused debug registers
//check DebuggerState.FakedDebugRegisterState[cpunumber].DR7 for unused breakpoints
//set state to what the guest thinks it is
debugger_dr0_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR0);
debugger_dr1_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR1);
debugger_dr2_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR2);
debugger_dr3_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR3);
debugger_dr6_setValue(DebuggerState.FakedDebugRegisterState[cpunr()].DR6);
for (breakpoint=0; breakpoint<4; breakpoint++)
{
if (DebuggerState.breakpoint[breakpoint].active)
{
int foundone=0;
// DbgPrint("Want to set breakpoint %d\n",breakpoint);
//find a usable debugregister
while ((debugregister<4) && (foundone==0))
{
if (DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue==0)
{
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=1;
}
//check if this debugregister is usable
if (((DebuggerState.FakedDebugRegisterState[cpunr()].DR7 >> (debugregister*2)) & 3)==0) //DR7.Gx and DR7.Lx are 0
{
// DbgPrint("debugregister %d is free to be used\n",debugregister);
foundone=1;
//set address
switch (debugregister)
{
case 0:
debugger_dr0_setValue(DebuggerState.breakpoint[breakpoint].address);
_dr7.L0=1;
_dr7.LEN0=DebuggerState.breakpoint[breakpoint].breakLength;
_dr7.RW0=DebuggerState.breakpoint[breakpoint].breakType;
break;
case 1:
debugger_dr1_setValue(DebuggerState.breakpoint[breakpoint].address);
_dr7.L1=1;
_dr7.LEN1=DebuggerState.breakpoint[breakpoint].breakLength;
_dr7.RW1=DebuggerState.breakpoint[breakpoint].breakType;
break;
case 2:
debugger_dr2_setValue(DebuggerState.breakpoint[breakpoint].address);
_dr7.L2=1;
_dr7.LEN2=DebuggerState.breakpoint[breakpoint].breakLength;
_dr7.RW2=DebuggerState.breakpoint[breakpoint].breakType;
break;
case 3:
debugger_dr3_setValue(DebuggerState.breakpoint[breakpoint].address);
_dr7.L3=1;
_dr7.LEN3=DebuggerState.breakpoint[breakpoint].breakLength;
_dr7.RW3=DebuggerState.breakpoint[breakpoint].breakType;
break;
}
}
debugregister++;
}
}
}
debugger_dr7_setValue(_dr7);
//DbgPrint("after:\n");
//DbgPrint("after fake DR0=%x real DR0=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR0, debugger_dr0_getValue());
//DbgPrint("after fake DR1=%x real DR1=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR1, debugger_dr1_getValue());
//DbgPrint("after fake DR2=%x real DR2=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR2, debugger_dr2_getValue());
//DbgPrint("after fake DR3=%x real DR3=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR3, debugger_dr3_getValue());
//DbgPrint("after fake DR6=%x real DR6=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR6, debugger_dr6_getValueDword());
//DbgPrint("after fake DR7=%x real DR7=%x\n",DebuggerState.FakedDebugRegisterState[currentcpunr].DR7, debugger_dr7_getValueDword());
}
else
{
//not global debug, just clear all flags and be done with it
if (handled)
debugger_dr6_setValue(0xffff0ff0);
}
disableInterrupts();
if (handled == 2)
{
//DbgPrint("handled==2\n");
handled = 1; //epilogue = 1 Dr handler
}
else
{
//not handled by the epilogue set DR0, so the actual epilogue
//DbgPrint("handled==1\n");
if (DebuggerState.globalDebug)
{
DebuggerState.FakedDebugRegisterState[cpunr()].inEpilogue=0;
if (!DebuggerState.stoppingTheDebugger)
debugger_dr7_setGD(DebuggerState.globalDebug); //set it back to 1, if not unloading
}
}
//after=getRSP();
//DbgPrint("before=%llx after=%llx\n",before,after);
//DbgPrint("end of interrupt1_centry. eflags=%x", stackpointer[si_eflags]);
//if branch tracing set lbr back on (get's disabled on debug interrupts)
/*
if (DebuggerState.storeLBR)
__writemsr(0x1d9, __readmsr(0x1d9) | 1);
*/
return handled;
}
#ifndef AMD64
_declspec( naked ) void interrupt1_asmentry( void )
//This routine is called upon an interrupt 1, even before windows gets it
{
__asm{
//change the start of the stack so that instructions like setthreadcontext do not affect the stack it when it's frozen and waiting for input
//meaning the setting of debug registers will have to be done with the changestate call
//sub esp,4096
//push [esp+4096+0+16] //optional ss
//push [esp+4096+4+12] //optional esp
//push [esp+4096+8+8] //eflags
//push [esp+4096+12+4] //cs
//push [esp+4096+16+0] //eip
cld //reset the direction flag
//save stack position
push 0 //push an errorcode on the stack so the stackindex can stay the same
push ebp
mov ebp,esp
//save state
pushad
xor eax,eax
mov ax,ds
push eax
mov ax,es
push eax
mov ax,fs
push eax
mov ax,gs
push eax
//save fpu state
//save sse state
mov ax,0x23 //0x10 should work too, but even windows itself is using 0x23
mov ds,ax
mov es,ax
mov gs,ax
mov ax,0x30
mov fs,ax
push ebp
call interrupt1_centry
cmp eax,1 //set flag
//restore state
pop gs
pop fs
pop es
pop ds
popad
pop ebp
je skip_original_int1
add esp,4 //undo errorcode push (add effects eflags, so set it at both locations)
jmp far [Int1JumpBackLocation]
skip_original_int1:
add esp,4 //undo errorcode push
iretd
}
}
#endif
================================================
FILE: src/debugger.h
================================================
#ifndef DEBUGGER_H
#define DEBUGGER_H
#include <ntifs.h>
#include <windef.h>
#pragma pack(4)
typedef struct {
UINT64 threadid; //
UINT64 causedbydbvm;
UINT64 rflags;
UINT64 rax;//
UINT64 rbx;
UINT64 rcx;//
UINT64 rdx;
UINT64 rsi;//
UINT64 rdi;
UINT64 rbp;//
UINT64 rsp;
UINT64 rip;//
UINT64 r8;
UINT64 r9;//
UINT64 r10;
UINT64 r11;//
UINT64 r12;
UINT64 r13;//
UINT64 r14;
UINT64 r15;//
UINT64 cs;
UINT64 ds;//
UINT64 es;
UINT64 fs;//
UINT64 gs;
UINT64 ss;//
UINT64 dr0;
UINT64 dr1;//
UINT64 dr2;
UINT64 dr3;//
UINT64 dr6;
UINT64 dr7;//
BYTE fxstate[512];
UINT64 LBR_Count;
UINT64 LBR[16];
} DebugStackState, *PDebugStackState;
#pragma pack()
//stack index
typedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnReadsAndWrites=3} BreakType;
typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/, bl_4byte=3} BreakLength;
void debugger_initialize(void);
void debugger_shutdown(void);
int debugger_initHookForCurrentCPU(void);
int debugger_setGlobalDebugState(BOOL state);
void debugger_setStoreLBR(BOOL state);
int debugger_startDebugging(DWORD debuggedProcessID);
int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakType bt, BreakLength bl);
int debugger_unsetGDBreakpoint(int breakpointnr);
void debugger_touchDebugRegister(UINT_PTR param);
int debugger_stopDebugging(void);
NTSTATUS debugger_waitForDebugEvent(ULONG timeout);
NTSTATUS debugger_continueDebugEvent(BOOL handled);
UINT_PTR *debugger_getLastStackPointer(void);
NTSTATUS debugger_getDebuggerState(PDebugStackState state);
NTSTATUS debugger_setDebuggerState(PDebugStackState state);
void GetDebuggerInfo(void);
VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
#endif
================================================
FILE: src/deepkernel.c
================================================
#pragma warning( disable: 4100 4103)
#include "deepkernel.h"
#include "DBKFunc.h"
#include <windef.h>
#include "vmxhelper.h"
BOOLEAN MakeWritableKM(PVOID StartAddress,UINT_PTR size)
{
#ifndef AMD64
UINT_PTR PTE,PDE;
struct PTEStruct *x;
UINT_PTR CurrentAddress=(UINT_PTR)StartAddress;
while (CurrentAddress<((UINT_PTR)StartAddress+size))
{
//find the PTE or PDE of the selected address
PTE=(UINT_PTR)CurrentAddress;
PTE=PTE/0x1000*PTESize+0xc0000000;
PTE=(UINT_PTR)StartAddress;
PTE=PTE/0x1000*PTESize+0xc0000000;
//now check if the address in PTE is valid by checking the page table directory at 0xc0300000 (same location as CR3 btw)
PDE=PTE/0x1000*PTESize+0xc0000000; //same formula
x=(PVOID)PDE;
if ((x->P==0) && (x->A2==0))
{
CurrentAddress+=PAGE_SIZE_LARGE;
continue;
}
if (x->PS==1)
{
//big page, no pte
x->RW=1;
CurrentAddress+=PAGE_SIZE_LARGE;
continue;
}
CurrentAddress+=0x1000;
x=(PVOID)PTE;
if ((x->P==0) && (x->A2==0))
continue; //see for explenation the part of the PDE
x->RW=1;
}
return TRUE;
#else
return FALSE;
gitextract_ndahrtj5/
├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── scripts/
│ ├── builder.js
│ ├── context.js
│ ├── multibuilder.js
│ ├── paths.js
│ └── utils.js
├── src/
│ ├── DBKDrvr.c
│ ├── DBKDrvr.h
│ ├── DBKFunc.c
│ ├── DBKFunc.h
│ ├── IOPLDispatcher.c
│ ├── IOPLDispatcher.h
│ ├── amd64/
│ │ ├── dbkfunca.asm
│ │ ├── debuggera.asm
│ │ ├── noexceptionsa.asm
│ │ ├── ultimapa.asm
│ │ ├── vmxhelpera.asm
│ │ └── vmxoffloada.asm
│ ├── debugger.c
│ ├── debugger.h
│ ├── deepkernel.c
│ ├── deepkernel.h
│ ├── extradefines.h
│ ├── extraimports.h
│ ├── interruptHook.c
│ ├── interruptHook.h
│ ├── memscan.c
│ ├── memscan.h
│ ├── noexceptions.c
│ ├── noexceptions.h
│ ├── processlist.c
│ ├── processlist.h
│ ├── segmentinfo.asm
│ ├── threads.c
│ ├── threads.h
│ ├── ultimap.c
│ ├── ultimap.h
│ ├── ultimap2/
│ │ ├── apic.c
│ │ └── apic.h
│ ├── ultimap2.c
│ ├── ultimap2.h
│ ├── vmxhelper.c
│ ├── vmxhelper.h
│ ├── vmxoffload.c
│ └── vmxoffload.h
├── templates/
│ ├── CMakeLists.txt.tpl
│ ├── chamd.inf.tpl
│ ├── driver64.dat.tpl
│ └── makecat.cdf.tpl
└── wdk/
└── FindWDK.cmake
SYMBOL INDEX (314 symbols across 28 files)
FILE: scripts/context.js
class Context (line 7) | class Context {
method constructor (line 22) | constructor(driverName, distDir) {
method all (line 42) | async all() {
method purge (line 57) | async purge() {
method purgeDir (line 67) | static async purgeDir(dir) {
method generateCmakeFile (line 76) | async generateCmakeFile() {
method templateToFile (line 86) | async templateToFile(src, dist, vars) {
method compile (line 94) | async compile() {
method createMakeCatFile (line 108) | async createMakeCatFile() {
method makeCatFile (line 118) | async makeCatFile() {
method signDriver (line 124) | async signDriver() {
method execute (line 137) | async execute(cmd, cwd, params = []) {
method createDriverDatFile (line 157) | async createDriverDatFile() {
method install (line 167) | async install() {
method clearBuildDir (line 190) | async clearBuildDir() {
FILE: scripts/multibuilder.js
function getRandomWord (line 11) | async function getRandomWord() {
FILE: src/DBKDrvr.c
type ULONG (line 45) | typedef ULONG (NTUSERSETWINDOWSHOOKEX)(
type NTSTATUS (line 58) | typedef NTSTATUS (*ZWSUSPENDPROCESS)
type NTSTATUS (line 81) | typedef NTSTATUS(*PSRCTNR)(__in PCREATE_THREAD_NOTIFY_ROUTINE NotifyRout...
type NTSTATUS (line 84) | typedef NTSTATUS(*PSRLINR)(__in PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);
function hideme (line 92) | void hideme(PDRIVER_OBJECT DriverObject)
function testfunction (line 118) | int testfunction(int p1,int p2)
function VOID (line 133) | VOID TestPassive(UINT_PTR param)
function VOID (line 139) | VOID TestDPC(IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID ...
function NTSTATUS (line 148) | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
function NTSTATUS (line 540) | NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,
function NTSTATUS (line 581) | NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,
function UnloadDriver (line 595) | void UnloadDriver(PDRIVER_OBJECT DriverObject)
FILE: src/DBKFunc.c
function _enable (line 14) | void _enable() {}
function _disable (line 15) | void _disable() {}
function forEachCpuPassive (line 19) | void forEachCpuPassive(PF f, UINT_PTR param)
function forOneCpu (line 95) | void forOneCpu(CCHAR cpunr, PKDEFERRED_ROUTINE dpcfunction, PVOID Deferr...
function forEachCpu (line 112) | void forEachCpu(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredContext, ...
function forEachCpuAsync (line 171) | void forEachCpuAsync(PKDEFERRED_ROUTINE dpcfunction, PVOID DeferredConte...
function spinlock (line 231) | void spinlock(volatile LONG *lockvar)
function csEnter (line 247) | void csEnter(PcriticalSection CS)
function csLeave (line 268) | void csLeave(PcriticalSection CS)
function getCpuCount (line 287) | int getCpuCount(void)
function isPrefix (line 301) | int isPrefix(unsigned char b)
function UINT64 (line 325) | UINT64 getDR7(void)
function cpunr (line 331) | int cpunr(void)
function EFLAGS (line 340) | EFLAGS getEflags(void)
function UINT64 (line 347) | UINT64 readMSR(DWORD msr)
function setCR0 (line 352) | void setCR0(UINT64 newcr0)
function UINT64 (line 357) | UINT64 getCR0(void)
function UINT64 (line 362) | UINT64 getCR2(void)
function setCR3 (line 369) | void setCR3(UINT64 newCR3)
function UINT64 (line 374) | UINT64 getCR3(void)
function setCR4 (line 381) | void setCR4(UINT64 newcr4)
function UINT64 (line 386) | UINT64 getCR4(void)
function GetIDT (line 391) | void GetIDT(PIDT pIdt)
function UINT64 (line 414) | UINT64 getTSC(void)
FILE: src/DBKFunc.h
type VOID (line 20) | typedef VOID F(UINT_PTR param);
type F (line 21) | typedef F *PF;
type VOID (line 23) | typedef VOID PREDPC_CALLBACK(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID ...
type PREDPC_CALLBACK (line 25) | typedef PREDPC_CALLBACK *PPREDPC_CALLBACK;
type criticalSection (line 28) | typedef struct _criticalSection
type KNORMAL_ROUTINE (line 51) | typedef KNORMAL_ROUTINE *PKNORMAL_ROUTINE;
type KKERNEL_ROUTINE (line 67) | typedef KKERNEL_ROUTINE *PKKERNEL_ROUTINE;
type KRUNDOWN_ROUTINE (line 80) | typedef KRUNDOWN_ROUTINE *PKRUNDOWN_ROUTINE;
type _IRQL_requires_same_ (line 83) | typedef
type KENUM_ROUTINE (line 93) | typedef KENUM_ROUTINE *PKENUM_ROUTINE;
type KAPC_ENVIRONMENT (line 95) | typedef enum _KAPC_ENVIRONMENT {
type PTEStruct (line 162) | struct PTEStruct
type PTEStruct64 (line 183) | struct PTEStruct64
type Debugregs (line 205) | typedef struct tagDebugregs
type EFLAGS (line 218) | typedef struct
type DebugReg7 (line 250) | typedef struct tagDebugReg7
type DebugReg6 (line 283) | typedef struct DebugReg6
type GDT (line 307) | typedef struct tagGDT
FILE: src/IOPLDispatcher.c
type PCHAR (line 34) | typedef PCHAR (*GET_PROCESS_IMAGE_NAME) (PEPROCESS Process);
function mykapc2 (line 60) | void mykapc2(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalCont...
function nothing2 (line 81) | void nothing2(PVOID arg1, PVOID arg2, PVOID arg3)
function mykapc (line 87) | void mykapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalConte...
function nothing (line 126) | void nothing(PVOID arg1, PVOID arg2, PVOID arg3)
function CreateRemoteAPC (line 132) | void CreateRemoteAPC(ULONG threadid,PVOID addresstoexecute)
function OB_PREOP_CALLBACK_STATUS (line 174) | OB_PREOP_CALLBACK_STATUS ThreadPreCallback(PVOID RegistrationContext, PO...
function VOID (line 216) | VOID ThreadPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_IN...
function OB_PREOP_CALLBACK_STATUS (line 222) | OB_PREOP_CALLBACK_STATUS ProcessPreCallback(PVOID RegistrationContext, P...
function VOID (line 270) | VOID ProcessPostCallback(PVOID RegistrationContext, POB_POST_OPERATION_I...
function BOOL (line 277) | BOOL DispatchIoctlDBVM(IN PDEVICE_OBJECT DeviceObject, ULONG IoControlCo...
function NTSTATUS (line 306) | NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
FILE: src/debugger.c
type SavedStack (line 83) | typedef struct _SavedStack
function debugger_dr7_setGD (line 95) | void debugger_dr7_setGD(int state)
function debugger_dr0_setValue (line 105) | void debugger_dr0_setValue(UINT_PTR value)
function UINT_PTR (line 110) | UINT_PTR debugger_dr0_getValue(void)
function debugger_dr1_setValue (line 115) | void debugger_dr1_setValue(UINT_PTR value)
function UINT_PTR (line 120) | UINT_PTR debugger_dr1_getValue(void)
function debugger_dr2_setValue (line 125) | void debugger_dr2_setValue(UINT_PTR value)
function UINT_PTR (line 130) | UINT_PTR debugger_dr2_getValue(void)
function debugger_dr3_setValue (line 135) | void debugger_dr3_setValue(UINT_PTR value)
function UINT_PTR (line 140) | UINT_PTR debugger_dr3_getValue(void)
function debugger_dr6_setValue (line 145) | void debugger_dr6_setValue(UINT_PTR value)
function debugger_dr7_setValue (line 150) | void debugger_dr7_setValue(DebugReg7 value)
function debugger_dr7_setValueDword (line 156) | void debugger_dr7_setValueDword(UINT_PTR value)
function UINT_PTR (line 161) | UINT_PTR debugger_dr7_getValueDword(void) //I wonder why I couldn't just...
function DebugReg7 (line 167) | DebugReg7 debugger_dr7_getValue(void)
function UINT_PTR (line 173) | UINT_PTR debugger_dr6_getValueDword(void)
function DebugReg6 (line 178) | DebugReg6 debugger_dr6_getValue(void)
function debugger_touchDebugRegister (line 186) | void debugger_touchDebugRegister(UINT_PTR param)
function debugger_initialize (line 195) | void debugger_initialize(void)
function debugger_shutdown (line 219) | void debugger_shutdown(void)
function debugger_growstack (line 238) | void debugger_growstack()
function debugger_setInitialFakeState (line 283) | void debugger_setInitialFakeState(void)
function VOID (line 294) | VOID debugger_initHookForCurrentCPU_DPC(IN struct _KDPC *Dpc, IN PVOID ...
function debugger_removeHookForCurrentCPU (line 299) | int debugger_removeHookForCurrentCPU(UINT_PTR params)
function debugger_initHookForCurrentCPU (line 305) | int debugger_initHookForCurrentCPU(void)
function debugger_setStoreLBR (line 346) | void debugger_setStoreLBR(BOOL state)
function debugger_setGlobalDebugState (line 388) | int debugger_setGlobalDebugState(BOOL state)
function debugger_startDebugging (line 420) | int debugger_startDebugging(DWORD debuggedProcessID)
function debugger_stopDebugging (line 439) | int debugger_stopDebugging(void)
function debugger_unsetGDBreakpoint (line 470) | int debugger_unsetGDBreakpoint(int breakpointnr)
function debugger_setGDBreakpoint (line 477) | int debugger_setGDBreakpoint(int breakpointnr, ULONG_PTR Address, BreakT...
function NTSTATUS (line 490) | NTSTATUS debugger_waitForDebugEvent(ULONG timeout)
function NTSTATUS (line 513) | NTSTATUS debugger_continueDebugEvent(BOOL handled)
function UINT_PTR (line 526) | UINT_PTR *debugger_getLastStackPointer(void)
function NTSTATUS (line 533) | NTSTATUS debugger_getDebuggerState(PDebugStackState state)
function NTSTATUS (line 628) | NTSTATUS debugger_setDebuggerState(PDebugStackState state)
function breakpointHandler_kernel (line 706) | int breakpointHandler_kernel(UINT_PTR *stackpointer, UINT_PTR *currentde...
function interrupt1_handler (line 836) | int interrupt1_handler(UINT_PTR *stackpointer, UINT_PTR *currentdebugregs)
function interrupt1_centry (line 1494) | int interrupt1_centry(UINT_PTR *stackpointer) //code segment 8 has a 32-...
function interrupt1_asmentry (line 1762) | _declspec( naked ) void interrupt1_asmentry( void )
FILE: src/debugger.h
type DebugStackState (line 8) | typedef struct {
type BreakType (line 50) | typedef enum {bt_OnInstruction=0,bt_OnWrites=1, bt_OnIOAccess=2, bt_OnRe...
type BreakLength (line 51) | typedef enum {bl_1byte=0, bl_2byte=1, bl_8byte=2/*Only when in 64-bit*/,...
FILE: src/deepkernel.c
function BOOLEAN (line 10) | BOOLEAN MakeWritableKM(PVOID StartAddress,UINT_PTR size)
function BOOLEAN (line 58) | BOOLEAN MakeWritable(PVOID StartAddress,UINT_PTR size,BOOLEAN usecopyonw...
function BOOLEAN (line 102) | BOOLEAN CheckImageName(IN PUNICODE_STRING FullImageName, IN char* List,i...
function VOID (line 161) | VOID LoadImageNotifyRoutine(IN PUNICODE_STRING FullImageName, IN HANDLE...
FILE: src/interruptHook.c
function WORD (line 21) | WORD inthook_getOriginalCS(unsigned char intnr)
function ULONG_PTR (line 26) | ULONG_PTR inthook_getOriginalEIP(unsigned char intnr)
function inthook_isHooked (line 31) | int inthook_isHooked(unsigned char intnr)
function inthook_isDBVMHook (line 40) | int inthook_isDBVMHook(unsigned char intnr)
function inthook_UnhookInterrupt (line 45) | int inthook_UnhookInterrupt(unsigned char intnr)
function inthook_HookInterrupt (line 105) | int inthook_HookInterrupt(unsigned char intnr, int newCS, ULONG_PTR newE...
FILE: src/interruptHook.h
type stackindex (line 8) | typedef enum {si_eax=0, si_ebx=1, si_ecx=2, si_edx=3, si_esi=4, si_edi=5...
type stackindex (line 10) | typedef enum {si_gs=-12, si_fs=-11, si_es=-10, si_ds=-9, si_edi=-8, si_e...
type INT_VECTOR (line 16) | typedef struct tagINT_VECTOR
type IDT (line 39) | typedef struct tagIDT
FILE: src/memscan.c
function VirtualAddressToIndexes (line 20) | void VirtualAddressToIndexes(QWORD address, int *pml4index, int *pagedir...
function QWORD (line 41) | QWORD IndexesToVirtualAddress(int pml4index, int pagedirptrindex, int pa...
function VirtualAddressToPageEntries32 (line 74) | void VirtualAddressToPageEntries32(DWORD address, PPDE *pagedirentry, PP...
function VirtualAddressToPageEntries64 (line 92) | void VirtualAddressToPageEntries64(QWORD address, PPDPTE_PAE *pml4entry,...
function BOOLEAN (line 136) | BOOLEAN IsAddressSafe(UINT_PTR StartAddress)
function UINT_PTR (line 250) | UINT_PTR getPEThread(UINT_PTR threadid)
function BOOLEAN (line 267) | BOOLEAN WriteProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,D...
function BOOLEAN (line 381) | BOOLEAN ReadProcessMemory(DWORD PID,PEPROCESS PEProcess,PVOID Address,DW...
function UINT64 (line 476) | UINT64 getMaxPhysAddress(void)
function NTSTATUS (line 496) | NTSTATUS ReadPhysicalMemory(char *startaddress, UINT_PTR bytestoread, vo...
function UINT_PTR (line 608) | UINT_PTR SignExtend(UINT_PTR a)
function UINT_PTR (line 621) | UINT_PTR getPageTableBase()
type PTEStruct (line 661) | struct PTEStruct
function BOOL (line 662) | BOOL walkPagingLayout(PEPROCESS PEProcess, UINT_PTR MaxAddress, PRESENTP...
function CleanAccessedList (line 785) | void CleanAccessedList()
function StoreAccessedRanges (line 803) | void StoreAccessedRanges(UINT_PTR StartAddress, UINT_PTR EndAddress, str...
function enumAllAccessedPages (line 827) | int enumAllAccessedPages(PEPROCESS PEProcess)
function getAccessedPageList (line 846) | int getAccessedPageList(PPRANGE List, int ListSizeInBytes)
function MarkPageAsNotAccessed (line 875) | void MarkPageAsNotAccessed(UINT_PTR StartAddress, UINT_PTR EndAddress, s...
function NTSTATUS (line 880) | NTSTATUS markAllPagesAsNeverAccessed(PEPROCESS PEProcess)
function BOOLEAN (line 1280) | BOOLEAN GetMemoryRegionData(DWORD PID,PEPROCESS PEProcess, PVOID mempoin...
FILE: src/memscan.h
type ADDRESSENTRY (line 10) | typedef struct _ADDRESSENTRY {
type MEMREGION (line 17) | typedef struct _MEMREGION //only holds regions that are allowed
type MEMSCANOPTIONS (line 24) | typedef struct _MEMSCANOPTIONS
type SCANDATA (line 38) | typedef struct _SCANDATA {
type PRANGE (line 53) | typedef struct
type PENTRY (line 59) | typedef struct
FILE: src/noexceptions.c
function KeQueryActiveProcessorCount (line 17) | int KeQueryActiveProcessorCount(PVOID x)
function BOOL (line 34) | BOOL NoExceptions_Enter()
function NoExceptions_CopyMemory (line 158) | int NoExceptions_CopyMemory(PVOID Destination, PVOID Source, int size)
function NoExceptions_Leave (line 185) | void NoExceptions_Leave()
function NoExceptions_Cleanup (line 202) | void NoExceptions_Cleanup()
FILE: src/noexceptions.h
type CPUSTATE (line 15) | typedef struct
FILE: src/processlist.c
function RTL_GENERIC_COMPARE_RESULTS (line 17) | RTL_GENERIC_COMPARE_RESULTS NTAPI ProcessListCompare(__in struct _RTL_GE...
function PVOID (line 32) | PVOID NTAPI ProcessListAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in...
function VOID (line 41) | VOID NTAPI ProcessListDealloc(__in struct _RTL_GENERIC_TABLE *Table, __i...
function VOID (line 48) | VOID GetThreadData(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
function VOID (line 94) | VOID CreateThreadNotifyRoutine(IN HANDLE ProcessId,IN HANDLE ThreadId,...
function VOID (line 127) | VOID CreateProcessNotifyRoutine(IN HANDLE ParentId, IN HANDLE ProcessI...
function VOID (line 372) | VOID CreateProcessNotifyRoutineEx(IN HANDLE ParentId, IN HANDLE Proces...
function HANDLE (line 378) | HANDLE GetHandleForProcessID(IN HANDLE ProcessID)
function VOID (line 396) | VOID CleanProcessList()
FILE: src/processlist.h
type ThreadData (line 9) | struct ThreadData
type ProcessListData (line 20) | typedef struct
type ProcessData (line 29) | struct ProcessData
type ProcessEventdta (line 38) | typedef struct tagProcessEventData
type ThreadEventDta (line 54) | typedef struct tagThreadEventData
FILE: src/threads.c
type ThreadData (line 16) | struct ThreadData
type ProcessData (line 18) | struct ProcessData
type ThreadData (line 19) | struct ThreadData
function Ignore (line 40) | void Ignore(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalConte...
function SuspendThreadAPCRoutine (line 46) | void SuspendThreadAPCRoutine(PVOID arg1, PVOID arg2, PVOID arg3)
function DBKSuspendThread (line 65) | void DBKSuspendThread(ULONG ThreadID)
function DBKResumeThread (line 111) | void DBKResumeThread(ULONG ThreadID)
function DBKSuspendProcess (line 142) | void DBKSuspendProcess(ULONG ProcessID)
function DBKResumeProcess (line 206) | void DBKResumeProcess(ULONG ProcessID)
FILE: src/ultimap.c
type _DataBlock (line 37) | typedef struct
function ultimap_flushBuffers_all (line 77) | void ultimap_flushBuffers_all(UINT_PTR param)
function ultimap_flushBuffers (line 87) | void ultimap_flushBuffers(void)
function NTSTATUS (line 115) | NTSTATUS ultimap_continue(PULTIMAPDATAEVENT data)
function NTSTATUS (line 136) | NTSTATUS ultimap_waitForData(ULONG timeout, PULTIMAPDATAEVENT data)
function ultimap_cleanstate (line 218) | void ultimap_cleanstate()
function perfmon_interrupt_centry (line 223) | int perfmon_interrupt_centry(void)
function ultimap_pause (line 417) | void ultimap_pause(void)
function VOID (line 422) | VOID ultimap_resume_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, ...
function ultimap_resume (line 427) | void ultimap_resume(void)
function VOID (line 432) | VOID ultimap_disable_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext,...
function ultimap_disable (line 451) | void ultimap_disable(void)
function VOID (line 493) | VOID ultimap_setup_dpc(IN struct _KDPC *Dpc, IN PVOID DeferredContext, ...
function ultimapapc (line 585) | void ultimapapc(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalC...
function ultimapapcnormal (line 594) | void ultimapapcnormal(PVOID arg1, PVOID arg2, PVOID arg3)
function perfmon_hook (line 608) | void perfmon_hook(__in struct _KINTERRUPT *Interrupt, __in PVOID Service...
function NTSTATUS (line 653) | NTSTATUS ultimap(UINT64 cr3, UINT64 dbgctl_msr, int _DS_AREA_SIZE, BOOL ...
FILE: src/ultimap.h
type UINT64 (line 7) | typedef UINT64 QWORD;
type DS_AREA_MANAGEMENT64 (line 28) | typedef struct
type BTS (line 44) | typedef struct
type DS_AREA_MANAGEMENT64 (line 54) | typedef DS_AREA_MANAGEMENT64 DS_AREA_MANAGEMENT;
type PDS_AREA_MANAGEMENT64 (line 55) | typedef PDS_AREA_MANAGEMENT64 PDS_AREA_MANAGEMENT;
type ULTIMAPEVENT (line 61) | typedef struct
type ULTIMAPDATAEVENT (line 67) | typedef struct
FILE: src/ultimap2.c
function KeQueryMaximumProcessorCount (line 42) | unsigned int KeQueryMaximumProcessorCount()
type ProcessorInfo (line 63) | typedef struct
function suspendThread (line 115) | void suspendThread(PVOID StartContext)
function NTSTATUS (line 147) | NTSTATUS ultimap2_continue(int cpunr)
function NTSTATUS (line 179) | NTSTATUS ultimap2_waitForData(ULONG timeout, PULTIMAP2DATAEVENT data)
function createUltimap2OutputFile (line 263) | void createUltimap2OutputFile(int cpunr)
function WriteThreadForSpecificCPU (line 297) | void WriteThreadForSpecificCPU(PVOID StartContext)
function ultimap2_LockFile (line 408) | void ultimap2_LockFile(int cpunr)
function ultimap2_ReleaseFile (line 432) | void ultimap2_ReleaseFile(int cpunr)
function UINT64 (line 445) | UINT64 ultimap2_GetTraceFileSize()
function ultimap2_ResetTraceFileSize (line 460) | void ultimap2_ResetTraceFileSize()
function SwitchToPABuffer (line 471) | void SwitchToPABuffer(struct _KDPC *Dpc, PVOID DeferredContext, PVOID Sy...
function WaitForWriteToFinishAndSwapWriteBuffers (line 586) | void WaitForWriteToFinishAndSwapWriteBuffers(BOOL interruptedOnly)
function bufferWriterThread (line 607) | void bufferWriterThread(PVOID StartContext)
function NTSTATUS (line 713) | NTSTATUS ultimap2_flushBuffers()
function RTIT_DPC_Handler (line 758) | void RTIT_DPC_Handler(__in struct _KDPC *Dpc, __in_opt PVOID DeferredCon...
function PMI (line 766) | void PMI(__in struct _KINTERRUPT *Interrupt, __in PVOID ServiceContext)
function ultimap2_disable_dpc (line 816) | void ultimap2_disable_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOI...
function ultimap2_setup_dpc (line 848) | void ultimap2_setup_dpc(struct _KDPC *Dpc, PVOID DeferredContext, PVOID ...
function getToPAHeaderCount (line 974) | int getToPAHeaderCount(ULONG _BufferSize)
function getToPAHeaderSize (line 979) | int getToPAHeaderSize(ULONG _BufferSize)
function RTL_GENERIC_COMPARE_RESULTS (line 986) | RTL_GENERIC_COMPARE_RESULTS NTAPI ToPACompare(__in struct _RTL_GENERIC_T...
function PVOID (line 1001) | PVOID NTAPI ToPAAlloc(__in struct _RTL_GENERIC_TABLE *Table, __in CLONG ...
function VOID (line 1006) | VOID NTAPI ToPADealloc(__in struct _RTL_GENERIC_TABLE *Table, __in __drv...
function NTSTATUS (line 1297) | NTSTATUS ultimap2_pause()
function NTSTATUS (line 1314) | NTSTATUS ultimap2_resume()
function SetupUltimap2 (line 1326) | void SetupUltimap2(UINT32 PID, UINT32 BufferSize, WCHAR *Path, int range...
function UnregisterUltimapPMI (line 1533) | void UnregisterUltimapPMI()
function DisableUltimap2 (line 1562) | void DisableUltimap2(void)
FILE: src/ultimap2.h
type URANGE (line 26) | typedef struct
type RTIT_CTL (line 35) | typedef union {
type RTIT_STATUS (line 67) | typedef union {
type ToPA_ENTRY (line 80) | typedef union {
type ToPA_LOOKUP (line 95) | typedef struct{
type ULTIMAP2DATAEVENT (line 100) | typedef struct
type NTSTATUS (line 125) | typedef NTSTATUS(*PSSUSPENDPROCESS)(PEPROCESS p);
FILE: src/ultimap2/apic.c
function apic_clearPerfmon (line 18) | void apic_clearPerfmon()
function setup_APIC_BASE (line 42) | void setup_APIC_BASE(void)
function clean_APIC_BASE (line 62) | void clean_APIC_BASE(void)
FILE: src/ultimap2/apic.h
type UINT128 (line 7) | typedef struct {
type APIC (line 14) | typedef volatile struct {
FILE: src/vmxhelper.c
function vmx_hasredirectedint1 (line 50) | int vmx_hasredirectedint1()
function vmx_getversion (line 65) | unsigned int vmx_getversion()
function vmx_getRealCR0 (line 86) | unsigned int vmx_getRealCR0()
function UINT_PTR (line 102) | UINT_PTR vmx_getRealCR3()
function vmx_getRealCR4 (line 118) | unsigned int vmx_getRealCR4()
function vmx_redirect_interrupt1 (line 134) | unsigned int vmx_redirect_interrupt1(VMXInterruptRedirectType redirectty...
function vmx_redirect_interrupt3 (line 161) | unsigned int vmx_redirect_interrupt3(VMXInterruptRedirectType redirectty...
function vmx_redirect_interrupt14 (line 189) | unsigned int vmx_redirect_interrupt14(VMXInterruptRedirectType redirectt...
function vmx_register_cr3_callback (line 216) | unsigned int vmx_register_cr3_callback(unsigned int cs, unsigned int eip...
function vmx_exit_cr3_callback (line 244) | unsigned int vmx_exit_cr3_callback(unsigned int newcr3)
function vmx_watch_pagewrites (line 267) | unsigned int vmx_watch_pagewrites(UINT64 PhysicalAddress, int Size, int ...
function vmx_watch_pageaccess (line 306) | unsigned int vmx_watch_pageaccess(UINT64 PhysicalAddress, int Size, int ...
function vmx_watch_retreivelog (line 345) | unsigned int vmx_watch_retreivelog(int ID, PPageEventListDescriptor resu...
function vmx_watch_delete (line 376) | unsigned int vmx_watch_delete(int ID)
function vmx_cloak_activate (line 398) | unsigned int vmx_cloak_activate(QWORD physicalPage)
function vmx_cloak_deactivate (line 437) | unsigned int vmx_cloak_deactivate(QWORD physicalPage)
function vmx_cloak_readOriginal (line 457) | unsigned int vmx_cloak_readOriginal(QWORD physicalPage, void *destination)
function vmx_cloak_writeOriginal (line 482) | unsigned int vmx_cloak_writeOriginal(QWORD physicalPage, void *source)
function vmx_changeregonbp (line 507) | unsigned int vmx_changeregonbp(QWORD physicalAddress, CHANGEREGONBPINFO ...
function vmx_ultimap_getDebugInfo (line 540) | unsigned int vmx_ultimap_getDebugInfo(PULTIMAPDEBUGINFO debuginfo)
function vmx_ultimap (line 564) | unsigned int vmx_ultimap(UINT_PTR cr3towatch, UINT64 debugctl_value, voi...
function vmx_ultimap_disable (line 591) | unsigned int vmx_ultimap_disable()
function vmx_ultimap_pause (line 609) | unsigned int vmx_ultimap_pause()
function vmx_ultimap_resume (line 627) | unsigned int vmx_ultimap_resume()
function vmx_disable_dataPageFaults (line 645) | unsigned int vmx_disable_dataPageFaults()
function vmx_enable_dataPageFaults (line 663) | unsigned int vmx_enable_dataPageFaults()
function UINT_PTR (line 681) | UINT_PTR vmx_getLastSkippedPageFault()
function vmx_add_memory (line 699) | unsigned int vmx_add_memory(UINT64 *list, int count)
function vmx_causedCurrentDebugBreak (line 754) | int vmx_causedCurrentDebugBreak()
function vmx_init_dovmcall (line 772) | void vmx_init_dovmcall(int isIntel)
FILE: src/vmxhelper.h
type UINT64 (line 66) | typedef UINT64 QWORD;
type CHANGEREGONBPINFO (line 68) | typedef struct _CHANGEREGONBPINFO
type PageEventBasic (line 124) | typedef struct _pageevent_basic
type FXSAVE64 (line 158) | typedef struct _fxsave64
type PageEventExtended (line 231) | typedef struct _pageevent_extended
type PageEventBasicWithStack (line 237) | typedef struct _pageevent_basic_withstack
type PageEventExtendedWithStack (line 243) | typedef struct _pageevent_extended_withstack
type PageEventListDescriptor (line 250) | typedef struct _pageeventlistdescriptor
type VMXInterruptRedirectType (line 268) | typedef enum {virt_differentInterrupt=0, virt_emulateInterrupt=1} VMXInt...
type ULTIMAPDEBUGINFO (line 270) | typedef struct
FILE: src/vmxoffload.c
type INITVARS (line 35) | typedef struct _INITVARS
type OriginalState (line 48) | typedef struct
function cleanupDBVM (line 223) | void cleanupDBVM() {
function initializeDBVM (line 266) | void initializeDBVM(PCWSTR dbvmimgpath)
function vmxoffload_override (line 963) | void vmxoffload_override(CCHAR cpunr, PKDEFERRED_ROUTINE Dpc, PVOID Defe...
function __drv_maxIRQL (line 1002) | __drv_functionClass(KDEFERRED_ROUTINE)
FILE: src/vmxoffload.h
type DBVMOffloadMemInfo (line 17) | typedef struct _DBVMOffloadMemInfo
type _PTE (line 24) | struct _PTE
type _PDE (line 41) | struct _PDE
type _PDE2MB (line 58) | struct _PDE2MB
type PTE_PAE (line 77) | typedef struct _PTE_PAE
type PDE_PAE (line 95) | typedef struct _PDE_PAE
type _PDE2MB_PAE (line 113) | struct _PDE2MB_PAE
type _PDPTE_PAE (line 134) | struct _PDPTE_PAE
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (458K chars).
[
{
"path": ".editorconfig",
"chars": 130,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\ninsert_final_newli"
},
{
"path": ".gitignore",
"chars": 61,
"preview": "build\n.cache\n.env\nnode_modules\nsrc/CMakeLists.txt\ndist\ndists\n"
},
{
"path": "LICENSE",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2021 Dmitry Marov\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "README.md",
"chars": 9509,
"preview": "# Chamd (Chameleon DBK64)\n\n## Modified Driver Based on Cheat Engine DBK64\n\nThis project provides a modified version of t"
},
{
"path": "package.json",
"chars": 591,
"preview": "{\n \"type\": \"module\",\n \"dependencies\": {\n \"dotenv\": \"^10.0.0\",\n \"handlebars\": \"^4.7.7\"\n },\n \"scripts\": {\n \"a"
},
{
"path": "scripts/builder.js",
"chars": 962,
"preview": "import dotenv from 'dotenv';\nimport Context from './context.js';\nimport generateRandomName from './utils.js';\nimport pat"
},
{
"path": "scripts/context.js",
"chars": 6258,
"preview": "import path from 'path';\nimport fs from 'fs';\nimport handlebars from 'handlebars';\nimport { spawn } from 'child_process'"
},
{
"path": "scripts/multibuilder.js",
"chars": 1429,
"preview": "import Context from './context.js';\nimport generateRandomName from './utils.js';\nimport path from 'path';\nimport http fr"
},
{
"path": "scripts/paths.js",
"chars": 166,
"preview": "import path from 'path';\nimport { fileURLToPath } from 'url';\nconst __filename = fileURLToPath(import.meta.url);\n\nexport"
},
{
"path": "scripts/utils.js",
"chars": 302,
"preview": "export default (length) => {\n let result = '';\n const characters = 'abcdefghijklmnopqrstuvwxyz';\n const charact"
},
{
"path": "src/DBKDrvr.c",
"chars": 15368,
"preview": "#pragma warning( disable: 4100 4101 4103 4189)\n\n#include \"DBKFunc.h\"\n#include <ntifs.h>\n#include <windef.h>\n#include \"DB"
},
{
"path": "src/DBKDrvr.h",
"chars": 74,
"preview": "#ifndef DBKDRVR_H\n#define DBKDRVR_H\n\n\n\n#define dbkversion 2000027\n\n\n#endif"
},
{
"path": "src/DBKFunc.c",
"chars": 8640,
"preview": "#pragma warning( disable: 4103)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include \"DBKFunc.h\"\n\n/*\n#include \"vmxhelper.h\"\n#"
},
{
"path": "src/DBKFunc.h",
"chars": 9563,
"preview": "#ifndef DBKFUNC_H\n#define DBKFUNC_H\n\n#pragma warning( disable: 4214 )\n\n#include <ntifs.h>\n#include <ntstrsafe.h>\n\n#inclu"
},
{
"path": "src/IOPLDispatcher.c",
"chars": 58597,
"preview": "#pragma warning( disable: 4100 4101 4103 4189)\n\n\n#include \"IOPLDispatcher.h\"\n#include \"DBKFunc.h\"\n#include \"DBKDrvr.h\"\n\n"
},
{
"path": "src/IOPLDispatcher.h",
"chars": 12977,
"preview": "#ifndef IOPLDISPACTCHER_H\n#define IOPLDISPACTCHER_H\n\n#include \"DBKfunc.h\"\n\n#define IOCTL_UNKNOWN_BASE\t\t\t\t\tFILE_DEVICE_UN"
},
{
"path": "src/amd64/dbkfunca.asm",
"chars": 1613,
"preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n;I should pro"
},
{
"path": "src/amd64/debuggera.asm",
"chars": 5109,
"preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK "
},
{
"path": "src/amd64/noexceptionsa.asm",
"chars": 1137,
"preview": "_TEXT SEGMENT 'CODE'\n\nPUBLIC NoException14\nNoException14:\n\n;Security cookies sucks, so getjmp/longjmp are not usable\n;So"
},
{
"path": "src/amd64/ultimapa.asm",
"chars": 4884,
"preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nCALLBACK "
},
{
"path": "src/amd64/vmxhelpera.asm",
"chars": 520,
"preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\n\n;vmcall: rd"
},
{
"path": "src/amd64/vmxoffloada.asm",
"chars": 5477,
"preview": ";RCX: 1st integer argument\n;RDX: 2nd integer argument\n;R8: 3rd integer argument\n;R9: 4th integer argument\n\nGDTDesc\tSTRUC"
},
{
"path": "src/debugger.c",
"chars": 49540,
"preview": "/*\ndebugger.c:\nThis unit will handle all debugging related code, from hooking, to handling interrupts\n\ntodo: this whole "
},
{
"path": "src/debugger.h",
"chars": 1820,
"preview": "#ifndef DEBUGGER_H\n#define DEBUGGER_H\n\n#include <ntifs.h>\n#include <windef.h>\n\n#pragma pack(4)\ntypedef struct {\n\tUINT64 "
},
{
"path": "src/deepkernel.c",
"chars": 3591,
"preview": "#pragma warning( disable: 4100 4103)\n\n#include \"deepkernel.h\"\n#include \"DBKFunc.h\"\n#include <windef.h>\n\n#include \"vmxhel"
},
{
"path": "src/deepkernel.h",
"chars": 426,
"preview": "#include <ntifs.h>\n#include <windef.h>\n\n\nVOID LoadImageNotifyRoutine(IN PUNICODE_STRING FullImageName, IN HANDLE Proce"
},
{
"path": "src/extradefines.h",
"chars": 587,
"preview": "/*#define HDESK\t\t\t\t\t\t\tULONG\n#define HWND\t\t\t\t\t\t\tULONG\n#define DWORD\t\t\t\t\t\t\tULONG\n#define WORD\t\t\t\t\t\t\tUSHORT\n#define BYTE\t\t\t"
},
{
"path": "src/extraimports.h",
"chars": 166,
"preview": "NTSYSAPI\nBOOLEAN\nKeAddSystemServiceTable(\n IN PULONG_PTR Base,\n IN PULONG Count OPTIONAL,\n IN ULONG Limit,\n "
},
{
"path": "src/interruptHook.c",
"chars": 4861,
"preview": "#pragma warning( disable: 4103)\n\n#include \"ntifs.h\"\n#include <windef.h>\n\n#include \"DBKFunc.h\"\n#include \"vmxhelper.h\"\n\n#i"
},
{
"path": "src/interruptHook.h",
"chars": 2075,
"preview": "#ifndef INTERRUPTHOOK_H\n#define INTERRUPTHOOK_H\n\n#include <windef.h>\n\n//assuming the standard interrupt hook routine is "
},
{
"path": "src/memscan.c",
"chars": 30132,
"preview": "#pragma warning( disable: 4100 4103 4146 4213)\n\n#include \"ntifs.h\"\n#include <windef.h>\n#ifdef CETC\n#include \"tdiwrapper."
},
{
"path": "src/memscan.h",
"chars": 2966,
"preview": "#include <windef.h>\n\n#ifdef AMD64\n#define PAGETABLEBASE 0xfffff68000000000ULL\n//win10 1607 it's random\n#else\n#define PAG"
},
{
"path": "src/noexceptions.c",
"chars": 4409,
"preview": "#include \"noexceptions.h\"\n\nint MaxCPUCount;\n\n\nPCPUSTATE cpustate = NULL;\n\n#ifdef AMD64\nextern void NoException14(void); "
},
{
"path": "src/noexceptions.h",
"chars": 672,
"preview": "#ifndef NOEXCEPTIONS_H\n#define NOEXCEPTIONS_H\n\n/*\nWill be responsible for temporarily switching out the IDT of the curen"
},
{
"path": "src/processlist.c",
"chars": 10405,
"preview": "#pragma warning( disable: 4100 4103 4706)\n\n#include \"ntifs.h\"\n#include \"processlist.h\"\n#include \"threads.h\"\n#include \"me"
},
{
"path": "src/processlist.h",
"chars": 1624,
"preview": "#include <ntifs.h>\n#include \"extradefines.h\"\n#include \"extraimports.h\"\n\n\nVOID CreateProcessNotifyRoutine(IN HANDLE Paren"
},
{
"path": "src/segmentinfo.asm",
"chars": 570,
"preview": "_TEXT SEGMENT 'CODE'\n\nPUBLIC _getAccessRights@8\t\t\t\t\t\t\t\t\t\t\n_getAccessRights@8:\n push ebp\n mov ebp,esp\n \n push ecx\n m"
},
{
"path": "src/threads.c",
"chars": 5546,
"preview": "#pragma warning( disable: 4100 4103)\n\n#include \"threads.h\"\n#include \"processlist.h\"\n#include \"memscan.h\"\n\n/*\nNTSTATUS NT"
},
{
"path": "src/threads.h",
"chars": 548,
"preview": "#ifndef THREADS_H\n#define THREADS_H\n\n\n#include <ntifs.h>\n#include <windef.h>\n#include \"DBKFunc.h\"\n\n\nvoid Ignore(PKAPC Ap"
},
{
"path": "src/ultimap.c",
"chars": 17822,
"preview": "/*\nUltimap implements the recording of all the branches in the target process\nRequires dbvm for process selection\n*/\n\n#p"
},
{
"path": "src/ultimap.h",
"chars": 2075,
"preview": "#ifndef ULTIMAP_H\n#define ULTIMAP_H\n\n#include <ntifs.h>\n#include <windef.h>\n\ntypedef UINT64 QWORD;\n\n#pragma pack(push)\n#"
},
{
"path": "src/ultimap2/apic.c",
"chars": 1849,
"preview": "#include <ntifs.h>\n\n#include \"apic.h\"\n#include <ntddk.h>\n#include \"..\\DBKFunc.h\"\n\n\n#define MSR_IA32_APICBASE "
},
{
"path": "src/ultimap2/apic.h",
"chars": 1159,
"preview": "#ifndef apic_h\n#define apic_h\n\n#include <ntddk.h>\n#include <windef.h>\n\ntypedef struct {\n\tDWORD a;\n\tDWORD b;\n\tDWORD c;\n\tD"
},
{
"path": "src/ultimap2.c",
"chars": 41425,
"preview": "#pragma warning( disable: 4100 4706)\n\n#include <ntifs.h>\n#include <ntddk.h>\n#include <minwindef.h>\n#include <wdm.h>\n#inc"
},
{
"path": "src/ultimap2.h",
"chars": 2920,
"preview": "#ifndef ULTIMAP2_H\n#define ULTIMAP2_H\n\n#include <ntifs.h>\n\n//MSR's\n#define IA32_PERF_GLOBAL_STATUS\t\t0x38e \n#define IA32"
},
{
"path": "src/vmxhelper.c",
"chars": 20743,
"preview": "#pragma warning( disable: 4100 4103 4213)\n#include <ntifs.h>\n#include <ntddk.h>\n#include <windef.h>\n#include \"vmxhelper."
},
{
"path": "src/vmxhelper.h",
"chars": 7348,
"preview": "#ifndef VMXHELPER_H\n#define VMXHELPER_H\n\n#pragma warning( disable: 4200)\n\n#define VMCALL_GETVERSION 0\n#define VMCALL_CHA"
},
{
"path": "src/vmxoffload.c",
"chars": 28174,
"preview": "/*\nsets up all the needed data structures \ncopies dbvm into physical memory\njumps into dbvm's os entry point\n\n*/\n#pragma"
},
{
"path": "src/vmxoffload.h",
"chars": 5802,
"preview": "#ifndef VMXOFFLOAD_H\n#define VMXOFFLOAD_H\n\nvoid cleanupDBVM();\nvoid initializeDBVM(PCWSTR dbvmimgpath);\nvoid vmxoffload("
},
{
"path": "templates/CMakeLists.txt.tpl",
"chars": 1806,
"preview": "cmake_minimum_required(VERSION 3.18.0)\nproject({{DRIVER_NAME}} VERSION 1.0.0)\n\nenable_language(C ASM_MASM)\n\nlist(APPEND "
},
{
"path": "templates/chamd.inf.tpl",
"chars": 2410,
"preview": ";\n; {{DRIVER_NAME}}.inf\n;\n\n[Version]\nSignature=\"$WINDOWS NT$\"\nClass=Sample ; TODO: edit Class\nClassGuid={78A1C341-4539-1"
},
{
"path": "templates/driver64.dat.tpl",
"chars": 66,
"preview": "fgfgfgfh\nfghcghfhg\nfvfghfbg\n{{DRIVER_NAME}}.sys\n76543210\nfedcba98\n"
},
{
"path": "templates/makecat.cdf.tpl",
"chars": 169,
"preview": "[CatalogHeader]\nName={{DRIVER_NAME}}.cat\nPublicVersion=0x0000001\nEncodingType=0x00010001\nCATATTR1=0x10010001:OSAttr:2:6."
},
{
"path": "wdk/FindWDK.cmake",
"chars": 8507,
"preview": "# Redistribution and use is allowed under the OSI-approved 3-clause BSD license.\n# Copyright (c) 2018 Sergey Podobry (se"
}
]
About this extraction
This page contains the full source code of the dmarov/chamd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (397.1 KB), approximately 126.1k tokens, and a symbol index with 314 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.