mirror of
https://github.com/HyperDbg/HyperDbg
synced 2026-08-15 06:29:09 -04:00
Merge branch 'dev' into feat/intel-pt-integration
This commit is contained in:
commit
b38b43eef9
298 changed files with 16255 additions and 5213 deletions
51
CHANGELOG.md
51
CHANGELOG.md
|
|
@ -4,7 +4,16 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.19.0.0] - 2026-XX-XX
|
||||
## [0.20.0.0] - 2026-XX-XX
|
||||
New release of the HyperDbg Debugger.
|
||||
|
||||
### Added
|
||||
-
|
||||
|
||||
### Changed
|
||||
-
|
||||
|
||||
## [0.19.0.0-beta] - 2026-06-10
|
||||
New release of the HyperDbg Debugger.
|
||||
|
||||
### Added
|
||||
|
|
@ -13,12 +22,26 @@ New release of the HyperDbg Debugger.
|
|||
- Added Legacy LBR support to the HyperTrace module
|
||||
- Added Architectural LBR support to the HyperTrace module
|
||||
- Added the '!lbr' command for performing different Last Branch Record (LBR) operations ([link](https://docs.hyperdbg.org/commands/extension-commands/lbr))
|
||||
- Added the '!lbrdump' command for dumping saved Last Branch Record (LBR) entries ([link](https://docs.hyperdbg.org/commands/extension-commands/lbrdmp))
|
||||
- Added the '!lbrdump' command for dumping saved Last Branch Record (LBR) entries ([link](https://docs.hyperdbg.org/commands/extension-commands/lbrdump))
|
||||
- Added **lbr_save()** and **lbr_print()** functions in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_save))([link](https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_print))
|
||||
- Added mock application for compiling SDK for Linux
|
||||
- Add '!help' alias for the '.help' command
|
||||
- Added '!help' alias for the '.help' command
|
||||
- Added 'vm' alias for the 'load' command ([link](https://docs.hyperdbg.org/commands/debugging-commands/load))
|
||||
- Added **lbr_check()** and **lbr_restore()** functions in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_check))([link](https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_restore))
|
||||
- Added **lbr_restore_by_filter(filter)** function in the script engine ([link](https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_restore_by_filter))
|
||||
- Added the 'kd' module in the 'load' command ([link](https://docs.hyperdbg.org/commands/debugging-commands/load))
|
||||
- Added the 'trace' module in the 'load' command ([link](https://docs.hyperdbg.org/commands/debugging-commands/load))
|
||||
- Exported SDK API for detecting CPU vendors
|
||||
- Initial codes for the HyperTrace project by using Intel Processor Trace (PT), thanks to [@masoudrahimi01](https://github.com/masoudrahimi01) ([link](https://github.com/HyperDbg/HyperDbg/pull/589))
|
||||
- Exported SDK APIs for loading and unloading the 'kd' and the 'trace' modules
|
||||
- Exported SDK APIs for starting (installing) the 'kd' driver
|
||||
- Exported SDK APIs for loading/unloading all modules
|
||||
- Added tests for checking PE parser in 'hyperdbg-test' project
|
||||
- Added example for loading HyperDbg in VMI mode directly from libhyperdbg
|
||||
- Fix action cleanup list removal in debugger events ([link](https://github.com/HyperDbg/HyperDbg/pull/601))
|
||||
- Added transparent-mode evade mask selection thanks to [@jtaw5649](https://github.com/jtaw5649) ([link](https://github.com/HyperDbg/HyperDbg/pull/602))
|
||||
- Added synthetic MSR handling thanks to [@Idov31](https://github.com/Idov31) ([link](https://github.com/HyperDbg/HyperDbg/pull/605))
|
||||
- Added use of relative RSDS fixture paths when loading PDB symbols, thanks to [@jtaw5649](https://github.com/jtaw5649) ([link](https://github.com/HyperDbg/HyperDbg/pull/607))
|
||||
|
||||
### Changed
|
||||
- Fix the problem of not applying the EAX index in the CPUID event extension command ([link](https://docs.hyperdbg.org/commands/extension-commands/cpuid#parameters))
|
||||
|
|
@ -27,13 +50,25 @@ New release of the HyperDbg Debugger.
|
|||
- VMX instructions are ported to platform-independent files to support Linux
|
||||
- All CPU-related intrinsic instructions are ported to platform-independent files to support Linux
|
||||
- HyperDbg SDK now compiles on Linux (GCC) for both user-mode and kernel-mode
|
||||
- Fix the 'wrmsr' command IOCTL checks by receiving output the buffer ([link](https://docs.hyperdbg.org/commands/debugging-commands/wrmsr))
|
||||
- Fix the 'wrmsr' command IOCTL checks by receiving output in the buffer ([link](https://docs.hyperdbg.org/commands/debugging-commands/wrmsr))
|
||||
- Extensive refactoring of code base (doxygen, variables, function names)
|
||||
- Building certain modules on Linux and fixing CMake files thanks to [@maxraulea](https://github.com/maxraulea) ([link](https://github.com/HyperDbg/HyperDbg/pull/592))
|
||||
- Fix the '!hide' command's HyperEvade activation guard thanks to [@jtaw5649](https://github.com/jtaw5649) ([link](https://github.com/HyperDbg/HyperDbg/pull/593))
|
||||
- Fix synchronous debugger device IOCTL handles thanks to [@jtaw5649](https://github.com/jtaw5649) ([link](https://github.com/HyperDbg/HyperDbg/pull/595))
|
||||
- PE parser ('.pe' command) now supports richer DOS/NT/COFF/optional-header output, section bounds checking, data directory reporting, import/export parsing, TLS/debug/PDB/load-config metadata, overlay reporting, and malformed metadata warnings thanks to [@jtaw5649](https://github.com/jtaw5649) ([link](https://github.com/HyperDbg/HyperDbg/pull/598))([link](https://docs.hyperdbg.org/commands/meta-commands/.pe))
|
||||
- Building the script engine module on Linux (GCC) thanks to [@maxraulea](https://github.com/maxraulea) ([link](https://github.com/HyperDbg/HyperDbg/pull/596))
|
||||
- The pool manager moved from 'hyperhv' to 'hyperkd'
|
||||
- The 'load' command could load all modules using a new alias 'load all' ([link](https://docs.hyperdbg.org/commands/debugging-commands/load))
|
||||
- The 'unload' command could remove all modules using two new aliases 'unload all' and 'unload remove all' ([link](https://docs.hyperdbg.org/commands/debugging-commands/unload))
|
||||
- Change device handle checks with module loading status checks for IOCTLs ([link](https://github.com/HyperDbg/HyperDbg/pull/610))
|
||||
- Fix standard callbacks for the VMM module ([link](https://github.com/HyperDbg/HyperDbg/pull/610))
|
||||
- Fix race condition bug within the pool manager
|
||||
|
||||
## [0.18.1.0] - 2026-04-09
|
||||
New release of the HyperDbg Debugger.
|
||||
|
||||
### Added
|
||||
- Hypertrace now works with HyperDbg VMM ([link](https://github.com/HyperDbg/HyperDbg/pull/568))
|
||||
- HyperTrace now works with HyperDbg VMM ([link](https://github.com/HyperDbg/HyperDbg/pull/568))
|
||||
- Progress on implementing Last Branch Recode (LBR) ([link](https://github.com/HyperDbg/HyperDbg/commit/1dd73675e9cd78737e013ffb35bc712f385f387e))
|
||||
- Applying LBR registers on the VMCS instead of the DEBUGCTL MSR ([link](https://github.com/HyperDbg/HyperDbg/commit/15f8b3cca15448acd18d7e198740464a19ce4fe2))
|
||||
|
||||
|
|
@ -41,7 +76,7 @@ New release of the HyperDbg Debugger.
|
|||
- Fix the problem of the '!epthook' not finding the PML1 entry ([link](https://docs.hyperdbg.org/commands/extension-commands/epthook))
|
||||
- Fix the problem of getting the PML1 entry of the target address on Intel Core Ultra processors (#567) ([link](https://github.com/HyperDbg/HyperDbg/issues/567))
|
||||
- Fix the '.clang-format' formatting error
|
||||
- Restructure of the hypertrace project
|
||||
- Restructure of the HyperTrace project
|
||||
- Add starting structure for supporting Intel Processor Trace (PT)
|
||||
|
||||
## [0.18.0.0] - 2026-02-16
|
||||
|
|
@ -49,8 +84,8 @@ New release of the HyperDbg Debugger.
|
|||
|
||||
### Added
|
||||
- Script engine now supports writing libraries using the '#include' keyword thanks to [@xmaple555](https://github.com/xmaple555) ([link](https://docs.hyperdbg.org/commands/scripting-language/casting-and-inclusion))([link](https://github.com/HyperDbg/HyperDbg/issues/557))([link](https://github.com/HyperDbg/HyperDbg/pull/561))
|
||||
- Initial codes for the hypertrace project by using Intel Last Branch Record (LBR) and Branch Trace Store (BTS) thanks to [@harimishal1](https://github.com/harimishal1) ([link](https://github.com/HyperDbg/HyperDbg/tree/master/hyperdbg/hypertrace))
|
||||
- The hypertrace project is now linked to the hyperkd
|
||||
- Initial codes for the HyperTrace project by using Intel Last Branch Record (LBR) and Branch Trace Store (BTS) thanks to [@harimishal1](https://github.com/harimishal1) ([link](https://github.com/HyperDbg/HyperDbg/tree/master/hyperdbg/hypertrace))
|
||||
- The HyperTrace project is now linked to the hyperkd
|
||||
- Initial efforts to port HyperDbg to Linux have started thanks to [@Alish14](https://github.com/Alish14) ([link](https://github.com/HyperDbg/HyperDbg/pull/563))
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
|
|
@ -14,18 +14,16 @@ Please make sure to create a [discussion](https://github.com/orgs/HyperDbg/discu
|
|||
- Troubleshooting problems with running on VirtualBox's nested virtualization.
|
||||
- Supporting KDNET (sending data over the network).
|
||||
- Enhancing HyperDbg's [Transparent Mode](https://docs.hyperdbg.org/using-hyperdbg/prerequisites/operation-modes#transparent-mode). These features should be added as an extension to the [HyperEvade](https://www.vusec.net/projects/hyperevade/) project (e.g., by bypassing [al-khaser](https://github.com/LordNoteworthy/al-khaser) and similar anti-debugging and anti-hypervisor projects).
|
||||
- Enhancing and adding more features to the ['.pe'](https://docs.hyperdbg.org/commands/meta-commands/.pe) command.
|
||||
- Adding HyperDbg to the system startup using UEFI.
|
||||
- Adding routines to activate and use Last Branch Record (LBR) and Branch Trace Store (BTS) | (In progress).
|
||||
- Creating a QT-based GUI.
|
||||
- Creating a SoftICE-style GUI.
|
||||
- Supporting nested-virtualization on HyperDbg itself.
|
||||
- Protecting HyperDbg code and memory from modification using VT-x capabilities.
|
||||
- Adding support for the Intel Processor Trace (PT) and event command for detecting coverage.
|
||||
- Adding support for the Intel Processor Trace (PT) and event command for detecting coverage | (In progress).
|
||||
- Creating a wrapper that automatically interprets the [HyperDbg SDK](https://github.com/HyperDbg/HyperDbg/tree/master/hyperdbg/include/SDK) to GO, RUST, C#, Python, etc.
|
||||
- Creating syntax highlighting for dslang for different IDEs (VSCode, VIM, etc.).
|
||||
- Building HyperDbg using LLVM clang.
|
||||
- Helping us start supporting HyperDbg on Linux (discussion needed).
|
||||
- Helping us start supporting HyperDbg on Linux (discussion needed) | (In progress).
|
||||
- Helping us start supporting HyperDbg on AMD processors (discussion needed).
|
||||
- Adding digital (FPGA) modules to the hwdbg hardware debugger.
|
||||
- Creating a [ret-sync](https://github.com/bootleg/ret-sync) module for HyperDbg.
|
||||
|
|
@ -44,6 +42,8 @@ Please make sure to create a [discussion](https://github.com/orgs/HyperDbg/discu
|
|||
- Adding support for [Hardware Performance Counters (HPC)](https://en.wikipedia.org/wiki/Hardware_performance_counter).
|
||||
- Any other interesting tasks you might find!
|
||||
|
||||
- ~~Enhancing and adding more features to the ['.pe'](https://docs.hyperdbg.org/commands/meta-commands/.pe) command.~~ Added: [<a href="https://docs.hyperdbg.org/commands/meta-commands/.pe" target="_blank">link</a>][<a href="https://github.com/HyperDbg/HyperDbg/pull/598" target="_blank">link</a>]
|
||||
- ~~Adding routines to activate and use Last Branch Record (LBR) and Branch Trace Store (BTS).~~ Added: [<a href="https://docs.hyperdbg.org/commands/extension-commands/lbr" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/extension-commands/lbrdump" target="_blank">link</a>]
|
||||
- ~~Creating commands to inspect and read details of PCIe devices.~~ Added: [<a href="https://docs.hyperdbg.org/commands/extension-commands/pcitree" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/extension-commands/pcicam" target="_blank">link</a>]
|
||||
- ~~Mitigating the anti-hypervisor method described [here](https://howtohypervise.blogspot.com/2019/01/a-common-missight-in-most-hypervisors.html).~~ [[Fixed](https://github.com/HyperDbg/HyperDbg/pull/497)]
|
||||
- ~~Fixing the problem with [XSETBV instruction freezing](https://github.com/HyperDbg/HyperDbg/issues/429).~~ [[Fixed](https://github.com/HyperDbg/HyperDbg/pull/491)]
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -73,19 +73,7 @@ In case you use one of **HyperDbg**'s components in your work, please consider c
|
|||
|
||||
<summary><b>Other paper built upon HyperDbg...</b></summary>
|
||||
|
||||
|
||||
**2. [The Reversing Machine: Reconstructing Memory Assumptions](https://arxiv.org/pdf/2405.00298)** [[arXiv](https://arxiv.org/abs/2405.00298)]
|
||||
|
||||
```
|
||||
@article{karvandi2024reversing,
|
||||
title={The Reversing Machine: Reconstructing Memory Assumptions},
|
||||
author={Karvandi, Mohammad Sina and Meghdadizanjani, Soroush and Arasteh, Sima and Monfared, Saleh Khalaj and Fallah, Mohammad K and Gorgin, Saeid and Lee, Jeong-A and van der Kouwe, Erik},
|
||||
journal={arXiv preprint arXiv:2405.00298},
|
||||
year={2024}
|
||||
}
|
||||
```
|
||||
|
||||
**3. [hwdbg: Debugging Hardware Like Software (EuroSec'25)](https://dl.acm.org/doi/abs/10.1145/3722041.3723101)** [[PDF](https://dl.acm.org/doi/pdf/10.1145/3722041.3723101)]
|
||||
**2. [hwdbg: Debugging Hardware Like Software (EuroSec'25)](https://dl.acm.org/doi/abs/10.1145/3722041.3723101)** [[PDF](https://dl.acm.org/doi/pdf/10.1145/3722041.3723101)]
|
||||
|
||||
```
|
||||
@inproceedings{karvandi2025hwdbg,
|
||||
|
|
@ -97,7 +85,7 @@ In case you use one of **HyperDbg**'s components in your work, please consider c
|
|||
}
|
||||
```
|
||||
|
||||
**4. [HyperEvade: Countering Anti-Debugging Techniques and Enhancing Transparency in Nested Virtualization using HyperDbg (DEBT'25)](https://www.jot.fm/contents/issue_2026_01/a8.html)** [[PDF](https://www.jot.fm/issues/issue_2026_01/a8.pdf)]
|
||||
**3. [HyperEvade: Countering Anti-Debugging Techniques and Enhancing Transparency in Nested Virtualization using HyperDbg (DEBT'25)](https://www.jot.fm/contents/issue_2026_01/a8.html)** [[PDF](https://www.jot.fm/issues/issue_2026_01/a8.pdf)]
|
||||
|
||||
```
|
||||
@article{ruytenberg2026hyperevade,
|
||||
|
|
@ -112,7 +100,7 @@ In case you use one of **HyperDbg**'s components in your work, please consider c
|
|||
}
|
||||
```
|
||||
|
||||
**5. [Digital Hole: Bypassing Commercial Audio DRM Solutions with DReaMcatcher (EuroSys'26)](https://dl.acm.org/doi/abs/10.1145/3767295.3803583)** [[PDF](https://dl.acm.org/doi/pdf/10.1145/3767295.3803583)]
|
||||
**4. [Digital Hole: Bypassing Commercial Audio DRM Solutions with DReaMcatcher (EuroSys'26)](https://dl.acm.org/doi/abs/10.1145/3767295.3803583)** [[PDF](https://dl.acm.org/doi/pdf/10.1145/3767295.3803583)]
|
||||
|
||||
```
|
||||
@inproceedings{ruytenberg2026digital,
|
||||
|
|
@ -124,6 +112,18 @@ In case you use one of **HyperDbg**'s components in your work, please consider c
|
|||
}
|
||||
```
|
||||
|
||||
**5. [TRM: An Efficient Hypervisor-Based Framework For Malware Analysis and Memory Reconstruction (AsiaCCS'26)](https://dl.acm.org/doi/10.1145/3779208.3785293)** [[PDF](https://dl.acm.org/doi/pdf/10.1145/3779208.3785293)]
|
||||
|
||||
```
|
||||
@inproceedings{karvandi2026trm,
|
||||
title={TRM: An Efficient Hypervisor-Based Framework For Malware Analysis and Memory Reconstruction},
|
||||
author={Karvandi, Mohammad Sina and Meghdadizanjani, Soroush and Arasteh, Sima and Monfared, Saleh Khalaj and Fallah, Mohammad K and Gorgin, Saeid and Lee, Jeong-A and Slowinska, Asia and van der Kouwe, Erik},
|
||||
booktitle={Proceedings of the ACM Asia Conference on Computer and Communications Security},
|
||||
pages={68--82},
|
||||
year={2026}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
You can also read [this article](https://research.hyperdbg.org/debugger/kernel-debugger-design/) as it describes the overall architecture, technical difficulties, design decisions, and internals of HyperDbg Debugger, [this article](https://research.hyperdbg.org/vmm/transparency/) about our efforts on vm-exit transparency, [this article](https://research.hyperdbg.org/debugger/chasing-bugs/) about chasing bugs within hypervisors, and [this article](https://research.hyperdbg.org/debugger/gaining-insights/) about new reverse engineering techniques introduced in HyperDbg. More articles, posts, and resources are available at the **[awesome](https://github.com/HyperDbg/awesome)** repo, and in addition, the **[slides](https://github.com/HyperDbg/slides)** repo provides presentation slides for further reference.
|
||||
|
|
@ -178,7 +178,8 @@ You can also read [this article](https://research.hyperdbg.org/debugger/kernel-d
|
|||
* Attaching to the User-mode Process and Preventing Execution [<a href="https://docs.hyperdbg.org/commands/meta-commands/.attach" target="_blank">link</a>]
|
||||
* Intercepting Execution of XSETBV Instructions [<a href="https://docs.hyperdbg.org/commands/extension-commands/xsetbv" target="_blank">link</a>]
|
||||
* Writing Library Script Files [<a href="https://docs.hyperdbg.org/commands/scripting-language/casting-and-inclusion" target="_blank">link</a>]
|
||||
* Tracing Branches using Last Branch Record [<a href="https://docs.hyperdbg.org/commands/extension-commands/lbr" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/extension-commands/lbrdump" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr_print" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr_save" target="_blank">link</a>]
|
||||
* Enhanced Portable Executable (PE) Parser [<a href="https://docs.hyperdbg.org/commands/meta-commands/.pe" target="_blank">link</a>]
|
||||
* Tracing Branches using Last Branch Record (LBR) [<a href="https://docs.hyperdbg.org/commands/extension-commands/lbr" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/extension-commands/lbrdump" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_print" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_save" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_check" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_restore" target="_blank">link</a>][<a href="https://docs.hyperdbg.org/commands/scripting-language/functions/tracing/lbr/lbr_restore_by_filter" target="_blank">link</a>]
|
||||
|
||||
## How does it work?
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ DriverEntry(
|
|||
//
|
||||
DbgPrint("HyperDbg's device and major functions are loaded");
|
||||
|
||||
|
||||
ASSERT(NT_SUCCESS(Ntstatus));
|
||||
return Ntstatus;
|
||||
}
|
||||
|
|
@ -105,7 +106,7 @@ DrvUnload(PDRIVER_OBJECT DriverObject)
|
|||
//
|
||||
// Unloading VMM and Debugger
|
||||
//
|
||||
LoaderUninitializeLogTracer();
|
||||
LoaderUninitLogTracer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
//
|
||||
PoolManagerCheckAndPerformAllocationAndDeallocation();
|
||||
|
||||
if (g_AllowIoctlFromUsermode)
|
||||
if (g_VmmInitialized)
|
||||
{
|
||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ LoaderInitVmmAndReversingMachine()
|
|||
//
|
||||
// Allow to server IOCTL
|
||||
//
|
||||
g_AllowIoctlFromUsermode = TRUE;
|
||||
g_VmmInitialized = TRUE;
|
||||
|
||||
//
|
||||
// Fill the callbacks for the message tracer
|
||||
|
|
@ -90,7 +90,7 @@ LoaderInitVmmAndReversingMachine()
|
|||
//
|
||||
// Not loaded
|
||||
//
|
||||
g_AllowIoctlFromUsermode = FALSE;
|
||||
g_VmmInitialized = FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -101,7 +101,7 @@ LoaderInitVmmAndReversingMachine()
|
|||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitializeLogTracer()
|
||||
LoaderUninitLogTracer()
|
||||
{
|
||||
LogDebugInfo("Unloading HyperDbg's debugger...\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
//////////////////////////////////////////////////
|
||||
|
||||
VOID
|
||||
LoaderUninitializeLogTracer();
|
||||
LoaderUninitLogTracer();
|
||||
|
||||
BOOLEAN
|
||||
LoaderInitVmmAndReversingMachine();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
BOOLEAN g_HandleInUse;
|
||||
|
||||
/**
|
||||
* @brief Determines whether the clients are allowed to send IOCTL to the drive or not
|
||||
* @brief Shows whether the VMM is initialized or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_AllowIoctlFromUsermode;
|
||||
BOOLEAN g_VmmInitialized;
|
||||
|
|
@ -16,8 +16,8 @@ static UINT8 * g_Code = NULL;
|
|||
static int
|
||||
ShowMessages(const char * Text)
|
||||
{
|
||||
printf("%s", Text);
|
||||
return 0;
|
||||
printf("%s", Text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ set(CMAKE_CXX_STANDARD 23)
|
|||
enable_language(ASM_MASM)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
if(LINUX)
|
||||
|
||||
message(STATUS "Building on Linux")
|
||||
elseif(WIN32)
|
||||
message(STATUS "Building on Windows")
|
||||
find_package(WDK REQUIRED)
|
||||
|
||||
include_directories(
|
||||
|
|
@ -48,23 +52,30 @@ target_link_libraries(hyperhv Zycore Zydis)
|
|||
add_subdirectory(hyperkd)
|
||||
target_link_libraries(hyperkd hyperlog hyperhv kdserial)
|
||||
|
||||
endif()
|
||||
|
||||
add_subdirectory(dependencies/pdbex/Source)
|
||||
#add_subdirectory(dependencies/pdbex/Source)
|
||||
|
||||
add_subdirectory(symbol-parser)
|
||||
target_link_libraries(symbol-parser pdbex)
|
||||
#add_subdirectory(symbol-parser)
|
||||
#target_link_libraries(symbol-parser pdbex)
|
||||
|
||||
#target_link_libraries(script-engine symbol-parser)
|
||||
|
||||
#add_subdirectory(hyperdbg-test)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
||||
#add_subdirectory(symbol-parser)
|
||||
#target_link_libraries(symbol-parser pdbex)
|
||||
|
||||
#add_subdirectory(script-engine)
|
||||
#target_link_libraries(script-engine symbol-parser)
|
||||
|
||||
add_subdirectory(script-engine)
|
||||
target_link_libraries(script-engine symbol-parser)
|
||||
|
||||
link_directories(libraries/zydis/user libraries/keystone/release-lib)
|
||||
add_subdirectory(libhyperdbg)
|
||||
target_link_libraries(libhyperdbg Zycore Zydis script-engine keystone)
|
||||
|
||||
|
||||
add_subdirectory(hyperdbg-test)
|
||||
|
||||
add_subdirectory(hyperdbg-cli)
|
||||
target_link_libraries(hyperdbg-cli libhyperdbg)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Code generated by Visual Studio kit, DO NOT EDIT.
|
||||
set(SourceFiles
|
||||
"hyperdbg-cli.cpp"
|
||||
"../include/platform/user/header/Environment.h"
|
||||
"../include/platform/general/header/Environment.h"
|
||||
)
|
||||
include_directories(
|
||||
"../include"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @file hyperdbg-cli.cpp
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Main HyperDbg Cli source coede
|
||||
* @brief Main HyperDbg Cli source code
|
||||
* @details
|
||||
* @version 0.1
|
||||
* @date 2020-04-11
|
||||
|
|
@ -10,11 +10,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <Windows.h>
|
||||
#ifdef _WIN32
|
||||
# include <Windows.h>
|
||||
# include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <conio.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
|
||||
#include "SDK/HyperDbgSdk.h"
|
||||
#include "SDK/imports/user/HyperDbgLibImports.h"
|
||||
|
|
@ -24,9 +28,9 @@ using namespace std;
|
|||
/**
|
||||
* @brief CLI main function
|
||||
*
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @return int
|
||||
* @param argc the number of arguments
|
||||
* @param argv the arguments
|
||||
* @return int zero on success, 1 on failure
|
||||
*/
|
||||
int
|
||||
main(int argc, char * argv[])
|
||||
|
|
@ -38,12 +42,19 @@ main(int argc, char * argv[])
|
|||
//
|
||||
// Set console output code page to UTF-8
|
||||
//
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
|
||||
printf("HyperDbg Debugger [version: %s, build: %s]\n", CompleteVersion, BuildVersion);
|
||||
printf("Please visit https://docs.hyperdbg.org for more information...\n");
|
||||
printf("HyperDbg is released under the GNU Public License v3 (GPLv3).\n\n");
|
||||
|
||||
#if BETA_VERSION == 1
|
||||
printf("Notice: This is a beta release and may contain bugs or stability issues. ");
|
||||
printf("If you encounter any problems, please report them and consider using the previous stable release.\n\n");
|
||||
#endif
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
//
|
||||
|
|
@ -74,7 +85,7 @@ main(int argc, char * argv[])
|
|||
//
|
||||
reset = TRUE;
|
||||
|
||||
GetMultiLinecCommand:
|
||||
GetMultiLineCommand:
|
||||
|
||||
string temp_command = "";
|
||||
|
||||
|
|
@ -115,7 +126,7 @@ main(int argc, char * argv[])
|
|||
//
|
||||
// Get next command
|
||||
//
|
||||
goto GetMultiLinecCommand;
|
||||
goto GetMultiLineCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,23 +15,23 @@ namespace fs = std::filesystem;
|
|||
|
||||
/**
|
||||
* @brief function to comment each line by adding ';' at the start
|
||||
* @param content
|
||||
* @param Content the content to comment out
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
std::string
|
||||
commentContent(const std::string & content)
|
||||
CommentContent(const std::string & Content)
|
||||
{
|
||||
std::istringstream iss(content);
|
||||
std::string line;
|
||||
std::string commentedContent;
|
||||
std::istringstream Iss(Content);
|
||||
std::string Line;
|
||||
std::string CommentedContent;
|
||||
|
||||
while (std::getline(iss, line))
|
||||
while (std::getline(Iss, Line))
|
||||
{
|
||||
commentedContent += line + "\n; ";
|
||||
CommentedContent += Line + "\n; ";
|
||||
}
|
||||
|
||||
return commentedContent;
|
||||
return CommentedContent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -42,9 +42,9 @@ commentContent(const std::string & content)
|
|||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
||||
ReadDirectoryAndCreateHwdbgTestCases(const CHAR * HwdbgScriptTestCasesPath)
|
||||
{
|
||||
CHAR tempFilePath[MAX_PATH] = {0};
|
||||
CHAR TempFilePath[MAX_PATH] = {0};
|
||||
|
||||
//
|
||||
// Iterate through the directory
|
||||
|
|
@ -61,7 +61,7 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
//
|
||||
// Get the file path
|
||||
//
|
||||
std::string filePath = entry.path().string();
|
||||
std::string FilePath = entry.path().string();
|
||||
|
||||
//
|
||||
// Output the file name
|
||||
|
|
@ -71,10 +71,10 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
//
|
||||
// Open the file and read its contents
|
||||
//
|
||||
std::ifstream file(filePath);
|
||||
if (file.is_open())
|
||||
std::ifstream File(FilePath);
|
||||
if (File.is_open())
|
||||
{
|
||||
std::string content((std::istreambuf_iterator<char>(file)),
|
||||
std::string Content((std::istreambuf_iterator<char>(File)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
//
|
||||
|
|
@ -84,19 +84,19 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
|
||||
// std::cout << content << std::endl;
|
||||
|
||||
std::string compiled_version_file_path = HWDBG_SCRIPT_TEST_CASE_COMPILED_SCRIPTS_DIRECTORY "\\" + entry.path().filename().string() + ".hex.txt";
|
||||
std::string CompiledVersionFilePath = HWDBG_SCRIPT_TEST_CASE_COMPILED_SCRIPTS_DIRECTORY "\\" + entry.path().filename().string() + ".hex.txt";
|
||||
|
||||
//
|
||||
// Run the test case command
|
||||
//
|
||||
printf("File content: %s\n", content.c_str());
|
||||
printf("File content: %s\n", Content.c_str());
|
||||
|
||||
if (!hwdbg_script_run_script(content.c_str(),
|
||||
if (!hwdbg_script_run_script(Content.c_str(),
|
||||
HWDBG_TEST_READ_INSTANCE_INFO_PATH,
|
||||
compiled_version_file_path.c_str(),
|
||||
CompiledVersionFilePath.c_str(),
|
||||
DEFAULT_INITIAL_BRAM_BUFFER_SIZE))
|
||||
{
|
||||
std::cout << "[-] Could not run the script: " << filePath << std::endl;
|
||||
std::cout << "[-] Could not run the script: " << FilePath << std::endl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
//
|
||||
// Parse the hwdbg compiled test cases from the file
|
||||
//
|
||||
if (!hyperdbg_u_setup_path_for_filename(compiled_version_file_path.c_str(), tempFilePath, MAX_PATH, FALSE))
|
||||
if (!hyperdbg_u_setup_path_for_filename(CompiledVersionFilePath.c_str(), TempFilePath, MAX_PATH, FALSE))
|
||||
{
|
||||
//
|
||||
// Error could not find the test case files
|
||||
|
|
@ -116,48 +116,48 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
std::ifstream compiledFile(tempFilePath);
|
||||
if (compiledFile.is_open())
|
||||
std::ifstream CompiledFile(TempFilePath);
|
||||
if (CompiledFile.is_open())
|
||||
{
|
||||
//
|
||||
// Read the existing content of the compiled file
|
||||
//
|
||||
std::string compiledContent((std::istreambuf_iterator<char>(compiledFile)),
|
||||
std::string CompiledContent((std::istreambuf_iterator<char>(CompiledFile)),
|
||||
std::istreambuf_iterator<char>());
|
||||
compiledFile.close(); // Close the file after reading
|
||||
CompiledFile.close(); // Close the file after reading
|
||||
|
||||
//
|
||||
// Comment the content
|
||||
//
|
||||
std::string commentedContent = commentContent(content);
|
||||
std::string CommentedContent = CommentContent(Content);
|
||||
|
||||
//
|
||||
// Concatenate the new content (prepend the original content)
|
||||
//
|
||||
std::string newContent = "; The raw script file is available at: " HWDBG_SCRIPT_TEST_CASE_COMPILED_SCRIPTS_DIRECTORY "\\" +
|
||||
std::string NewContent = "; The raw script file is available at: " HWDBG_SCRIPT_TEST_CASE_COMPILED_SCRIPTS_DIRECTORY "\\" +
|
||||
entry.path().filename().string() +
|
||||
"\n;\n; !hw script " +
|
||||
commentedContent +
|
||||
CommentedContent +
|
||||
"\n" +
|
||||
compiledContent;
|
||||
CompiledContent;
|
||||
|
||||
//
|
||||
// Write the new content back to the file (overwriting it)
|
||||
//
|
||||
std::ofstream compiledFileOut(tempFilePath);
|
||||
if (compiledFileOut.is_open())
|
||||
std::ofstream CompiledFileOut(TempFilePath);
|
||||
if (CompiledFileOut.is_open())
|
||||
{
|
||||
compiledFileOut << newContent;
|
||||
compiledFileOut.close();
|
||||
CompiledFileOut << NewContent;
|
||||
CompiledFileOut.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Could not open file for writing: " << compiled_version_file_path << std::endl;
|
||||
std::cerr << "Could not open file for writing: " << CompiledVersionFilePath << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Could not open compiled file: " << compiled_version_file_path << std::endl;
|
||||
std::cerr << "Could not open compiled file: " << CompiledVersionFilePath << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "--------------------------------------------" << std::endl;
|
||||
|
|
@ -165,11 +165,11 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
//
|
||||
// Close the file
|
||||
//
|
||||
file.close();
|
||||
File.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Could not open file: " << filePath << std::endl;
|
||||
std::cerr << "Could not open file: " << FilePath << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -194,8 +194,8 @@ ReadDirectoryAndCreateHwdbgTestCases(const char * HwdbgScriptTestCasesPath)
|
|||
BOOLEAN
|
||||
HwdbgTestCreateTestCases()
|
||||
{
|
||||
int testNum = 0;
|
||||
CHAR dirPath[MAX_PATH] = {0};
|
||||
INT32 TestNum = 0;
|
||||
CHAR dirPath[MAX_PATH] = {0};
|
||||
|
||||
//
|
||||
// Parse the hwdbg test cases from the file
|
||||
|
|
|
|||
|
|
@ -43,10 +43,25 @@ main(int argc, char * argv[])
|
|||
printf("\n[x] The main command parser test cases failed\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES))
|
||||
else if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_PE_PARSER))
|
||||
{
|
||||
//
|
||||
// # Test case 2
|
||||
// Testing PE parser helpers
|
||||
//
|
||||
if (TestPeParser())
|
||||
{
|
||||
printf("\n[*] The PE parser test cases passed successfully\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n[x] The PE parser test cases failed\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_SCRIPT_SEMANTIC_TEST_CASES))
|
||||
{
|
||||
//
|
||||
// # Test case 3
|
||||
// Testing script semantic test cases
|
||||
//
|
||||
if (TestSemanticScripts())
|
||||
|
|
@ -58,6 +73,21 @@ main(int argc, char * argv[])
|
|||
printf("\n[x] The script semantic test cases failed\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], TEST_CASE_PARAMETER_FOR_CODEVIEW_RSDS_PARSER))
|
||||
{
|
||||
//
|
||||
// # Test case 4
|
||||
// Testing CodeView RSDS parser helpers
|
||||
//
|
||||
if (TestCodeViewRsdsParser())
|
||||
{
|
||||
printf("\n[*] The CodeView RSDS parser test cases passed successfully\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n[x] The CodeView RSDS parser test cases failed\n");
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[1], TEST_HWDBG_FUNCTIONALITIES))
|
||||
{
|
||||
//
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#include "pch.h"
|
||||
|
||||
/**
|
||||
* @brief Create a named pipe server
|
||||
* @brief Connect and transfer buffers via named pipe
|
||||
*
|
||||
* @return UINT32
|
||||
*/
|
||||
|
|
@ -204,14 +204,14 @@ NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize, UINT32 Input
|
|||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeServerWaitForClientConntection(HANDLE PipeHandle)
|
||||
NamedPipeServerWaitForClientConnection(HANDLE PipeHandle)
|
||||
{
|
||||
//
|
||||
// Wait for the client to connect
|
||||
//
|
||||
BOOL bClientConnected = ConnectNamedPipe(PipeHandle, NULL);
|
||||
BOOLEAN ClientConnected = ConnectNamedPipe(PipeHandle, NULL);
|
||||
|
||||
if (FALSE == bClientConnected)
|
||||
if (FALSE == ClientConnected)
|
||||
{
|
||||
printf("err, occurred while connecting to the client (%x)\n",
|
||||
GetLastError());
|
||||
|
|
@ -234,9 +234,9 @@ NamedPipeServerWaitForClientConntection(HANDLE PipeHandle)
|
|||
* @return UINT32
|
||||
*/
|
||||
UINT32
|
||||
NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int MaximumReadBufferLength)
|
||||
NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT32 MaximumReadBufferLength)
|
||||
{
|
||||
DWORD cbBytes;
|
||||
DWORD BytesTransferred;
|
||||
|
||||
//
|
||||
// We are connected to the client.
|
||||
|
|
@ -248,13 +248,13 @@ NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int Max
|
|||
//
|
||||
// Read client message
|
||||
//
|
||||
BOOL bResult = ReadFile(PipeHandle, // handle to pipe
|
||||
BufferToSave, // buffer to receive data
|
||||
MaximumReadBufferLength, // size of buffer
|
||||
&cbBytes, // number of bytes read
|
||||
NULL); // not overlapped I/O
|
||||
BOOLEAN Result = ReadFile(PipeHandle, // handle to pipe
|
||||
BufferToSave, // buffer to receive data
|
||||
MaximumReadBufferLength, // size of buffer
|
||||
&BytesTransferred, // number of bytes read
|
||||
NULL); // not overlapped I/O
|
||||
|
||||
if ((!bResult) || (0 == cbBytes))
|
||||
if ((!Result) || (0 == BytesTransferred))
|
||||
{
|
||||
printf("err, occurred while reading from the client (%x)\n",
|
||||
GetLastError());
|
||||
|
|
@ -265,29 +265,37 @@ NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int Max
|
|||
//
|
||||
// Number of bytes that the client sends to us
|
||||
//
|
||||
return cbBytes;
|
||||
return BytesTransferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a message to the client over named pipe
|
||||
*
|
||||
* @param PipeHandle Handle of the named pipe
|
||||
* @param BufferToSend Buffer containing the message to send
|
||||
* @param BufferSize Size of the buffer to send
|
||||
* @return BOOLEAN TRUE if successful, FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeServerSendMessageToClient(HANDLE PipeHandle,
|
||||
char * BufferToSend,
|
||||
int BufferSize)
|
||||
CHAR * BufferToSend,
|
||||
INT32 BufferSize)
|
||||
{
|
||||
DWORD cbBytes;
|
||||
DWORD BytesTransferred;
|
||||
|
||||
//
|
||||
// Reply to client
|
||||
//
|
||||
BOOLEAN bResult =
|
||||
WriteFile(PipeHandle, // handle to pipe
|
||||
BufferToSend, // buffer to write from
|
||||
BufferSize, // number of bytes to write, include the NULL
|
||||
&cbBytes, // number of bytes written
|
||||
NULL); // not overlapped I/O
|
||||
BOOLEAN Result =
|
||||
WriteFile(PipeHandle, // handle to pipe
|
||||
BufferToSend, // buffer to write from
|
||||
BufferSize, // number of bytes to write, include the NULL
|
||||
&BytesTransferred, // number of bytes written
|
||||
NULL); // not overlapped I/O
|
||||
|
||||
if ((!bResult) || (BufferSize != cbBytes))
|
||||
if ((!Result) || (BufferSize != (INT32)BytesTransferred))
|
||||
{
|
||||
printf("Error occurred while writing to the client (%x)\n",
|
||||
printf("err, occurred while writing to the client (%x)\n",
|
||||
GetLastError());
|
||||
CloseHandle(PipeHandle);
|
||||
return FALSE;
|
||||
|
|
@ -363,15 +371,15 @@ NamedPipeClientCreatePipe(LPCSTR PipeName)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief send client message over named pipe
|
||||
* @brief Send client message over named pipe
|
||||
*
|
||||
* @param PipeHandle
|
||||
* @param BufferToSend
|
||||
* @param BufferSize
|
||||
* @return BOOLEAN
|
||||
* @param PipeHandle Handle of the named pipe
|
||||
* @param BufferToSend Buffer containing the message to send
|
||||
* @param BufferSize Size of the buffer to send
|
||||
* @return BOOLEAN TRUE if successful, FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSize)
|
||||
NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT32 BufferSize)
|
||||
{
|
||||
//
|
||||
// We are done connecting to the server pipe,
|
||||
|
|
@ -380,19 +388,19 @@ NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSiz
|
|||
// on handle - hPipe
|
||||
//
|
||||
|
||||
DWORD cbBytes;
|
||||
DWORD BytesTransferred;
|
||||
|
||||
//
|
||||
// Send the message to server
|
||||
//
|
||||
BOOL bResult =
|
||||
WriteFile(PipeHandle, // handle to pipe
|
||||
BufferToSend, // buffer to write from
|
||||
BufferSize, // number of bytes to write, include the NULL
|
||||
&cbBytes, // number of bytes written
|
||||
NULL); // not overlapped I/O
|
||||
BOOLEAN Result =
|
||||
WriteFile(PipeHandle, // handle to pipe
|
||||
BufferToSend, // buffer to write from
|
||||
BufferSize, // number of bytes to write, include the NULL
|
||||
&BytesTransferred, // number of bytes written
|
||||
NULL); // not overlapped I/O
|
||||
|
||||
if ((!bResult) || (BufferSize != cbBytes))
|
||||
if ((!Result) || (BufferSize != (INT32)BytesTransferred))
|
||||
{
|
||||
printf("err, occurred while writing to the server (%x)\n",
|
||||
GetLastError());
|
||||
|
|
@ -410,35 +418,40 @@ NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSiz
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read the count of read buffer
|
||||
//
|
||||
/**
|
||||
* @brief Read a message from the server over named pipe
|
||||
*
|
||||
* @param PipeHandle Handle of the named pipe
|
||||
* @param BufferToRead Buffer to store the received message
|
||||
* @param MaximumSizeOfBuffer Maximum size of the receive buffer
|
||||
* @return UINT32 number of bytes read, or 0 on failure
|
||||
*/
|
||||
UINT32
|
||||
NamedPipeClientReadMessage(HANDLE PipeHandle, char * BufferToRead, int MaximumSizeOfBuffer)
|
||||
NamedPipeClientReadMessage(HANDLE PipeHandle, CHAR * BufferToRead, INT32 MaximumSizeOfBuffer)
|
||||
{
|
||||
DWORD cbBytes;
|
||||
DWORD BytesTransferred;
|
||||
|
||||
//
|
||||
// Read server response
|
||||
//
|
||||
BOOL bResult = ReadFile(PipeHandle, // handle to pipe
|
||||
BufferToRead, // buffer to receive data
|
||||
MaximumSizeOfBuffer, // size of buffer
|
||||
&cbBytes, // number of bytes read
|
||||
NULL); // not overlapped I/O
|
||||
BOOLEAN Result = ReadFile(PipeHandle, // handle to pipe
|
||||
BufferToRead, // buffer to receive data
|
||||
MaximumSizeOfBuffer, // size of buffer
|
||||
&BytesTransferred, // number of bytes read
|
||||
NULL); // not overlapped I/O
|
||||
|
||||
if ((!bResult) || (0 == cbBytes))
|
||||
if ((!Result) || (0 == BytesTransferred))
|
||||
{
|
||||
printf("err, occurred while reading from the server (%x)\n",
|
||||
GetLastError());
|
||||
CloseHandle(PipeHandle);
|
||||
return NULL; // Error
|
||||
return 0; // Error
|
||||
}
|
||||
|
||||
//
|
||||
// Success
|
||||
//
|
||||
return cbBytes;
|
||||
return BytesTransferred;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -460,19 +473,19 @@ NamedPipeClientClosePipe(HANDLE PipeHandle)
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief and example of how to use named pipe as a server
|
||||
* @brief An example of how to use named pipe as a server
|
||||
*
|
||||
* @return int
|
||||
* @return INT32
|
||||
*/
|
||||
int
|
||||
INT32
|
||||
NamedPipeServerExample()
|
||||
{
|
||||
HANDLE PipeHandle;
|
||||
BOOLEAN SentMessageResult;
|
||||
UINT32 ReadBytes;
|
||||
const int BufferSize = 1024;
|
||||
char BufferToRead[BufferSize] = {0};
|
||||
char BufferToSend[BufferSize] = "test message to send from server !!!";
|
||||
HANDLE PipeHandle;
|
||||
BOOLEAN SentMessageResult;
|
||||
UINT32 ReadBytes;
|
||||
const INT32 BufferSize = 1024;
|
||||
CHAR BufferToRead[BufferSize] = {0};
|
||||
CHAR BufferToSend[BufferSize] = "test message to send from server !!!";
|
||||
|
||||
printf("create name pipe\n");
|
||||
PipeHandle = NamedPipeServerCreatePipe("\\\\.\\Pipe\\HyperDbgTests",
|
||||
|
|
@ -489,7 +502,7 @@ NamedPipeServerExample()
|
|||
printf("success!\n");
|
||||
printf("wait for the client connection\n");
|
||||
|
||||
if (!NamedPipeServerWaitForClientConntection(PipeHandle))
|
||||
if (!NamedPipeServerWaitForClientConnection(PipeHandle))
|
||||
{
|
||||
//
|
||||
// Error in connection
|
||||
|
|
@ -516,7 +529,7 @@ NamedPipeServerExample()
|
|||
SentMessageResult = NamedPipeServerSendMessageToClient(
|
||||
PipeHandle,
|
||||
BufferToSend,
|
||||
(int)strlen(BufferToSend) + 1);
|
||||
(INT32)strlen(BufferToSend) + 1);
|
||||
|
||||
if (!SentMessageResult)
|
||||
{
|
||||
|
|
@ -538,20 +551,19 @@ NamedPipeServerExample()
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief and example of how to use named pipe as a client
|
||||
* @brief An example of how to use named pipe as a client
|
||||
*
|
||||
* @return int
|
||||
* @return INT32
|
||||
*/
|
||||
int
|
||||
INT32
|
||||
NamedPipeClientExample()
|
||||
{
|
||||
HANDLE PipeHandle;
|
||||
BOOLEAN SentMessageResult;
|
||||
UINT32 ReadBytes;
|
||||
const int BufferSize = 1024;
|
||||
char Buffer[BufferSize] = "test message to send from client !!!";
|
||||
|
||||
PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests");
|
||||
HANDLE PipeHandle;
|
||||
BOOLEAN SentMessageResult;
|
||||
UINT32 ReadBytes;
|
||||
const INT32 BufferSize = 1024;
|
||||
CHAR Buffer[BufferSize] = "test message to send from client !!!";
|
||||
PipeHandle = NamedPipeClientCreatePipe("\\\\.\\Pipe\\HyperDbgTests");
|
||||
|
||||
if (!PipeHandle)
|
||||
{
|
||||
|
|
@ -562,7 +574,7 @@ NamedPipeClientExample()
|
|||
}
|
||||
|
||||
SentMessageResult =
|
||||
NamedPipeClientSendMessage(PipeHandle, Buffer, (int)strlen(Buffer) + 1);
|
||||
NamedPipeClientSendMessage(PipeHandle, Buffer, (INT32)strlen(Buffer) + 1);
|
||||
|
||||
if (!SentMessageResult)
|
||||
{
|
||||
|
|
|
|||
932
hyperdbg/hyperdbg-test/code/tests/test-codeview-rsds-parser.cpp
Normal file
932
hyperdbg/hyperdbg-test/code/tests/test-codeview-rsds-parser.cpp
Normal file
|
|
@ -0,0 +1,932 @@
|
|||
/**
|
||||
* @file test-codeview-rsds-parser.cpp
|
||||
* @author jtaw5649
|
||||
* @brief Test cases for CodeView RSDS parser helpers
|
||||
* @details
|
||||
* @version 0.19
|
||||
* @date 2026-06-02
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
static constexpr SIZE_T RsdsFixtureSize = 0x600;
|
||||
static constexpr LONG RsdsPeHeaderOffset = 0x80;
|
||||
static constexpr DWORD RsdsSectionRva = 0x1000;
|
||||
static constexpr DWORD RsdsSectionRaw = 0x200;
|
||||
static constexpr DWORD RsdsSectionSize = 0x300;
|
||||
static constexpr DWORD RsdsDebugDirectoryRva = 0x1100;
|
||||
static constexpr DWORD RsdsDebugDirectoryRaw = 0x300;
|
||||
static constexpr DWORD RsdsPayloadRva = 0x1140;
|
||||
static constexpr DWORD RsdsPayloadRaw = 0x340;
|
||||
static constexpr DWORD RsdsLoadedDebugRva = 0x280;
|
||||
static constexpr DWORD RsdsLoadedPayloadRva = 0x2c0;
|
||||
static constexpr SIZE_T RsdsHighLoadedSize = 0x22000;
|
||||
static constexpr DWORD RsdsHighLoadedDebugRva = 0x20000;
|
||||
static constexpr DWORD RsdsHighLoadedPayloadRva = 0x20100;
|
||||
static constexpr DWORD RsdsBogusRawPointer = 0xfffff000;
|
||||
|
||||
static const GUID RsdsGuid64 = {0x67452301, 0xab89, 0xefcd, {0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe}};
|
||||
static const GUID RsdsGuid32 = {0x01234567, 0x89ab, 0xcdef, {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}};
|
||||
static const GUID RsdsGuidMulti = {0xaabbccdd, 0xeeff, 0x1122, {0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa}};
|
||||
|
||||
/**
|
||||
* @brief Calculates the file offset of the optional header based on the PE header offset
|
||||
*
|
||||
* @return SIZE_T The file offset of the optional header
|
||||
*/
|
||||
static SIZE_T
|
||||
RsdsOptionalHeaderOffset()
|
||||
{
|
||||
return RsdsPeHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the file offset of the first section header based on the optional header size
|
||||
*
|
||||
* @param OptionalHeaderSize The size of the optional header, obtained from the IMAGE_FILE_HEADER
|
||||
*
|
||||
* @return SIZE_T The file offset of the first section header
|
||||
*/
|
||||
static SIZE_T
|
||||
RsdsSectionHeaderOffset(SIZE_T OptionalHeaderSize)
|
||||
{
|
||||
return RsdsOptionalHeaderOffset() + OptionalHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds a minimal PE image in the provided buffer with the specified architecture
|
||||
*
|
||||
* @param Buffer The buffer to write the PE image into. Must be at least RsdsFixtureSize bytes
|
||||
* @param Is32Bit Whether to build a 32-bit (true) or 64-bit (false) PE image
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsBuildMinimalPe(BYTE * Buffer, BOOLEAN Is32Bit)
|
||||
{
|
||||
ZeroMemory(Buffer, RsdsFixtureSize);
|
||||
|
||||
IMAGE_DOS_HEADER * DosHeader = (IMAGE_DOS_HEADER *)Buffer;
|
||||
DosHeader->e_magic = IMAGE_DOS_SIGNATURE;
|
||||
DosHeader->e_lfanew = RsdsPeHeaderOffset;
|
||||
|
||||
BYTE * NtHeaders = Buffer + RsdsPeHeaderOffset;
|
||||
*(DWORD *)NtHeaders = IMAGE_NT_SIGNATURE;
|
||||
|
||||
IMAGE_FILE_HEADER * FileHeader = (IMAGE_FILE_HEADER *)(NtHeaders + sizeof(DWORD));
|
||||
FileHeader->Machine = Is32Bit ? IMAGE_FILE_MACHINE_I386 : IMAGE_FILE_MACHINE_AMD64;
|
||||
FileHeader->NumberOfSections = 1;
|
||||
FileHeader->SizeOfOptionalHeader = Is32Bit ? sizeof(IMAGE_OPTIONAL_HEADER32) : sizeof(IMAGE_OPTIONAL_HEADER64);
|
||||
|
||||
BYTE * OptionalHeader = NtHeaders + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
if (Is32Bit)
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER32 * OptionalHeader32 = (IMAGE_OPTIONAL_HEADER32 *)OptionalHeader;
|
||||
OptionalHeader32->Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
|
||||
OptionalHeader32->SizeOfHeaders = 0x200;
|
||||
OptionalHeader32->SizeOfImage = 0x2000;
|
||||
OptionalHeader32->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
|
||||
OptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = RsdsDebugDirectoryRva;
|
||||
OptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof(IMAGE_DEBUG_DIRECTORY);
|
||||
}
|
||||
else
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER64 * OptionalHeader64 = (IMAGE_OPTIONAL_HEADER64 *)OptionalHeader;
|
||||
OptionalHeader64->Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
|
||||
OptionalHeader64->SizeOfHeaders = 0x200;
|
||||
OptionalHeader64->SizeOfImage = 0x2000;
|
||||
OptionalHeader64->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
|
||||
OptionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = RsdsDebugDirectoryRva;
|
||||
OptionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof(IMAGE_DEBUG_DIRECTORY);
|
||||
}
|
||||
|
||||
IMAGE_SECTION_HEADER * SectionHeader = (IMAGE_SECTION_HEADER *)(Buffer + RsdsSectionHeaderOffset(FileHeader->SizeOfOptionalHeader));
|
||||
CopyMemory(SectionHeader->Name, ".rdata", sizeof(".rdata") - 1);
|
||||
SectionHeader->Misc.VirtualSize = RsdsSectionSize;
|
||||
SectionHeader->VirtualAddress = RsdsSectionRva;
|
||||
SectionHeader->SizeOfRawData = RsdsSectionSize;
|
||||
SectionHeader->PointerToRawData = RsdsSectionRaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the debug directory entry in the PE image to point to the specified directory
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image
|
||||
* @param DirectoryRva The RVA of the debug directory to set
|
||||
* @param DirectorySize The size of the debug directory
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsSetDebugDirectory(BYTE * Buffer, DWORD DirectoryRva, DWORD DirectorySize)
|
||||
{
|
||||
BYTE * NtHeaders = Buffer + RsdsPeHeaderOffset;
|
||||
BYTE * OptionalHeader = NtHeaders + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
WORD Magic = *(WORD *)OptionalHeader;
|
||||
|
||||
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER32 * OptionalHeader32 = (IMAGE_OPTIONAL_HEADER32 *)OptionalHeader;
|
||||
OptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = DirectoryRva;
|
||||
OptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = DirectorySize;
|
||||
}
|
||||
else
|
||||
{
|
||||
IMAGE_OPTIONAL_HEADER64 * OptionalHeader64 = (IMAGE_OPTIONAL_HEADER64 *)OptionalHeader;
|
||||
OptionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = DirectoryRva;
|
||||
OptionalHeader64->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size = DirectorySize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the NumberOfRvaAndSizes field in the optional header to the specified value
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image
|
||||
* @param NumberOfRvaAndSizes The value to set for the NumberOfRvaAndSizes field
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsSetNumberOfRvaAndSizes(BYTE * Buffer, DWORD NumberOfRvaAndSizes)
|
||||
{
|
||||
BYTE * NtHeaders = Buffer + RsdsPeHeaderOffset;
|
||||
BYTE * OptionalHeader = NtHeaders + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
WORD Magic = *(WORD *)OptionalHeader;
|
||||
|
||||
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
((IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->NumberOfRvaAndSizes = NumberOfRvaAndSizes;
|
||||
}
|
||||
else
|
||||
{
|
||||
((IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->NumberOfRvaAndSizes = NumberOfRvaAndSizes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the SizeOfImage field in the optional header to the specified value
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image
|
||||
* @param SizeOfImage The value to set for the SizeOfImage field
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsSetSizeOfImage(BYTE * Buffer, DWORD SizeOfImage)
|
||||
{
|
||||
BYTE * NtHeaders = Buffer + RsdsPeHeaderOffset;
|
||||
BYTE * OptionalHeader = NtHeaders + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
WORD Magic = *(WORD *)OptionalHeader;
|
||||
|
||||
if (Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
|
||||
{
|
||||
((IMAGE_OPTIONAL_HEADER32 *)OptionalHeader)->SizeOfImage = SizeOfImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
((IMAGE_OPTIONAL_HEADER64 *)OptionalHeader)->SizeOfImage = SizeOfImage;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes an RSDS CodeView payload to the specified location in the buffer
|
||||
*
|
||||
* @param Buffer The buffer to write the payload into
|
||||
* @param RawOffset The file offset to write the payload at
|
||||
* @param Guid The GUID to include in the payload
|
||||
* @param Age The age to include in the payload
|
||||
* @param Path The path to include in the payload
|
||||
* @param IncludeNul Whether to include a NUL terminator at the end of the path
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsWritePayload(BYTE * Buffer, DWORD RawOffset, const GUID & Guid, DWORD Age, const CHAR * Path, BOOLEAN IncludeNul)
|
||||
{
|
||||
BYTE * Payload = Buffer + RawOffset;
|
||||
CopyMemory(Payload, "RSDS", sizeof(DWORD));
|
||||
CopyMemory(Payload + sizeof(DWORD), &Guid, sizeof(Guid));
|
||||
CopyMemory(Payload + sizeof(DWORD) + sizeof(GUID), &Age, sizeof(Age));
|
||||
|
||||
SIZE_T PathLength = strlen(Path);
|
||||
CopyMemory(Payload + sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD), Path, PathLength);
|
||||
if (IncludeNul)
|
||||
{
|
||||
Payload[sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + PathLength] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the size of an RSDS CodeView payload based on the path length and whether to include a NUL terminator
|
||||
*
|
||||
* @param Path The path to be included in the payload
|
||||
* @param IncludeNul Whether to include a NUL terminator at the end of the path
|
||||
*
|
||||
* @return DWORD The size of the payload in bytes
|
||||
*/
|
||||
static DWORD
|
||||
RsdsPayloadSize(const CHAR * Path, BOOLEAN IncludeNul)
|
||||
{
|
||||
return (DWORD)(sizeof(DWORD) + sizeof(GUID) + sizeof(DWORD) + strlen(Path) + (IncludeNul ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes an IMAGE_DEBUG_DIRECTORY entry to the specified location in the buffer
|
||||
*
|
||||
* @param Buffer The buffer to write the debug entry into
|
||||
* @param EntryRawOffset The file offset to write the debug entry at
|
||||
* @param Type The Type field of the debug entry
|
||||
* @param PayloadRva The AddressOfRawData field of the debug entry
|
||||
* @param PayloadRaw The PointerToRawData field of the debug entry
|
||||
* @param PayloadSize The SizeOfData field of the debug entry
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsWriteDebugEntry(BYTE * Buffer, DWORD EntryRawOffset, DWORD Type, DWORD PayloadRva, DWORD PayloadRaw, DWORD PayloadSize)
|
||||
{
|
||||
IMAGE_DEBUG_DIRECTORY * DebugEntry = (IMAGE_DEBUG_DIRECTORY *)(Buffer + EntryRawOffset);
|
||||
ZeroMemory(DebugEntry, sizeof(*DebugEntry));
|
||||
DebugEntry->Type = Type;
|
||||
DebugEntry->SizeOfData = PayloadSize;
|
||||
DebugEntry->AddressOfRawData = PayloadRva;
|
||||
DebugEntry->PointerToRawData = PayloadRaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds a minimal PE image with a valid RSDS debug entry in the specified buffer
|
||||
*
|
||||
* @param Buffer The buffer to write the PE image into. Must be at least RsdsFixtureSize bytes
|
||||
* @param Guid The GUID to include in the RSDS payload
|
||||
* @param Age The age to include in the RSDS payload
|
||||
* @param Path The path to include in the RSDS payload
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsWriteValidDebugEntry(BYTE * Buffer, const GUID & Guid, DWORD Age, const CHAR * Path)
|
||||
{
|
||||
DWORD PayloadSize = RsdsPayloadSize(Path, TRUE);
|
||||
RsdsWritePayload(Buffer, RsdsPayloadRaw, Guid, Age, Path, TRUE);
|
||||
RsdsWriteDebugEntry(Buffer, RsdsDebugDirectoryRaw, IMAGE_DEBUG_TYPE_CODEVIEW, RsdsPayloadRva, RsdsPayloadRaw, PayloadSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds a minimal PE image with a valid RSDS debug entry suitable for loaded PE parsing in the specified buffer
|
||||
*
|
||||
* @param Buffer The buffer to write the PE image into. Must be at least RsdsFixtureSize bytes
|
||||
* @param Is32Bit Whether to build a 32-bit (true) or 64-bit (false) PE image
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsBuildLoadedPe(BYTE * Buffer, BOOLEAN Is32Bit)
|
||||
{
|
||||
RsdsBuildMinimalPe(Buffer, Is32Bit);
|
||||
RsdsSetDebugDirectory(Buffer, RsdsLoadedDebugRva, sizeof(IMAGE_DEBUG_DIRECTORY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a valid RSDS debug entry suitable for loaded PE parsing to the specified buffer
|
||||
*
|
||||
* @param Buffer The buffer to write the debug entry into
|
||||
* @param Guid The GUID to include in the RSDS payload
|
||||
* @param Age The age to include in the RSDS payload
|
||||
* @param Path The path to include in the RSDS payload
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
static VOID
|
||||
RsdsWriteValidLoadedDebugEntry(BYTE * Buffer, const GUID & Guid, DWORD Age, const CHAR * Path)
|
||||
{
|
||||
DWORD PayloadSize = RsdsPayloadSize(Path, TRUE);
|
||||
RsdsWritePayload(Buffer, RsdsLoadedPayloadRva, Guid, Age, Path, TRUE);
|
||||
RsdsWriteDebugEntry(Buffer, RsdsLoadedDebugRva, IMAGE_DEBUG_TYPE_CODEVIEW, RsdsLoadedPayloadRva, RsdsBogusRawPointer, PayloadSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two GUIDs for equality
|
||||
*
|
||||
* @param Left The first GUID to compare
|
||||
* @param Right The second GUID to compare
|
||||
*
|
||||
* @return BOOLEAN TRUE if the GUIDs are equal, FALSE otherwise
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsGuidEquals(const GUID & Left, const GUID & Right)
|
||||
{
|
||||
return memcmp(&Left, &Right, sizeof(Left)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to test that the RSDS parser successfully extracts the expected information from the provided buffer
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image to parse
|
||||
* @param ExpectedPdb The expected PDB file name to be extracted from the RSDS payload
|
||||
* @param ExpectedGuid The expected GUID to be extracted from the RSDS payload
|
||||
* @param ExpectedAge The expected age to be extracted from the RSDS payload
|
||||
*
|
||||
* @return BOOLEAN TRUE if the parser successfully extracted the expected information, FALSE otherwise
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsExpectSuccess(const BYTE * Buffer, const CHAR * ExpectedPdb, const GUID & ExpectedGuid, DWORD ExpectedAge)
|
||||
{
|
||||
CHAR PdbFileName[MAX_PATH] = {0};
|
||||
GUID Guid = {0};
|
||||
DWORD Age = 0;
|
||||
|
||||
return SymExtractCodeViewRsdsInfoFromPeImage(Buffer, RsdsFixtureSize, PdbFileName, sizeof(PdbFileName), &Guid, &Age) &&
|
||||
strcmp(PdbFileName, ExpectedPdb) == 0 && RsdsGuidEquals(Guid, ExpectedGuid) && Age == ExpectedAge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to test that the RSDS parser fails to extract information from the provided buffer and leaves output parameters unchanged
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image to parse
|
||||
*
|
||||
* @return BOOLEAN TRUE if the parser failed as expected and left output parameters unchanged, FALSE otherwise
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsExpectFailure(const BYTE * Buffer)
|
||||
{
|
||||
CHAR PdbFileName[MAX_PATH] = {'x'};
|
||||
GUID Guid = RsdsGuid64;
|
||||
GUID EmptyGuid = {0};
|
||||
DWORD Age = 0x12345678;
|
||||
|
||||
return !SymExtractCodeViewRsdsInfoFromPeImage(Buffer, RsdsFixtureSize, PdbFileName, sizeof(PdbFileName), &Guid, &Age) &&
|
||||
PdbFileName[0] == '\0' && RsdsGuidEquals(Guid, EmptyGuid) && Age == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to test that the RSDS parser successfully extracts the expected information from the provided buffer when parsing as a loaded PE
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image to parse
|
||||
* @param ExpectedPdb The expected PDB file name to be extracted from the RSDS payload
|
||||
* @param ExpectedGuid The expected GUID to be extracted from the RSDS payload
|
||||
* @param ExpectedAge The expected age to be extracted from the RSDS payload
|
||||
*
|
||||
* @return BOOLEAN TRUE if the parser successfully extracted the expected information, FALSE otherwise
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsExpectLoadedSuccess(const BYTE * Buffer, const CHAR * ExpectedPdb, const GUID & ExpectedGuid, DWORD ExpectedAge)
|
||||
{
|
||||
CHAR PdbFileName[MAX_PATH] = {0};
|
||||
GUID Guid = {0};
|
||||
DWORD Age = 0;
|
||||
|
||||
return SymExtractCodeViewRsdsInfoFromLoadedPeImage(Buffer, RsdsFixtureSize, PdbFileName, sizeof(PdbFileName), &Guid, &Age) &&
|
||||
strcmp(PdbFileName, ExpectedPdb) == 0 && RsdsGuidEquals(Guid, ExpectedGuid) && Age == ExpectedAge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper function to test that the RSDS parser fails to extract information from the provided buffer when parsing as a loaded PE and leaves output parameters unchanged
|
||||
*
|
||||
* @param Buffer The buffer containing the PE image to parse
|
||||
*
|
||||
* @return BOOLEAN TRUE if the parser failed as expected and left output parameters unchanged, FALSE otherwise
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsExpectLoadedFailure(const BYTE * Buffer)
|
||||
{
|
||||
CHAR PdbFileName[MAX_PATH] = {'x'};
|
||||
GUID Guid = RsdsGuid64;
|
||||
GUID EmptyGuid = {0};
|
||||
DWORD Age = 0x12345678;
|
||||
|
||||
return !SymExtractCodeViewRsdsInfoFromLoadedPeImage(Buffer, RsdsFixtureSize, PdbFileName, sizeof(PdbFileName), &Guid, &Age) &&
|
||||
PdbFileName[0] == '\0' && RsdsGuidEquals(Guid, EmptyGuid) && Age == 0;
|
||||
}
|
||||
|
||||
// Context structure for the fake fallback function used in some test cases
|
||||
typedef struct _RSDS_FAKE_FALLBACK_CONTEXT
|
||||
{
|
||||
INT32 CallCount;
|
||||
BOOLEAN Succeed;
|
||||
} RSDS_FAKE_FALLBACK_CONTEXT, *PRSDS_FAKE_FALLBACK_CONTEXT;
|
||||
|
||||
/**
|
||||
* @brief A fake fallback function that can be used to test the behavior of the RSDS parser when a fallback is triggered
|
||||
*
|
||||
* @param Context A pointer to an RSDS_FAKE_FALLBACK_CONTEXT structure that controls the behavior of the fallback
|
||||
* @param PdbFile The output buffer to receive the PDB file name (must be at least MAX_PATH bytes)
|
||||
* @param PdbFileSize The size of the PdbFile buffer in bytes
|
||||
* @param Guid The output parameter to receive the GUID
|
||||
* @param Age The output parameter to receive the age
|
||||
*
|
||||
* @return BOOLEAN TRUE if the fallback succeeded and filled output parameters, FALSE if the fallback failed and left output parameters unchanged
|
||||
*/
|
||||
static BOOLEAN
|
||||
RsdsFakeFallback(PVOID Context, CHAR * PdbFile, SIZE_T PdbFileSize, GUID * Guid, DWORD * Age)
|
||||
{
|
||||
PRSDS_FAKE_FALLBACK_CONTEXT FallbackContext = (PRSDS_FAKE_FALLBACK_CONTEXT)Context;
|
||||
|
||||
FallbackContext->CallCount++;
|
||||
if (!FallbackContext->Succeed)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (strcpy_s(PdbFile, PdbFileSize, "fallback.pdb") != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*Guid = RsdsGuidMulti;
|
||||
*Age = 0x2b;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Runs a series of test cases to validate the behavior of the RSDS parser helper functions
|
||||
*
|
||||
* @return BOOLEAN TRUE if all test cases passed, FALSE if any test case failed
|
||||
*/
|
||||
BOOLEAN
|
||||
TestCodeViewRsdsParser()
|
||||
{
|
||||
BYTE Buffer[RsdsFixtureSize] = {0};
|
||||
INT32 TestNum = 0;
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid64, 7, "symbols\\valid64.pdb");
|
||||
TestNum++;
|
||||
if (RsdsExpectSuccess(Buffer, "valid64.pdb", RsdsGuid64, 7))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] valid PE32+ RSDS entry was not parsed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid64, 7, "symbols\\unadvertised.pdb");
|
||||
RsdsSetNumberOfRvaAndSizes(Buffer, IMAGE_DIRECTORY_ENTRY_DEBUG);
|
||||
TestNum++;
|
||||
if (RsdsExpectFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] raw parser accepted an unadvertised debug directory\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, TRUE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid32, 9, "symbols/valid32.pdb");
|
||||
TestNum++;
|
||||
if (RsdsExpectSuccess(Buffer, "valid32.pdb", RsdsGuid32, 9))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] valid PE32 RSDS entry was not parsed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid64, 7, "symbols\\valid64.pdb");
|
||||
RsdsSetDebugDirectory(Buffer, 0x3000, sizeof(IMAGE_DEBUG_DIRECTORY));
|
||||
TestNum++;
|
||||
if (RsdsExpectFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] unmapped debug directory parsed successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid64, 7, "symbols\\invalid.pdb");
|
||||
CopyMemory(Buffer + RsdsPayloadRaw, "ABCD", sizeof(DWORD));
|
||||
TestNum++;
|
||||
if (RsdsExpectFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] unsupported CodeView signature parsed successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWritePayload(Buffer, RsdsPayloadRaw, RsdsGuid64, 7, "symbols\\missing-nul.pdb", FALSE);
|
||||
RsdsWriteDebugEntry(Buffer,
|
||||
RsdsDebugDirectoryRaw,
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||
RsdsPayloadRva,
|
||||
RsdsPayloadRaw,
|
||||
RsdsPayloadSize("symbols\\missing-nul.pdb", FALSE));
|
||||
TestNum++;
|
||||
if (RsdsExpectFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] RSDS path without NUL terminator parsed successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsSetDebugDirectory(Buffer, RsdsDebugDirectoryRva, sizeof(IMAGE_DEBUG_DIRECTORY) * 2);
|
||||
RsdsWriteDebugEntry(Buffer, RsdsDebugDirectoryRaw, IMAGE_DEBUG_TYPE_CODEVIEW, RsdsPayloadRva, RsdsPayloadRaw, sizeof(DWORD));
|
||||
CopyMemory(Buffer + RsdsPayloadRaw, "NB10", sizeof(DWORD));
|
||||
RsdsWritePayload(Buffer, 0x390, RsdsGuidMulti, 11, "alt/second-valid.pdb", TRUE);
|
||||
RsdsWriteDebugEntry(Buffer,
|
||||
RsdsDebugDirectoryRaw + sizeof(IMAGE_DEBUG_DIRECTORY),
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||
0x1190,
|
||||
0x390,
|
||||
RsdsPayloadSize("alt/second-valid.pdb", TRUE));
|
||||
TestNum++;
|
||||
if (RsdsExpectSuccess(Buffer, "second-valid.pdb", RsdsGuidMulti, 11))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] parser did not skip invalid first entry and parse second RSDS entry\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid64, 0x21, "loaded\\loaded64.pdb");
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedSuccess(Buffer, "loaded64.pdb", RsdsGuid64, 0x21))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded PE32+ RSDS entry was not parsed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid64, 0x21, "loaded\\unadvertised.pdb");
|
||||
RsdsSetNumberOfRvaAndSizes(Buffer, IMAGE_DIRECTORY_ENTRY_DEBUG);
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser accepted an unadvertised debug directory\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, TRUE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid32, 0x22, "loaded/loaded32.pdb");
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedSuccess(Buffer, "loaded32.pdb", RsdsGuid32, 0x22))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded PE32 RSDS entry was not parsed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid64, 0x23, "loaded\\bogus-raw-ignored.pdb");
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedSuccess(Buffer, "bogus-raw-ignored.pdb", RsdsGuid64, 0x23))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser used bogus PointerToRawData instead of loaded RVA\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
std::vector<BYTE> HighLoadedBuffer(RsdsHighLoadedSize);
|
||||
RsdsBuildLoadedPe(HighLoadedBuffer.data(), FALSE);
|
||||
RsdsSetSizeOfImage(HighLoadedBuffer.data(), (DWORD)HighLoadedBuffer.size());
|
||||
RsdsSetDebugDirectory(HighLoadedBuffer.data(), RsdsHighLoadedDebugRva, sizeof(IMAGE_DEBUG_DIRECTORY));
|
||||
RsdsWritePayload(HighLoadedBuffer.data(), RsdsHighLoadedPayloadRva, RsdsGuid64, 0x28, "loaded\\high-rva.pdb", TRUE);
|
||||
RsdsWriteDebugEntry(HighLoadedBuffer.data(),
|
||||
RsdsHighLoadedDebugRva,
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||
RsdsHighLoadedPayloadRva,
|
||||
RsdsBogusRawPointer,
|
||||
RsdsPayloadSize("loaded\\high-rva.pdb", TRUE));
|
||||
CHAR HighLoadedPdbFileName[MAX_PATH] = {0};
|
||||
GUID HighLoadedGuid = {0};
|
||||
DWORD HighLoadedAge = 0;
|
||||
TestNum++;
|
||||
if (SymExtractCodeViewRsdsInfoFromLoadedPeImage(HighLoadedBuffer.data(),
|
||||
HighLoadedBuffer.size(),
|
||||
HighLoadedPdbFileName,
|
||||
sizeof(HighLoadedPdbFileName),
|
||||
&HighLoadedGuid,
|
||||
&HighLoadedAge) &&
|
||||
strcmp(HighLoadedPdbFileName, "high-rva.pdb") == 0 && RsdsGuidEquals(HighLoadedGuid, RsdsGuid64) &&
|
||||
HighLoadedAge == 0x28)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser did not parse high-RVA RSDS data\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid64, 0x24, "loaded\\invalid-dir.pdb");
|
||||
RsdsSetDebugDirectory(Buffer, RsdsFixtureSize - sizeof(IMAGE_DEBUG_DIRECTORY) / 2, sizeof(IMAGE_DEBUG_DIRECTORY));
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser accepted malformed debug directory bounds\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWriteValidLoadedDebugEntry(Buffer, RsdsGuid64, 0x25, "loaded\\unsupported.pdb");
|
||||
CopyMemory(Buffer + RsdsLoadedPayloadRva, "ABCD", sizeof(DWORD));
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser accepted unsupported CodeView signature\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsWritePayload(Buffer, RsdsLoadedPayloadRva, RsdsGuid64, 0x26, "loaded\\missing-nul.pdb", FALSE);
|
||||
RsdsWriteDebugEntry(Buffer,
|
||||
RsdsLoadedDebugRva,
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||
RsdsLoadedPayloadRva,
|
||||
RsdsBogusRawPointer,
|
||||
RsdsPayloadSize("loaded\\missing-nul.pdb", FALSE));
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedFailure(Buffer))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser accepted RSDS path without NUL terminator\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildLoadedPe(Buffer, FALSE);
|
||||
RsdsSetDebugDirectory(Buffer, RsdsLoadedDebugRva, sizeof(IMAGE_DEBUG_DIRECTORY) * 2);
|
||||
RsdsWriteDebugEntry(Buffer, RsdsLoadedDebugRva, IMAGE_DEBUG_TYPE_CODEVIEW, RsdsLoadedPayloadRva, RsdsBogusRawPointer, sizeof(DWORD));
|
||||
CopyMemory(Buffer + RsdsLoadedPayloadRva, "NB10", sizeof(DWORD));
|
||||
RsdsWritePayload(Buffer, 0x330, RsdsGuidMulti, 0x27, "loaded/second-loaded.pdb", TRUE);
|
||||
RsdsWriteDebugEntry(Buffer,
|
||||
RsdsLoadedDebugRva + sizeof(IMAGE_DEBUG_DIRECTORY),
|
||||
IMAGE_DEBUG_TYPE_CODEVIEW,
|
||||
0x330,
|
||||
RsdsBogusRawPointer,
|
||||
RsdsPayloadSize("loaded/second-loaded.pdb", TRUE));
|
||||
TestNum++;
|
||||
if (RsdsExpectLoadedSuccess(Buffer, "second-loaded.pdb", RsdsGuidMulti, 0x27))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] loaded parser did not skip invalid first entry and parse second RSDS entry\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CHAR SymbolServerRelativePath[MAX_PATH] = {0};
|
||||
CHAR GuidAndAgeDetails[MAX_PATH] = {0};
|
||||
CHAR SmallGuidAndAgeDetails[MAXIMUM_GUID_AND_AGE_SIZE] = {0};
|
||||
const GUID Guid = {0x01234567, 0x89ab, 0xcdef, {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}};
|
||||
TestNum++;
|
||||
if (SymFormatPdbIdentity("valid32.pdb",
|
||||
&Guid,
|
||||
0x1a,
|
||||
SymbolServerRelativePath,
|
||||
sizeof(SymbolServerRelativePath),
|
||||
GuidAndAgeDetails,
|
||||
sizeof(GuidAndAgeDetails)) &&
|
||||
strcmp(GuidAndAgeDetails, "0123456789abcdeffedcba98765432101a") == 0 &&
|
||||
strcmp(SymbolServerRelativePath, "valid32.pdb/0123456789abcdeffedcba98765432101a/valid32.pdb") == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] PDB identity formatting did not match symbol server path and GUID+age expectations\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TestNum++;
|
||||
if (SymFormatPdbIdentity("valid32.pdb",
|
||||
&Guid,
|
||||
0x1a,
|
||||
NULL,
|
||||
0,
|
||||
SmallGuidAndAgeDetails,
|
||||
sizeof(SmallGuidAndAgeDetails)) &&
|
||||
strcmp(SmallGuidAndAgeDetails, "0123456789abcdeffedcba98765432101a") == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] GUID+age identity did not fit the SDK-sized buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsdsBuildMinimalPe(Buffer, FALSE);
|
||||
RsdsWriteValidDebugEntry(Buffer, RsdsGuid64, 0x1c, "preferred\\preferred.pdb");
|
||||
RSDS_FAKE_FALLBACK_CONTEXT FallbackContext = {0, TRUE};
|
||||
CHAR PreferredPath[MAX_PATH] = {0};
|
||||
TestNum++;
|
||||
if (SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
PreferredPath,
|
||||
sizeof(PreferredPath),
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
strcmp(PreferredPath, "preferred.pdb/67452301ab89efcd1032547698badcfe1c/preferred.pdb") == 0 &&
|
||||
FallbackContext.CallCount == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] PE RSDS identity was not preferred over fallback identity\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FallbackContext.CallCount = 0;
|
||||
CHAR ZeroSizeOutput = 'x';
|
||||
TestNum++;
|
||||
if (!SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
&ZeroSizeOutput,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
ZeroSizeOutput == 'x' && FallbackContext.CallCount == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] zero-sized output buffer was written or reported success\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FallbackContext.CallCount = 0;
|
||||
TestNum++;
|
||||
if (!SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
FallbackContext.CallCount == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] identity formatting without requested output reported success or used fallback\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FallbackContext.CallCount = 0;
|
||||
CHAR SmallPdbPath[4] = {'x'};
|
||||
CHAR SmallFailureGuidAge[64] = {'x'};
|
||||
TestNum++;
|
||||
if (!SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
NULL,
|
||||
0,
|
||||
SmallPdbPath,
|
||||
sizeof(SmallPdbPath),
|
||||
SmallFailureGuidAge,
|
||||
sizeof(SmallFailureGuidAge),
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
SmallPdbPath[0] == '\0' && SmallFailureGuidAge[0] == '\0' && FallbackContext.CallCount == 0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] output formatting failure leaked partial identity data\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(Buffer, sizeof(Buffer));
|
||||
FallbackContext.CallCount = 0;
|
||||
FallbackContext.Succeed = TRUE;
|
||||
CHAR FallbackPdb[MAX_PATH] = {0};
|
||||
CHAR FallbackGuidAge[MAX_PATH] = {0};
|
||||
TestNum++;
|
||||
if (SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
NULL,
|
||||
0,
|
||||
FallbackPdb,
|
||||
sizeof(FallbackPdb),
|
||||
FallbackGuidAge,
|
||||
sizeof(FallbackGuidAge),
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
strcmp(FallbackPdb, "fallback.pdb") == 0 &&
|
||||
strcmp(FallbackGuidAge, "aabbccddeeff112233445566778899aa2b") == 0 &&
|
||||
FallbackContext.CallCount == 1)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] malformed PE bytes did not use fallback identity\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FallbackContext.CallCount = 0;
|
||||
FallbackContext.Succeed = FALSE;
|
||||
CHAR FailedPath[MAX_PATH] = {'x'};
|
||||
CHAR FailedPdb[MAX_PATH] = {'x'};
|
||||
CHAR FailedGuidAge[MAX_PATH] = {'x'};
|
||||
TestNum++;
|
||||
if (!SymFormatPdbIdentityFromPeImageOrFallback(Buffer,
|
||||
RsdsFixtureSize,
|
||||
FailedPath,
|
||||
sizeof(FailedPath),
|
||||
FailedPdb,
|
||||
sizeof(FailedPdb),
|
||||
FailedGuidAge,
|
||||
sizeof(FailedGuidAge),
|
||||
RsdsFakeFallback,
|
||||
&FallbackContext) &&
|
||||
FailedPath[0] == '\0' && FailedPdb[0] == '\0' && FailedGuidAge[0] == '\0' && FallbackContext.CallCount == 1)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] fallback failure reported success or left success-looking output\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -11,132 +11,132 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
typedef char ** CHAR_PTR_PTR; // Define CHAR_PTR_PTR as a char**
|
||||
typedef CHAR ** CHAR_PTR_PTR; // Define CHAR_PTR_PTR as CHAR**
|
||||
|
||||
/**
|
||||
* @brief Create an array of strings from a vector of strings
|
||||
* @param testCases The vector of strings to copy
|
||||
* @param TestCases The vector of strings to copy
|
||||
*
|
||||
* @return A pointer to the array of strings
|
||||
*/
|
||||
CHAR_PTR_PTR
|
||||
createTestCaseArray(const std::vector<std::string> & testCases)
|
||||
CreateTestCaseArray(const std::vector<std::string> & TestCases)
|
||||
{
|
||||
//
|
||||
// Allocate memory for the array of pointers (size: number of test cases)
|
||||
//
|
||||
CHAR_PTR_PTR testCaseArray = (CHAR_PTR_PTR)malloc(testCases.size() * sizeof(UINT64));
|
||||
CHAR_PTR_PTR TestCaseArray = (CHAR_PTR_PTR)malloc(TestCases.size() * sizeof(UINT64));
|
||||
|
||||
//
|
||||
// Allocate memory for each string and copy the content
|
||||
//
|
||||
for (size_t i = 0; i < testCases.size(); ++i)
|
||||
for (SIZE_T i = 0; i < TestCases.size(); ++i)
|
||||
{
|
||||
testCaseArray[i] = (char *)malloc(testCases[i].length() + 1); // +1 for the null terminator
|
||||
TestCaseArray[i] = (CHAR *)malloc(TestCases[i].length() + 1); // +1 for the null terminator
|
||||
|
||||
if (testCaseArray[i] == NULL)
|
||||
if (TestCaseArray[i] == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
std::strcpy(testCaseArray[i], testCases[i].c_str());
|
||||
std::strcpy(TestCaseArray[i], TestCases[i].c_str());
|
||||
}
|
||||
|
||||
return testCaseArray;
|
||||
return TestCaseArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free the memory allocated for the test case array
|
||||
* @param testCaseArray The array of pointers to free
|
||||
* @param size The size of the array
|
||||
* @param TestCaseArray The array of pointers to free
|
||||
* @param Size The size of the array
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
freeTestCaseArray(CHAR_PTR_PTR testCaseArray, size_t size)
|
||||
FreeTestCaseArray(CHAR_PTR_PTR TestCaseArray, SIZE_T Size)
|
||||
{
|
||||
//
|
||||
// Free each string
|
||||
//
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
for (SIZE_T i = 0; i < Size; ++i)
|
||||
{
|
||||
free(testCaseArray[i]);
|
||||
free(TestCaseArray[i]);
|
||||
}
|
||||
|
||||
//
|
||||
// Free the array of pointers
|
||||
//
|
||||
free(testCaseArray);
|
||||
free(TestCaseArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse the test cases from the file
|
||||
* @param filename The name of the file to parse
|
||||
* @param Filename The name of the file to parse
|
||||
*
|
||||
* @return A vector of pairs, where each pair contains a command and a vector of tokens
|
||||
*/
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>>
|
||||
parseTestCases(const std::string & filename)
|
||||
ParseTestCases(const std::string & Filename)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
std::string line;
|
||||
std::string command;
|
||||
std::string currentToken;
|
||||
std::vector<std::string> tokens;
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> testCases;
|
||||
bool isCommand = false;
|
||||
bool addNewline = false;
|
||||
std::ifstream file(Filename);
|
||||
std::string Line;
|
||||
std::string Command;
|
||||
std::string CurrentToken;
|
||||
std::vector<std::string> Tokens;
|
||||
std::vector<std::pair<std::string, std::vector<std::string>>> TestCases;
|
||||
BOOLEAN IsCommand = FALSE;
|
||||
BOOLEAN AddNewline = FALSE;
|
||||
|
||||
const std::string tokenDelimiter = "----------------------------------";
|
||||
const std::string commandDelimiter = "_____________________________________________________________";
|
||||
const std::string TokenDelimiter = "----------------------------------";
|
||||
const std::string CommandDelimiter = "_____________________________________________________________";
|
||||
|
||||
while (std::getline(file, line))
|
||||
while (std::getline(file, Line))
|
||||
{
|
||||
if (line == commandDelimiter)
|
||||
if (Line == CommandDelimiter)
|
||||
{
|
||||
//
|
||||
// No new line is needed after this token
|
||||
//
|
||||
addNewline = false;
|
||||
AddNewline = FALSE;
|
||||
|
||||
//
|
||||
// Save the previous command and its tokens if any
|
||||
//
|
||||
if (!command.empty())
|
||||
if (!Command.empty())
|
||||
{
|
||||
if (!currentToken.empty())
|
||||
if (!CurrentToken.empty())
|
||||
{
|
||||
tokens.push_back(currentToken);
|
||||
currentToken.clear();
|
||||
Tokens.push_back(CurrentToken);
|
||||
CurrentToken.clear();
|
||||
}
|
||||
testCases.push_back({command, tokens});
|
||||
command.clear();
|
||||
tokens.clear();
|
||||
TestCases.push_back({Command, Tokens});
|
||||
Command.clear();
|
||||
Tokens.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// is command is true since a command is started
|
||||
//
|
||||
isCommand = true;
|
||||
IsCommand = TRUE;
|
||||
}
|
||||
else if (line == tokenDelimiter)
|
||||
else if (Line == TokenDelimiter)
|
||||
{
|
||||
//
|
||||
// No new line is needed after this token
|
||||
//
|
||||
addNewline = false;
|
||||
AddNewline = FALSE;
|
||||
|
||||
//
|
||||
// not in command anymore
|
||||
//
|
||||
isCommand = false;
|
||||
IsCommand = FALSE;
|
||||
|
||||
//
|
||||
// If we're in the middle of collecting a token, save it
|
||||
//
|
||||
if (!currentToken.empty())
|
||||
if (!CurrentToken.empty())
|
||||
{
|
||||
tokens.push_back(currentToken);
|
||||
currentToken.clear();
|
||||
Tokens.push_back(CurrentToken);
|
||||
CurrentToken.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -144,110 +144,110 @@ parseTestCases(const std::string & filename)
|
|||
//
|
||||
// Accumulate lines for the command or token
|
||||
//
|
||||
if (isCommand)
|
||||
if (IsCommand)
|
||||
{
|
||||
if (addNewline)
|
||||
command += "\n";
|
||||
command += line;
|
||||
if (AddNewline)
|
||||
Command += "\n";
|
||||
Command += Line;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (addNewline)
|
||||
currentToken += "\n";
|
||||
currentToken += line;
|
||||
if (AddNewline)
|
||||
CurrentToken += "\n";
|
||||
CurrentToken += Line;
|
||||
}
|
||||
|
||||
addNewline = true;
|
||||
AddNewline = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Store the last command and tokens if any
|
||||
//
|
||||
if (!command.empty())
|
||||
if (!Command.empty())
|
||||
{
|
||||
if (!currentToken.empty())
|
||||
if (!CurrentToken.empty())
|
||||
{
|
||||
tokens.push_back(currentToken);
|
||||
Tokens.push_back(CurrentToken);
|
||||
}
|
||||
testCases.push_back({command, tokens});
|
||||
TestCases.push_back({Command, Tokens});
|
||||
}
|
||||
|
||||
return testCases;
|
||||
return TestCases;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Count the number of occurrences of the substring "\\n" up to a specified position
|
||||
* @param str The string to search
|
||||
* @param limit The position to search up to
|
||||
* @param Str The string to search
|
||||
* @param Limit The position to search up to
|
||||
*
|
||||
* @return The number of occurrences of the substring "\\n"
|
||||
* @return INT32 The number of occurrences of the substring "\\n"
|
||||
*/
|
||||
int
|
||||
countBackslashNUpToPosition(const std::string & str, std::size_t limit)
|
||||
INT32
|
||||
CountBackslashNUpToPosition(const std::string & Str, std::size_t Limit)
|
||||
{
|
||||
int count = 0;
|
||||
std::string::size_type pos = 0;
|
||||
std::string target = "\\n";
|
||||
INT32 Count = 0;
|
||||
std::string::size_type Pos = 0;
|
||||
std::string Target = "\\n";
|
||||
|
||||
//
|
||||
// Limit the string to search within the specified range
|
||||
//
|
||||
while ((pos = str.find(target, pos)) != std::string::npos && pos < limit)
|
||||
while ((Pos = Str.find(Target, Pos)) != std::string::npos && Pos < Limit)
|
||||
{
|
||||
++count;
|
||||
pos += target.length(); // Move past the current occurrence
|
||||
++Count;
|
||||
Pos += Target.length(); // Move past the current occurrence
|
||||
}
|
||||
|
||||
return count;
|
||||
return Count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Show parsed command and tokens
|
||||
* @param testCases A vector of pairs, where each pair contains a command and a vector of tokens
|
||||
* @param failedTokenNum The number of the failed token
|
||||
* @param failedTokenPosition The position of the failed token
|
||||
* @param TestCase A pair containing a command and a vector of tokens
|
||||
* @param FailedTokenNum The number of the failed token
|
||||
* @param FailedTokenPosition The position of the failed token
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
ShowParsedCommandAndTokens(const std::pair<std::string,
|
||||
std::vector<std::string>> & testCase,
|
||||
UINT32 failedTokenNum,
|
||||
UINT32 failedTokenPosition)
|
||||
std::vector<std::string>> & TestCase,
|
||||
UINT32 FailedTokenNum,
|
||||
UINT32 FailedTokenPosition)
|
||||
{
|
||||
UINT32 tokenNum = 0;
|
||||
UINT32 TokenNum = 0;
|
||||
|
||||
//
|
||||
// Output the parsed test case
|
||||
//
|
||||
|
||||
string showingCommand = testCase.first;
|
||||
string ShowingCommand = TestCase.first;
|
||||
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = showingCommand.find("\n", pos)) != std::string::npos)
|
||||
std::string::size_type Pos = 0;
|
||||
while ((Pos = ShowingCommand.find("\n", Pos)) != std::string::npos)
|
||||
{
|
||||
showingCommand.replace(pos, 1, "\\n");
|
||||
pos += 2; // Move past the newly added characters
|
||||
ShowingCommand.replace(Pos, 1, "\\n");
|
||||
Pos += 2; // Move past the newly added characters
|
||||
}
|
||||
|
||||
std::cout << "Command: \"" << showingCommand << "\"" << std::endl;
|
||||
std::cout << "Command: \"" << ShowingCommand << "\"" << std::endl;
|
||||
std::cout << "____________________________________\n";
|
||||
|
||||
std::cout << "Expected Tokens: " << std::endl;
|
||||
|
||||
for (const auto & token : testCase.second)
|
||||
for (const auto & Token : TestCase.second)
|
||||
{
|
||||
string showingToken = token;
|
||||
string ShowingToken = Token;
|
||||
|
||||
pos = 0;
|
||||
while ((pos = showingToken.find("\n", pos)) != std::string::npos)
|
||||
Pos = 0;
|
||||
while ((Pos = ShowingToken.find("\n", Pos)) != std::string::npos)
|
||||
{
|
||||
showingToken.replace(pos, 1, "\\n");
|
||||
pos += 2; // Move past the newly added characters
|
||||
ShowingToken.replace(Pos, 1, "\\n");
|
||||
Pos += 2; // Move past the newly added characters
|
||||
}
|
||||
|
||||
if (tokenNum == failedTokenNum)
|
||||
if (TokenNum == FailedTokenNum)
|
||||
{
|
||||
std::cout << " x ";
|
||||
}
|
||||
|
|
@ -256,23 +256,23 @@ ShowParsedCommandAndTokens(const std::pair<std::string,
|
|||
std::cout << " - ";
|
||||
}
|
||||
|
||||
std::cout << "\"" << showingToken << "\"" << std::endl;
|
||||
std::cout << "\"" << ShowingToken << "\"" << std::endl;
|
||||
|
||||
if (tokenNum == failedTokenNum)
|
||||
if (TokenNum == FailedTokenNum)
|
||||
{
|
||||
std::cout << " ";
|
||||
int countOfSpaces = countBackslashNUpToPosition(showingToken, failedTokenPosition);
|
||||
INT32 CountOfSpaces = CountBackslashNUpToPosition(ShowingToken, FailedTokenPosition);
|
||||
|
||||
countOfSpaces += failedTokenPosition;
|
||||
CountOfSpaces += FailedTokenPosition;
|
||||
|
||||
for (int i = 0; i < countOfSpaces; i++)
|
||||
for (INT32 i = 0; i < CountOfSpaces; i++)
|
||||
{
|
||||
std::cout << " ";
|
||||
}
|
||||
std::cout << "^" << std::endl;
|
||||
}
|
||||
|
||||
tokenNum++;
|
||||
TokenNum++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,17 +284,17 @@ ShowParsedCommandAndTokens(const std::pair<std::string,
|
|||
BOOLEAN
|
||||
TestCommandParser()
|
||||
{
|
||||
BOOLEAN overallResult = TRUE;
|
||||
int testNum = 0;
|
||||
CHAR filePath[MAX_PATH] = {0};
|
||||
UINT32 failedTokenNum = 0;
|
||||
UINT32 failedTokenPosition = 0;
|
||||
BOOLEAN OverallResult = TRUE;
|
||||
INT32 TestNum = 0;
|
||||
CHAR FilePath[MAX_PATH] = {0};
|
||||
UINT32 FailedTokenNum = 0;
|
||||
UINT32 FailedTokenPosition = 0;
|
||||
|
||||
//
|
||||
// Parse the test cases from the file
|
||||
// Setup the path for the filename
|
||||
//
|
||||
if (!hyperdbg_u_setup_path_for_filename(COMMAND_PARSER_TEST_CASES_FILE, filePath, MAX_PATH, TRUE))
|
||||
if (!hyperdbg_u_setup_path_for_filename(COMMAND_PARSER_TEST_CASES_FILE, FilePath, MAX_PATH, TRUE))
|
||||
{
|
||||
//
|
||||
// Error could not find the test case files
|
||||
|
|
@ -306,7 +306,7 @@ TestCommandParser()
|
|||
//
|
||||
// Parse the test cases from the file
|
||||
//
|
||||
auto testCases = parseTestCases(filePath);
|
||||
auto TestCases = ParseTestCases(FilePath);
|
||||
|
||||
//
|
||||
// Perform testing test cases with parsed file
|
||||
|
|
@ -316,32 +316,32 @@ TestCommandParser()
|
|||
//
|
||||
// Output the parsed test cases
|
||||
//
|
||||
for (const auto & testCase : testCases)
|
||||
for (const auto & TestCase : TestCases)
|
||||
{
|
||||
testNum++;
|
||||
TestNum++;
|
||||
|
||||
//
|
||||
// Create CHAR**
|
||||
//
|
||||
CHAR_PTR_PTR testCaseArray = createTestCaseArray(testCase.second);
|
||||
CHAR_PTR_PTR TestCaseArray = CreateTestCaseArray(TestCase.second);
|
||||
|
||||
//
|
||||
// Check token with actual parser
|
||||
//
|
||||
if (hyperdbg_u_test_command_parser((CHAR *)testCase.first.c_str(),
|
||||
(UINT32)testCase.second.size(),
|
||||
testCaseArray,
|
||||
&failedTokenNum,
|
||||
&failedTokenPosition))
|
||||
if (hyperdbg_u_test_command_parser((CHAR *)TestCase.first.c_str(),
|
||||
(UINT32)TestCase.second.size(),
|
||||
TestCaseArray,
|
||||
&FailedTokenNum,
|
||||
&FailedTokenPosition))
|
||||
{
|
||||
cout << "[+] Test number " << testNum << " Passed " << endl;
|
||||
cout << "[+] Test number " << TestNum << " Passed " << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Set overall result to FALSE since one of the test cases failed
|
||||
//
|
||||
overallResult = FALSE;
|
||||
OverallResult = FALSE;
|
||||
|
||||
//
|
||||
// Show parsed command and tokens
|
||||
|
|
@ -356,14 +356,14 @@ TestCommandParser()
|
|||
//
|
||||
// Show tokens
|
||||
//
|
||||
hyperdbg_u_test_command_parser_show_tokens((CHAR *)testCase.first.c_str());
|
||||
hyperdbg_u_test_command_parser_show_tokens((CHAR *)TestCase.first.c_str());
|
||||
|
||||
cout << "\n============================================================" << endl;
|
||||
|
||||
cout << "\nThe parsed command and tokens (From file):" << endl;
|
||||
ShowParsedCommandAndTokens(testCase, failedTokenNum, failedTokenPosition);
|
||||
ShowParsedCommandAndTokens(TestCase, FailedTokenNum, FailedTokenPosition);
|
||||
|
||||
cout << "\n[-] Test number " << testNum << " Failed " << endl;
|
||||
cout << "\n[-] Test number " << TestNum << " Failed " << endl;
|
||||
cout << "============================================================\n"
|
||||
<< endl;
|
||||
|
||||
|
|
@ -373,8 +373,8 @@ TestCommandParser()
|
|||
//
|
||||
// Clean up memory
|
||||
//
|
||||
freeTestCaseArray(testCaseArray, testCase.second.size());
|
||||
FreeTestCaseArray(TestCaseArray, TestCase.second.size());
|
||||
}
|
||||
|
||||
return overallResult;
|
||||
return OverallResult;
|
||||
}
|
||||
|
|
|
|||
393
hyperdbg/hyperdbg-test/code/tests/test-pe-parser.cpp
Normal file
393
hyperdbg/hyperdbg-test/code/tests/test-pe-parser.cpp
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
/**
|
||||
* @file test-pe-parser.cpp
|
||||
* @author jtaw5649
|
||||
* @brief Test cases for PE parser helpers
|
||||
* @details
|
||||
* @version 0.19
|
||||
* @date 2026-06-01
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
static constexpr SIZE_T PeFixtureSize = 0x200;
|
||||
static constexpr LONG PeHeaderOffset = 0x80;
|
||||
|
||||
/**
|
||||
* @brief Returns the byte offset of the optional header within the test fixture buffer
|
||||
*
|
||||
* The optional header immediately follows the NT signature DWORD and the
|
||||
* IMAGE_FILE_HEADER at a fixed offset determined by PeHeaderOffset.
|
||||
*
|
||||
* @return SIZE_T Byte offset from the start of the fixture buffer
|
||||
*/
|
||||
static SIZE_T
|
||||
PeOptionalHeaderOffset()
|
||||
{
|
||||
return PeHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the byte offset of the section header table within the test fixture buffer
|
||||
*
|
||||
* The section table begins immediately after the optional header, whose size
|
||||
* is supplied by the caller.
|
||||
*
|
||||
* @param OptionalHeaderSize Size in bytes of the optional header (32-bit or 64-bit variant)
|
||||
*
|
||||
* @return SIZE_T Byte offset from the start of the fixture buffer
|
||||
*/
|
||||
static SIZE_T
|
||||
PeSectionHeaderOffset(SIZE_T OptionalHeaderSize)
|
||||
{
|
||||
return PeOptionalHeaderOffset() + OptionalHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a little-endian 16-bit value into a byte buffer at the given offset
|
||||
*
|
||||
* @param Buffer Pointer to the destination byte buffer
|
||||
* @param Offset Byte offset within Buffer at which to write
|
||||
* @param Value 16-bit value to write in little-endian order
|
||||
*/
|
||||
static VOID
|
||||
WriteWord(BYTE * Buffer, SIZE_T Offset, WORD Value)
|
||||
{
|
||||
Buffer[Offset] = (BYTE)(Value & 0xff);
|
||||
Buffer[Offset + 1] = (BYTE)((Value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a little-endian 32-bit value into a byte buffer at the given offset
|
||||
*
|
||||
* @param Buffer Pointer to the destination byte buffer
|
||||
* @param Offset Byte offset within Buffer at which to write
|
||||
* @param Value 32-bit value to write in little-endian order
|
||||
*/
|
||||
static VOID
|
||||
WriteDword(BYTE * Buffer, SIZE_T Offset, DWORD Value)
|
||||
{
|
||||
Buffer[Offset] = (BYTE)(Value & 0xff);
|
||||
Buffer[Offset + 1] = (BYTE)((Value >> 8) & 0xff);
|
||||
Buffer[Offset + 2] = (BYTE)((Value >> 16) & 0xff);
|
||||
Buffer[Offset + 3] = (BYTE)((Value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds a minimal valid 64-bit PE (PE32+) fixture in the supplied buffer
|
||||
*
|
||||
* Zeroes the buffer, then writes a valid IMAGE_DOS_HEADER pointing to PeHeaderOffset,
|
||||
* an NT signature, an IMAGE_FILE_HEADER with machine type AMD64 and one section,
|
||||
* and an IMAGE_OPTIONAL_HEADER64 magic value. The result is the smallest byte
|
||||
* sequence accepted by PeImageReaderInitialize as a 64-bit PE image.
|
||||
*
|
||||
* @param Buffer Pointer to a buffer of at least PeFixtureSize bytes
|
||||
*/
|
||||
static VOID
|
||||
BuildMinimalPe64(BYTE * Buffer)
|
||||
{
|
||||
ZeroMemory(Buffer, PeFixtureSize);
|
||||
|
||||
WriteWord(Buffer, 0, IMAGE_DOS_SIGNATURE);
|
||||
WriteDword(Buffer, offsetof(IMAGE_DOS_HEADER, e_lfanew), PeHeaderOffset);
|
||||
|
||||
WriteDword(Buffer, PeHeaderOffset, IMAGE_NT_SIGNATURE);
|
||||
WriteWord(Buffer, PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, Machine), IMAGE_FILE_MACHINE_AMD64);
|
||||
WriteWord(Buffer, PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, NumberOfSections), 1);
|
||||
WriteWord(Buffer,
|
||||
PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, SizeOfOptionalHeader),
|
||||
sizeof(IMAGE_OPTIONAL_HEADER64));
|
||||
WriteWord(Buffer,
|
||||
PeHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER),
|
||||
IMAGE_NT_OPTIONAL_HDR64_MAGIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Builds a minimal valid 32-bit PE (PE32) fixture in the supplied buffer
|
||||
*
|
||||
* Zeroes the buffer, then writes a valid IMAGE_DOS_HEADER pointing to PeHeaderOffset,
|
||||
* an NT signature, an IMAGE_FILE_HEADER with machine type I386 and one section,
|
||||
* and an IMAGE_OPTIONAL_HEADER32 magic value. The result is the smallest byte
|
||||
* sequence accepted by PeImageReaderInitialize as a 32-bit PE image.
|
||||
*
|
||||
* @param Buffer Pointer to a buffer of at least PeFixtureSize bytes
|
||||
*/
|
||||
static VOID
|
||||
BuildMinimalPe32(BYTE * Buffer)
|
||||
{
|
||||
ZeroMemory(Buffer, PeFixtureSize);
|
||||
|
||||
WriteWord(Buffer, 0, IMAGE_DOS_SIGNATURE);
|
||||
WriteDword(Buffer, offsetof(IMAGE_DOS_HEADER, e_lfanew), PeHeaderOffset);
|
||||
|
||||
WriteDword(Buffer, PeHeaderOffset, IMAGE_NT_SIGNATURE);
|
||||
WriteWord(Buffer, PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, Machine), IMAGE_FILE_MACHINE_I386);
|
||||
WriteWord(Buffer, PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, NumberOfSections), 1);
|
||||
WriteWord(Buffer,
|
||||
PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, SizeOfOptionalHeader),
|
||||
sizeof(IMAGE_OPTIONAL_HEADER32));
|
||||
WriteWord(Buffer,
|
||||
PeHeaderOffset + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER),
|
||||
IMAGE_NT_OPTIONAL_HDR32_MAGIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the SizeOfHeaders field in the PE64 optional header of a fixture buffer
|
||||
*
|
||||
* Computes the field offset within IMAGE_OPTIONAL_HEADER64 and writes a 32-bit
|
||||
* little-endian value at that position.
|
||||
*
|
||||
* @param Buffer Pointer to a fixture buffer previously initialised by BuildMinimalPe64
|
||||
* @param SizeOfHeaders Value to write into the SizeOfHeaders field
|
||||
*/
|
||||
static VOID
|
||||
SetPe64OptionalHeaderSizeOfHeaders(BYTE * Buffer, DWORD SizeOfHeaders)
|
||||
{
|
||||
SIZE_T Offset = PeOptionalHeaderOffset() + offsetof(IMAGE_OPTIONAL_HEADER64, SizeOfHeaders);
|
||||
|
||||
WriteDword(Buffer, Offset, SizeOfHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the first section header in a fixture buffer
|
||||
*
|
||||
* Computes the section header table offset using OptionalHeaderSize and casts
|
||||
* the corresponding location in Buffer to IMAGE_SECTION_HEADER *.
|
||||
*
|
||||
* @param Buffer Pointer to a fixture buffer
|
||||
* @param OptionalHeaderSize Size in bytes of the optional header used by the fixture
|
||||
*
|
||||
* @return IMAGE_SECTION_HEADER* Pointer to the first section header within the buffer
|
||||
*/
|
||||
static IMAGE_SECTION_HEADER *
|
||||
GetFixtureSectionHeader(BYTE * Buffer, SIZE_T OptionalHeaderSize)
|
||||
{
|
||||
return (IMAGE_SECTION_HEADER *)(Buffer + PeSectionHeaderOffset(OptionalHeaderSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the .text section header in a fixture buffer
|
||||
*
|
||||
* Zeroes the first section header slot, writes the name ".text", and sets
|
||||
* the virtual address, virtual size, raw data pointer, and raw data size
|
||||
* fields to the supplied values.
|
||||
*
|
||||
* @param Buffer Pointer to a fixture buffer
|
||||
* @param OptionalHeaderSize Size in bytes of the optional header used by the fixture
|
||||
* @param VirtualAddress RVA at which the section is loaded
|
||||
* @param VirtualSize Virtual size of the section
|
||||
* @param PointerToRawData Raw file offset of the section data
|
||||
* @param SizeOfRawData Size of the raw data on disk
|
||||
*/
|
||||
static VOID
|
||||
ConfigureTextSection(BYTE * Buffer, SIZE_T OptionalHeaderSize, DWORD VirtualAddress, DWORD VirtualSize, DWORD PointerToRawData, DWORD SizeOfRawData)
|
||||
{
|
||||
IMAGE_SECTION_HEADER * SectionHeader = GetFixtureSectionHeader(Buffer, OptionalHeaderSize);
|
||||
|
||||
ZeroMemory(SectionHeader, sizeof(*SectionHeader));
|
||||
CopyMemory(SectionHeader->Name, ".text", sizeof(".text") - 1);
|
||||
SectionHeader->Misc.VirtualSize = VirtualSize;
|
||||
SectionHeader->VirtualAddress = VirtualAddress;
|
||||
SectionHeader->SizeOfRawData = SizeOfRawData;
|
||||
SectionHeader->PointerToRawData = PointerToRawData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Runs all PE parser unit tests and reports pass/fail results
|
||||
*
|
||||
* Each numbered test case exercises a distinct behaviour of the PE image reader:
|
||||
* 1. A valid PE32+ image initialises successfully and reports 64-bit.
|
||||
* 2. A valid PE32 image initialises successfully and reports 32-bit.
|
||||
* 3. A corrupt DOS magic causes initialisation to fail.
|
||||
* 4. An optional header that is one byte too small causes initialisation to fail.
|
||||
* 5. An e_lfanew value that points past the buffer causes initialisation to fail.
|
||||
* 6. A valid section RVA maps to the correct raw file offset.
|
||||
* 7. Header-range RVA resolution is enforced at SizeOfHeaders boundaries.
|
||||
* 8. An 8-byte section name is always returned null-terminated.
|
||||
* 9. An RVA whose raw mapping extends outside the file is rejected.
|
||||
*
|
||||
* @return BOOLEAN TRUE if all tests pass, FALSE if any test fails
|
||||
*/
|
||||
BOOLEAN
|
||||
TestPeParser()
|
||||
{
|
||||
BOOLEAN OverallResult = TRUE;
|
||||
INT32 TestNum = 0;
|
||||
BYTE Buffer[PeFixtureSize] = {0};
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
|
||||
if (PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader) && !PeImageReaderIs32Bit(&Reader))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] valid PE64 did not initialize as PE32+\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe32(Buffer);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
|
||||
if (PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader) && PeImageReaderIs32Bit(&Reader))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] valid PE32 did not initialize as PE32\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
WriteWord(Buffer, 0, 0);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
|
||||
if (!PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] invalid DOS magic initialized successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
WriteWord(Buffer,
|
||||
PeHeaderOffset + sizeof(DWORD) + offsetof(IMAGE_FILE_HEADER, SizeOfOptionalHeader),
|
||||
sizeof(IMAGE_OPTIONAL_HEADER64) - 1);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
|
||||
if (!PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] truncated optional header initialized successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
WriteDword(Buffer, offsetof(IMAGE_DOS_HEADER, e_lfanew), PeFixtureSize);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
|
||||
if (!PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] invalid e_lfanew initialized successfully\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
SetPe64OptionalHeaderSizeOfHeaders(Buffer, 0x1c0);
|
||||
ConfigureTextSection(Buffer, sizeof(IMAGE_OPTIONAL_HEADER64), 0x1000, 0x50, 0x1c0, 0x40);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
SIZE_T FileOffset = 0;
|
||||
|
||||
if (PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader) &&
|
||||
PeImageReaderRvaToFileOffset(&Reader, 0x1010, 4, &FileOffset) && FileOffset == 0x1d0)
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] valid section RVA did not map to raw file offset\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
SetPe64OptionalHeaderSizeOfHeaders(Buffer, 0x1c0);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
SIZE_T FileOffset = 0;
|
||||
|
||||
if (PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader) &&
|
||||
PeImageReaderRvaToFileOffset(&Reader, 0x20, 4, &FileOffset) && FileOffset == 0x20 &&
|
||||
!PeImageReaderRvaToFileOffset(&Reader, 0x1be, 4, &FileOffset))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] header RVA bounds were not enforced\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
TestNum++;
|
||||
{
|
||||
IMAGE_SECTION_HEADER SectionHeader = {0};
|
||||
CHAR Name[9];
|
||||
|
||||
FillMemory(Name, sizeof(Name), 'X');
|
||||
CopyMemory(SectionHeader.Name, "ABCDEFGH", IMAGE_SIZEOF_SHORT_NAME);
|
||||
if (PeImageReaderGetSectionName(&SectionHeader, Name, sizeof(Name)) &&
|
||||
strcmp(Name, "ABCDEFGH") == 0 && Name[IMAGE_SIZEOF_SHORT_NAME] == '\0')
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] 8-byte section name was not null-terminated\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BuildMinimalPe64(Buffer);
|
||||
SetPe64OptionalHeaderSizeOfHeaders(Buffer, 0x1c0);
|
||||
ConfigureTextSection(Buffer, sizeof(IMAGE_OPTIONAL_HEADER64), 0x1000, 0x40, 0x300, 0x20);
|
||||
TestNum++;
|
||||
{
|
||||
PE_IMAGE_READER Reader = {0};
|
||||
SIZE_T FileOffset = 0;
|
||||
|
||||
if (PeImageReaderInitialize(Buffer, sizeof(Buffer), &Reader) &&
|
||||
!PeImageReaderRvaToFileOffset(&Reader, 0x1000, 1, &FileOffset))
|
||||
{
|
||||
printf("[+] Test number %d Passed\n", TestNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[-] Test number %d Failed\n", TestNum);
|
||||
printf("[x] RVA mapping accepted raw pointer outside file\n");
|
||||
OverallResult = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return OverallResult;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file test-semanitc-scripts.cpp
|
||||
* @file test-semantic-scripts.cpp
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Perform test on semantic scripts
|
||||
* @details
|
||||
|
|
@ -21,7 +21,7 @@ namespace fs = std::filesystem;
|
|||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
ReadDirectoryAndTestSemanticTestcases(const char * ScriptSemanticPath)
|
||||
ReadDirectoryAndTestSemanticTestCases(const CHAR * ScriptSemanticPath)
|
||||
{
|
||||
//
|
||||
// Iterate through the directory
|
||||
|
|
@ -38,7 +38,7 @@ ReadDirectoryAndTestSemanticTestcases(const char * ScriptSemanticPath)
|
|||
//
|
||||
// Get the file path
|
||||
//
|
||||
std::string filePath = entry.path().string();
|
||||
std::string FilePath = entry.path().string();
|
||||
|
||||
//
|
||||
// Output the file name
|
||||
|
|
@ -48,10 +48,10 @@ ReadDirectoryAndTestSemanticTestcases(const char * ScriptSemanticPath)
|
|||
//
|
||||
// Open the file and read its contents
|
||||
//
|
||||
std::ifstream file(filePath);
|
||||
if (file.is_open())
|
||||
std::ifstream File(FilePath);
|
||||
if (File.is_open())
|
||||
{
|
||||
std::string content((std::istreambuf_iterator<char>(file)),
|
||||
std::string Content((std::istreambuf_iterator<char>(File)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
//
|
||||
|
|
@ -64,18 +64,18 @@ ReadDirectoryAndTestSemanticTestcases(const char * ScriptSemanticPath)
|
|||
//
|
||||
// Run the test case command
|
||||
//
|
||||
hyperdbg_u_run_command((CHAR *)content.c_str());
|
||||
hyperdbg_u_run_command((CHAR *)Content.c_str());
|
||||
|
||||
std::cout << "--------------------------------------------" << std::endl;
|
||||
|
||||
//
|
||||
// Close the file
|
||||
//
|
||||
file.close();
|
||||
File.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Could not open file: " << filePath << std::endl;
|
||||
std::cerr << "Could not open file: " << FilePath << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -94,8 +94,8 @@ ReadDirectoryAndTestSemanticTestcases(const char * ScriptSemanticPath)
|
|||
BOOLEAN
|
||||
TestSemanticScripts()
|
||||
{
|
||||
int testNum = 0;
|
||||
CHAR dirPath[MAX_PATH] = {0};
|
||||
INT32 TestNum = 0;
|
||||
CHAR dirPath[MAX_PATH] = {0};
|
||||
|
||||
//
|
||||
// Parse the semantic script test cases from the file
|
||||
|
|
@ -122,7 +122,7 @@ TestSemanticScripts()
|
|||
//
|
||||
// Run test cases
|
||||
//
|
||||
ReadDirectoryAndTestSemanticTestcases(dirPath);
|
||||
ReadDirectoryAndTestSemanticTestCases(dirPath);
|
||||
|
||||
//
|
||||
// Close the connection
|
||||
|
|
|
|||
|
|
@ -11,28 +11,48 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
/**
|
||||
* @brief Convert a UINT64 value to a hex string
|
||||
*
|
||||
* @param Value the value to convert
|
||||
* @return std::string the hex string representation
|
||||
*/
|
||||
std::string
|
||||
Uint64ToString(UINT64 value)
|
||||
Uint64ToString(UINT64 Value)
|
||||
{
|
||||
ostringstream Os;
|
||||
Os << setw(16) << setfill('0') << hex << value;
|
||||
Os << setw(16) << setfill('0') << hex << Value;
|
||||
return Os.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replace the first occurrence of a substring in a string
|
||||
*
|
||||
* @param Str the string to modify
|
||||
* @param From the substring to search for
|
||||
* @param To the replacement substring
|
||||
* @return BOOLEAN TRUE if the replacement was made, FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
StringReplace(std::string & str, const std::string & from, const std::string & to)
|
||||
StringReplace(std::string & Str, const std::string & From, const std::string & To)
|
||||
{
|
||||
size_t start_pos = str.find(from);
|
||||
if (start_pos == string::npos)
|
||||
SIZE_T StartPos = Str.find(From);
|
||||
if (StartPos == string::npos)
|
||||
return FALSE;
|
||||
str.replace(start_pos, from.length(), to);
|
||||
Str.replace(StartPos, From.length(), To);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a C-string to a std::string
|
||||
*
|
||||
* @param Str the C-string to convert
|
||||
* @return std::string the resulting string object
|
||||
*/
|
||||
std::string
|
||||
ConvertToString(char * Str)
|
||||
ConvertToString(CHAR * Str)
|
||||
{
|
||||
string s(Str);
|
||||
string Result(Str);
|
||||
|
||||
return s;
|
||||
return Result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@ HANDLE
|
|||
NamedPipeServerCreatePipe(LPCSTR PipeName, UINT32 OutputBufferSize, UINT32 InputBufferSize);
|
||||
|
||||
BOOLEAN
|
||||
NamedPipeServerWaitForClientConntection(HANDLE PipeHandle);
|
||||
NamedPipeServerWaitForClientConnection(HANDLE PipeHandle);
|
||||
|
||||
UINT32
|
||||
NamedPipeServerReadClientMessage(HANDLE PipeHandle, char * BufferToSave, int MaximumReadBufferLength);
|
||||
NamedPipeServerReadClientMessage(HANDLE PipeHandle, CHAR * BufferToSave, INT32 MaximumReadBufferLength);
|
||||
|
||||
BOOLEAN
|
||||
NamedPipeServerSendMessageToClient(HANDLE PipeHandle,
|
||||
char * BufferToSend,
|
||||
int BufferSize);
|
||||
CHAR * BufferToSend,
|
||||
INT32 BufferSize);
|
||||
|
||||
VOID
|
||||
NamedPipeServerCloseHandle(HANDLE PipeHandle);
|
||||
|
|
@ -40,10 +40,10 @@ HANDLE
|
|||
NamedPipeClientCreatePipe(LPCSTR PipeName);
|
||||
|
||||
BOOLEAN
|
||||
NamedPipeClientSendMessage(HANDLE PipeHandle, char * BufferToSend, int BufferSize);
|
||||
NamedPipeClientSendMessage(HANDLE PipeHandle, CHAR * BufferToSend, INT32 BufferSize);
|
||||
|
||||
UINT32
|
||||
NamedPipeClientReadMessage(HANDLE PipeHandle, char * BufferToRead, int MaximumSizeOfBuffer);
|
||||
NamedPipeClientReadMessage(HANDLE PipeHandle, CHAR * BufferToRead, INT32 MaximumSizeOfBuffer);
|
||||
|
||||
VOID
|
||||
NamedPipeClientClosePipe(HANDLE PipeHandle);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ TestCase(std::vector<std::string> & TestCase);
|
|||
//////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
extern void inline AsmTest();
|
||||
extern VOID inline AsmTest();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
|
@ -37,10 +37,10 @@ TestCreateLookupTable(HANDLE PipeHandle, PVOID KernelInformation, UINT32 KernelI
|
|||
//////////////////////////////////////////////////
|
||||
|
||||
std::string
|
||||
Uint64ToString(UINT64 value);
|
||||
Uint64ToString(UINT64 Value);
|
||||
|
||||
BOOLEAN
|
||||
StringReplace(std::string & str, const std::string & from, const std::string & to);
|
||||
StringReplace(std::string & Str, const std::string & From, const std::string & To);
|
||||
|
||||
std::string
|
||||
ConvertToString(char * Str);
|
||||
ConvertToString(CHAR * Str);
|
||||
|
|
|
|||
|
|
@ -18,5 +18,11 @@
|
|||
BOOLEAN
|
||||
TestCommandParser();
|
||||
|
||||
BOOLEAN
|
||||
TestPeParser();
|
||||
|
||||
BOOLEAN
|
||||
TestCodeViewRsdsParser();
|
||||
|
||||
BOOLEAN
|
||||
TestSemanticScripts();
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);$(SolutionDir)libhyperdbg;$(SolutionDir)symbol-parser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\include;$(SolutionDir)dependencies;$(ProjectDir);$(SolutionDir)libhyperdbg;$(SolutionDir)symbol-parser;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
|
|
@ -103,19 +103,27 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\include\components\pe\code\pe-image-reader.cpp" />
|
||||
<ClCompile Include="code\hardware\hwdbg-tests.cpp" />
|
||||
<ClCompile Include="..\symbol-parser\code\codeview-rsds.cpp" />
|
||||
<ClCompile Include="..\symbol-parser\code\pdb-identity.cpp" />
|
||||
<ClCompile Include="code\main.cpp" />
|
||||
<ClCompile Include="code\namedpipe.cpp" />
|
||||
<ClCompile Include="code\tests\test-codeview-rsds-parser.cpp" />
|
||||
<ClCompile Include="code\tests\test-pe-parser.cpp" />
|
||||
<ClCompile Include="code\tests\test-parser.cpp" />
|
||||
<ClCompile Include="code\tests\test-semantic-scripts.cpp" />
|
||||
<ClCompile Include="code\tools.cpp" />
|
||||
<ClCompile Include="pch.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\components\pe\header\pe-image-reader.h" />
|
||||
<ClInclude Include="header\hwdbg-tests.h" />
|
||||
<ClInclude Include="header\namedpipe.h" />
|
||||
<ClInclude Include="header\routines.h" />
|
||||
<ClInclude Include="header\testcases.h" />
|
||||
<ClInclude Include="..\symbol-parser\header\codeview-rsds.h" />
|
||||
<ClInclude Include="..\symbol-parser\header\pdb-identity.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -126,4 +134,4 @@
|
|||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\marmasm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -21,11 +21,29 @@
|
|||
<Filter Include="code\hardware">
|
||||
<UniqueIdentifier>{18515e99-bdbe-465f-9c92-58dc89591116}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="code\components">
|
||||
<UniqueIdentifier>{4905a2c5-31b5-4b16-9f84-d2b3b39726d3}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="code\components\pe">
|
||||
<UniqueIdentifier>{2835e8e0-5525-473b-ae43-c498674fb42e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="header\components">
|
||||
<UniqueIdentifier>{b36455ac-6726-4c17-903c-3c3e3de1b783}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="header\components\pe">
|
||||
<UniqueIdentifier>{b3920039-7e86-412e-bf10-8a5a7946e102}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="code\tests\test-parser.cpp">
|
||||
<Filter>code\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\tests\test-pe-parser.cpp">
|
||||
<Filter>code\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\tests\test-codeview-rsds-parser.cpp">
|
||||
<Filter>code\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\namedpipe.cpp">
|
||||
<Filter>code</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -41,9 +59,18 @@
|
|||
<ClCompile Include="code\hardware\hwdbg-tests.cpp">
|
||||
<Filter>code\hardware</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\symbol-parser\code\codeview-rsds.cpp">
|
||||
<Filter>code\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\symbol-parser\code\pdb-identity.cpp">
|
||||
<Filter>code\tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>code</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\components\pe\code\pe-image-reader.cpp">
|
||||
<Filter>code\components\pe</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="header\namedpipe.h">
|
||||
|
|
@ -61,10 +88,19 @@
|
|||
<ClInclude Include="pch.h">
|
||||
<Filter>header</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\components\pe\header\pe-image-reader.h">
|
||||
<Filter>header\components\pe</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\symbol-parser\header\codeview-rsds.h">
|
||||
<Filter>header</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\symbol-parser\header\pdb-identity.h">
|
||||
<Filter>header</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="code\assembly\asm-test.asm">
|
||||
<Filter>code\assembly</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -34,20 +34,32 @@ using namespace std;
|
|||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <strsafe.h>
|
||||
|
||||
//
|
||||
// SDK and config headers
|
||||
//
|
||||
#include "SDK/HyperDbgSdk.h"
|
||||
#include "config/Definition.h"
|
||||
|
||||
//
|
||||
// Program Defined Headers
|
||||
//
|
||||
#include "SDK/HyperDbgSdk.h"
|
||||
#include "config/Definition.h"
|
||||
#include "../hyperdbg-test/header/namedpipe.h"
|
||||
#include "../hyperdbg-test/header/routines.h"
|
||||
#include "../hyperdbg-test/header/testcases.h"
|
||||
#include "header/namedpipe.h"
|
||||
#include "header/routines.h"
|
||||
#include "header/testcases.h"
|
||||
#include "header/pdb-identity.h"
|
||||
#include "header/codeview-rsds.h"
|
||||
|
||||
//
|
||||
// Components
|
||||
//
|
||||
#include "../include/components/pe/header/pe-image-reader.h"
|
||||
|
||||
//
|
||||
// Hardware Debugger Headers
|
||||
//
|
||||
#include "../hyperdbg-test/header/hwdbg-tests.h"
|
||||
#include "header/hwdbg-tests.h"
|
||||
|
||||
//
|
||||
// import libhyperdbg
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "headers", "headers", "{D67D
|
|||
include\SDK\Headers\Ioctls.h = include\SDK\Headers\Ioctls.h
|
||||
include\SDK\headers\LbrDefinitions.h = include\SDK\headers\LbrDefinitions.h
|
||||
include\SDK\headers\Pcie.h = include\SDK\headers\Pcie.h
|
||||
include\SDK\headers\PortableExecutable.h = include\SDK\headers\PortableExecutable.h
|
||||
include\SDK\headers\PtDefinitions.h = include\SDK\headers\PtDefinitions.h
|
||||
include\SDK\Headers\RequestStructures.h = include\SDK\Headers\RequestStructures.h
|
||||
include\SDK\Headers\ScriptEngineCommonDefinitions.h = include\SDK\Headers\ScriptEngineCommonDefinitions.h
|
||||
include\SDK\Headers\Symbols.h = include\SDK\Headers\Symbols.h
|
||||
|
|
@ -291,6 +293,40 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "kernel", "kernel", "{09E02C
|
|||
linux\mock\kernel\pch.h = linux\mock\kernel\pch.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "windows-only", "windows-only", "{C95E342A-9622-4351-8177-CDA43A52E7B2}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\platform\user\header\windows-only\windows-privilege.h = include\platform\user\header\windows-only\windows-privilege.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "windows-only", "windows-only", "{45ABB14F-86B9-40BE-9C0F-213653CE6A93}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\platform\user\code\windows-only\windows-privilege.c = include\platform\user\code\windows-only\windows-privilege.c
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "callback", "callback", "{1AA10217-07BF-490B-A688-1D1D6A267D52}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{78821DCF-DCFE-45B7-A9DD-3543BDF1FB9E}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\components\callback\hyperlog\code\HyperLogCallback.c = include\components\callback\hyperlog\code\HyperLogCallback.c
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{AD02B952-0D75-47FE-8FF7-18B3E081E2C1}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\components\callback\hyperlog\header\HyperLogCallback.h = include\components\callback\hyperlog\header\HyperLogCallback.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pe", "pe", "{9A0232BB-B06B-47EE-A096-E7B475956437}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "code", "code", "{824DF7C7-18B5-48DE-99D7-AD6B612D6204}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\components\pe\code\pe-image-reader.cpp = include\components\pe\code\pe-image-reader.cpp
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "header", "header", "{CA2D9C24-F90A-48ED-8ABC-F296674EA2B7}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
include\components\pe\header\pe-image-reader.h = include\components\pe\header\pe-image-reader.h
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
debug|x64 = debug|x64
|
||||
|
|
@ -390,6 +426,14 @@ Global
|
|||
{848FE945-4F37-4B5B-98C8-F22CA3AA7184} = {17652C16-00A0-40D4-A227-697E595DE053}
|
||||
{D3722A82-0A54-4172-A0C1-1EA6500E9F1E} = {770B65D6-5307-478C-A9EB-3E4A64B67225}
|
||||
{09E02C0A-6A6C-408A-8136-C787FDC58A5F} = {770B65D6-5307-478C-A9EB-3E4A64B67225}
|
||||
{C95E342A-9622-4351-8177-CDA43A52E7B2} = {DBE32379-8D5A-4454-A1B6-ACC407881898}
|
||||
{45ABB14F-86B9-40BE-9C0F-213653CE6A93} = {4BF590C3-1032-4DD2-BF87-BB9E5781977C}
|
||||
{1AA10217-07BF-490B-A688-1D1D6A267D52} = {DF15E9D4-976B-4E1D-B68F-9B67F93654BF}
|
||||
{78821DCF-DCFE-45B7-A9DD-3543BDF1FB9E} = {1AA10217-07BF-490B-A688-1D1D6A267D52}
|
||||
{AD02B952-0D75-47FE-8FF7-18B3E081E2C1} = {1AA10217-07BF-490B-A688-1D1D6A267D52}
|
||||
{9A0232BB-B06B-47EE-A096-E7B475956437} = {DF15E9D4-976B-4E1D-B68F-9B67F93654BF}
|
||||
{824DF7C7-18B5-48DE-99D7-AD6B612D6204} = {9A0232BB-B06B-47EE-A096-E7B475956437}
|
||||
{CA2D9C24-F90A-48ED-8ABC-F296674EA2B7} = {9A0232BB-B06B-47EE-A096-E7B475956437}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1444BEC7-11CE-4CA6-B77C-5F98AC9BFAEB}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,33 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
#if ActivateHyperEvadeProject != TRUE
|
||||
|
||||
/**
|
||||
* @brief Handle The triggered hook on KiSystemCall64 system call handler
|
||||
* when the Transparency mode is disabled
|
||||
*
|
||||
* @param Regs The virtual processor's state of registers
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
TransparentHandleSystemCallHook(GUEST_REGS * Regs)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Regs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle returns from the syscall
|
||||
* when the Transparency mode is disabled
|
||||
*
|
||||
* @param Regs The virtual processor's state of registers
|
||||
* @param ProcessId The process id of the thread
|
||||
* @param ThreadId The thread id of the thread
|
||||
* @param Context The context of the caller
|
||||
* @param Params The (optional) parameters of the caller
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
TransparentCallbackHandleAfterSyscall(GUEST_REGS * Regs,
|
||||
UINT32 ProcessId,
|
||||
|
|
@ -31,7 +52,7 @@ TransparentCallbackHandleAfterSyscall(GUEST_REGS * Regs,
|
|||
UNREFERENCED_PARAMETER(Params);
|
||||
}
|
||||
|
||||
#if DISABLE_HYPERDBG_HYPEREVADE == FALSE
|
||||
#else // ActivateHyperEvadeProject != TRUE
|
||||
|
||||
/**
|
||||
* @brief Handle The triggered hook on KiSystemCall64 system call handler
|
||||
|
|
@ -805,7 +826,7 @@ TransparentHandleNtEnumerateKeySyscall(GUEST_REGS * Regs)
|
|||
* it is possible to still detect that some tampering was done from the user space
|
||||
*
|
||||
* @param Ptr The pointer to a valid read/writable SYSTEM_MODULE_INFORMATION memory buffer
|
||||
* @param VirualAddress A pointer to a user-mode virtual address
|
||||
* @param VirtualAddress A pointer to a user-mode virtual address
|
||||
* @param BufferSize Size of the user-mode buffer
|
||||
*
|
||||
* @return BOOLEAN
|
||||
|
|
@ -822,11 +843,11 @@ TransparentHandleModuleInformationQuery(PVOID Ptr, UINT64 VirtualAddress, UINT32
|
|||
//
|
||||
for (UINT16 i = 0; i < StructBuf->Count; i++)
|
||||
{
|
||||
PCHAR path = (PCHAR)ModuleList[i].FullPathName;
|
||||
PCHAR Path = (PCHAR)ModuleList[i].FullPathName;
|
||||
|
||||
for (UINT16 j = 0; j < (sizeof(HV_DRIVER) / sizeof(HV_DRIVER[0])); j++)
|
||||
{
|
||||
if (strstr(path, HV_DRIVER[j]))
|
||||
if (strstr(Path, HV_DRIVER[j]))
|
||||
{
|
||||
//
|
||||
// If a module file name matches, remove the entry from the list by shifting it forward by one entry
|
||||
|
|
@ -934,9 +955,9 @@ TransparentHandleProcessInformationQuery(SYSCALL_CALLBACK_CONTEXT_PARAMS * Param
|
|||
//
|
||||
// Loop through the known list of identifiable hypervisor related processes
|
||||
//
|
||||
for (UINT16 i = 0; i < (sizeof(HV_Processes) / sizeof(HV_Processes[0])); i++)
|
||||
for (UINT16 i = 0; i < (sizeof(HV_PROCESSES) / sizeof(HV_PROCESSES[0])); i++)
|
||||
{
|
||||
if (!_wcsnicmp(ImageName, HV_Processes[i], (CurStructBuf.ImageName.Length) / sizeof(WCHAR)))
|
||||
if (!_wcsnicmp(ImageName, HV_PROCESSES[i], (CurStructBuf.ImageName.Length) / sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// If the name matches, bypass it by increasing the previous entries .nextEntryOffset value
|
||||
|
|
@ -1037,7 +1058,7 @@ TransparentHandleProcessInformationQuery(SYSCALL_CALLBACK_CONTEXT_PARAMS * Param
|
|||
/**
|
||||
* @brief Handle the request for SystemFirmwareTableInformation
|
||||
*
|
||||
* @param ptr The pointer to a valid read/writable SYSTEM_FIRMWARE_TABLE_INFORMATION memory buffer
|
||||
* @param Ptr The pointer to a valid read/writable SYSTEM_FIRMWARE_TABLE_INFORMATION memory buffer
|
||||
* @param BufMaxSize The size of the allocated user-mode buffer
|
||||
* @param BufSizePtr A pointer to a ULONG field containing the size of the written data
|
||||
*
|
||||
|
|
@ -1146,9 +1167,9 @@ TransparentHandleFirmwareInformationQuery(UINT64 Ptr, UINT32 BufMaxSize, UINT64
|
|||
//
|
||||
|
||||
ULONG MatchedStringLen = (ULONG)strlen(HV_FIRM_NAMES[i]);
|
||||
ULONG oldLength = StructBuf->TableBufferLength;
|
||||
ULONG OldLength = StructBuf->TableBufferLength;
|
||||
|
||||
ULONG NewStringSize = oldLength - MatchedStringLen + NewSubstringSize;
|
||||
ULONG NewStringSize = OldLength - MatchedStringLen + NewSubstringSize;
|
||||
|
||||
//
|
||||
// Check if the buffer size allows the modification, in case of expansion
|
||||
|
|
@ -1165,7 +1186,7 @@ TransparentHandleFirmwareInformationQuery(UINT64 Ptr, UINT32 BufMaxSize, UINT64
|
|||
//
|
||||
// Update the required buffer size for the next call
|
||||
//
|
||||
BufSize = (BufSize - oldLength) + NewStringSize;
|
||||
BufSize = (BufSize - OldLength) + NewStringSize;
|
||||
g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(BufSizePtr, &BufSize, sizeof(ULONG));
|
||||
|
||||
//
|
||||
|
|
@ -1186,7 +1207,7 @@ TransparentHandleFirmwareInformationQuery(UINT64 Ptr, UINT32 BufMaxSize, UINT64
|
|||
// Move the data after the matched string forward
|
||||
// and replace the identified hypervisor string with the genuine one
|
||||
//
|
||||
memmove((PVOID)(StringBuf + MatchOffset + NewSubstringSize), (PVOID)MatchEnd, oldLength - MatchedStringLen - MatchOffset);
|
||||
memmove((PVOID)(StringBuf + MatchOffset + NewSubstringSize), (PVOID)MatchEnd, OldLength - MatchedStringLen - MatchOffset);
|
||||
memcpy((PVOID)MatchStart, (PVOID)NewVendorString, NewSubstringSize);
|
||||
|
||||
StructBuf->TableBufferLength = NewStringSize;
|
||||
|
|
@ -1230,8 +1251,8 @@ TransparentHandleFirmwareInformationQuery(UINT64 Ptr, UINT32 BufMaxSize, UINT64
|
|||
UINT64
|
||||
TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS * Params, ULONG DataOffset, ULONG DataLenOffset)
|
||||
{
|
||||
PVOID Buf = NULL;
|
||||
BOOL PoolAlloc = FALSE;
|
||||
PVOID Buf = NULL;
|
||||
BOOLEAN PoolAlloc = FALSE;
|
||||
|
||||
//
|
||||
// Check that the user provided pointers are safe to read from
|
||||
|
|
@ -1313,7 +1334,7 @@ TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS *
|
|||
//
|
||||
// SPOOFS PCI device ID's(in the registry), This might be implemented in other ways that are not part of this implementation
|
||||
//
|
||||
WORD Idx = TRANSPARENT_GENUINE_VENDOR_STRING_INDEX % (sizeof(TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR) / sizeof(TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR[0]));
|
||||
WORD Idx = g_TransparentGenuineVendorStringIndex % (sizeof(TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR) / sizeof(TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR[0]));
|
||||
NewVendorString = TRANSPARENT_LEGIT_DEVICE_ID_VENDOR_STRINGS_WCHAR[Idx];
|
||||
}
|
||||
|
||||
|
|
@ -1329,23 +1350,23 @@ TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS *
|
|||
//
|
||||
// Obtain the replacement vendor name string, randomized when the transparency mode was enabled
|
||||
//
|
||||
NewVendorString = TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[TRANSPARENT_GENUINE_VENDOR_STRING_INDEX];
|
||||
NewVendorString = TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[g_TransparentGenuineVendorStringIndex];
|
||||
}
|
||||
|
||||
//
|
||||
// Obtain the lengths of all the strings and substring
|
||||
//
|
||||
ULONG tempSize = (ULONG)wcslen(NewVendorString) * sizeof(WCHAR);
|
||||
ULONG TempSize = (ULONG)wcslen(NewVendorString) * sizeof(WCHAR);
|
||||
|
||||
ULONG MatchedStringLen = (ULONG)wcslen(HV_REGKEYS[i]) * sizeof(WCHAR);
|
||||
ULONG oldLength = *((PBYTE)Buf + DataLenOffset);
|
||||
ULONG OldLength = *((PBYTE)Buf + DataLenOffset);
|
||||
|
||||
ULONG NewStringSize = oldLength - MatchedStringLen + tempSize;
|
||||
ULONG NewStringSize = OldLength - MatchedStringLen + TempSize;
|
||||
|
||||
//
|
||||
// Check if the buffer size allows the modification, in case of expansion
|
||||
//
|
||||
if (BufSize - MatchedStringLen + tempSize > Params->OptionalParam3)
|
||||
if (BufSize - MatchedStringLen + TempSize > Params->OptionalParam3)
|
||||
{
|
||||
//
|
||||
// If adding the new string exceeds the user allocated size,
|
||||
|
|
@ -1357,7 +1378,7 @@ TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS *
|
|||
//
|
||||
// Update the required buffer size for the next call
|
||||
//
|
||||
BufSize = (tempSize - MatchedStringLen) + oldLength;
|
||||
BufSize = (TempSize - MatchedStringLen) + OldLength;
|
||||
g_Callbacks.MemoryMapperWriteMemorySafeOnTargetProcess(Params->OptionalParam4, &BufSize, sizeof(ULONG));
|
||||
|
||||
//
|
||||
|
|
@ -1378,15 +1399,15 @@ TransparentReplaceVendorStringFromBufferWChar(SYSCALL_CALLBACK_CONTEXT_PARAMS *
|
|||
//
|
||||
// Move the data after the matched string forward
|
||||
//
|
||||
memmove((PVOID)(StringBuf + MatchOffset + (tempSize / sizeof(WCHAR))), (PVOID)MatchEnd, oldLength - MatchedStringLen - (MatchOffset * sizeof(WCHAR)));
|
||||
memmove((PVOID)(StringBuf + MatchOffset + (TempSize / sizeof(WCHAR))), (PVOID)MatchEnd, OldLength - MatchedStringLen - (MatchOffset * sizeof(WCHAR)));
|
||||
|
||||
//
|
||||
// Replace the identified hypervisor string with the genuine one, if needed
|
||||
//
|
||||
memcpy((PVOID)MatchStart, (PVOID)NewVendorString, tempSize);
|
||||
memcpy((PVOID)MatchStart, (PVOID)NewVendorString, TempSize);
|
||||
|
||||
*(PULONG)((PBYTE)Buf + DataLenOffset) = NewStringSize;
|
||||
BufSize = BufSize - MatchedStringLen + tempSize;
|
||||
BufSize = BufSize - MatchedStringLen + TempSize;
|
||||
|
||||
//
|
||||
// Write the changes back to the user buffers
|
||||
|
|
@ -1519,7 +1540,7 @@ TransparentCallbackHandleAfterNtQueryValueKeySyscall(SYSCALL_CALLBACK_CONTEXT_PA
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function to handle the returns from the NtQueryValueKey syscall
|
||||
* @brief Callback function to handle the returns from the NtEnumerateKey syscall
|
||||
*
|
||||
* @param Params The set transparent callback params that contain:
|
||||
in OptionalParam1 the KEY_VALUE_INFORMATION_CLASS enum value
|
||||
|
|
@ -1949,4 +1970,4 @@ TransparentCallbackHandleAfterSyscall(GUEST_REGS * Regs,
|
|||
Params->OptionalParam4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // ActivateHyperEvadeProject != TRUE
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file Transparency.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief Try to hide the debugger from anti-debugging and anti-hypervisor methods
|
||||
* @details
|
||||
* @version 0.1
|
||||
|
|
@ -14,8 +15,8 @@
|
|||
/**
|
||||
* @brief Hide debugger on transparent-mode (activate transparent-mode)
|
||||
*
|
||||
* @param HyperevadeCallbacks
|
||||
* @param TransparentModeRequest
|
||||
* @param HyperevadeCallbacks Pointer to the HyperEvade callbacks structure
|
||||
* @param TransparentModeRequest Pointer to the transparent debugger mode request
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
|
|
@ -23,6 +24,19 @@ BOOLEAN
|
|||
TransparentHideDebugger(HYPEREVADE_CALLBACKS * HyperevadeCallbacks,
|
||||
DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest)
|
||||
{
|
||||
UINT32 EvadeMask = TransparentModeRequest->EvadeMask;
|
||||
|
||||
if (EvadeMask == 0)
|
||||
{
|
||||
EvadeMask = TRANSPARENT_EVADE_MASK_DEFAULT;
|
||||
}
|
||||
|
||||
if ((EvadeMask & ~TRANSPARENT_EVADE_MASK_ALL) != 0)
|
||||
{
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if any of the required callbacks are NULL
|
||||
//
|
||||
|
|
@ -54,18 +68,20 @@ TransparentHideDebugger(HYPEREVADE_CALLBACKS * Hyperevade
|
|||
RtlCopyBytes(&g_SystemCallNumbersInformation,
|
||||
&TransparentModeRequest->SystemCallNumbersInformation,
|
||||
sizeof(SYSTEM_CALL_NUMBERS_INFORMATION));
|
||||
#if DISABLE_HYPERDBG_HYPEREVADE == FALSE
|
||||
#if ActivateHyperEvadeProject == TRUE
|
||||
//
|
||||
// Choose a random genuine vendor string to replace hypervisor vendor data
|
||||
//
|
||||
TRANSPARENT_GENUINE_VENDOR_STRING_INDEX = TransparentGetRand() %
|
||||
(sizeof(TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR) / sizeof(TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[0]));
|
||||
g_TransparentGenuineVendorStringIndex = TransparentGetRand() %
|
||||
(sizeof(TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR) / sizeof(TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[0]));
|
||||
#endif
|
||||
|
||||
//
|
||||
// Enable the transparent mode
|
||||
//
|
||||
g_TransparentMode = TRUE;
|
||||
g_TransparentEvadeMask = EvadeMask;
|
||||
TransparentModeRequest->EvadeMask = EvadeMask;
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
//
|
||||
|
|
@ -93,7 +109,8 @@ TransparentUnhideDebugger()
|
|||
//
|
||||
// Disable the transparent-mode
|
||||
//
|
||||
g_TransparentMode = FALSE;
|
||||
g_TransparentMode = FALSE;
|
||||
g_TransparentEvadeMask = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -125,7 +142,7 @@ TransparentGetRand()
|
|||
* @brief Add name or process id of the target process to the list
|
||||
* of processes that HyperDbg should apply transparent-mode on them
|
||||
*
|
||||
* @param Measurements
|
||||
* @param Measurements Pointer to the debugger hide and transparent mode request structure
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
|
|
@ -189,8 +206,8 @@ TransparentAddNameOrProcessIdToTheList(PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_M
|
|||
//
|
||||
// Move the process name string to the end of the buffer
|
||||
//
|
||||
RtlCopyBytes((void *)((UINT64)PidAndNameBuffer + sizeof(TRANSPARENCY_PROCESS)),
|
||||
(const void *)((UINT64)Measurements + sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)),
|
||||
RtlCopyBytes((VOID *)((UINT64)PidAndNameBuffer + sizeof(TRANSPARENCY_PROCESS)),
|
||||
(CONST VOID *)((UINT64)Measurements + sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)),
|
||||
Measurements->LengthOfProcessName);
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file UnloadDll.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Unloading DLL in the target Windows
|
||||
*
|
||||
* @details
|
||||
* @version 0.4
|
||||
* @date 2023-07-06
|
||||
*
|
||||
|
|
@ -18,6 +18,12 @@
|
|||
// other module remains loaded in the memory.
|
||||
//
|
||||
|
||||
/**
|
||||
* @brief Routine called on DLL initialization
|
||||
*
|
||||
* @param RegistryPath The registry path of the driver
|
||||
* @return NTSTATUS
|
||||
*/
|
||||
NTSTATUS
|
||||
DllInitialize(
|
||||
_In_ PUNICODE_STRING RegistryPath)
|
||||
|
|
@ -27,8 +33,13 @@ DllInitialize(
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Routine called on DLL unload
|
||||
*
|
||||
* @return NTSTATUS
|
||||
*/
|
||||
NTSTATUS
|
||||
DllUnload(void)
|
||||
DllUnload(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file VmxFootprints.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief Try to hide VMX methods from anti-debugging and anti-hypervisor
|
||||
* @details
|
||||
* @version 0.14
|
||||
|
|
@ -22,6 +23,11 @@
|
|||
VOID
|
||||
TransparentCheckAndModifyCpuid(PGUEST_REGS Regs, INT32 CpuInfo[])
|
||||
{
|
||||
if ((g_TransparentEvadeMask & TRANSPARENT_EVADE_MASK_CPUID) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Regs->rax == CPUID_PROCESSOR_AND_PROCESSOR_FEATURE_IDENTIFIERS)
|
||||
{
|
||||
//
|
||||
|
|
@ -50,6 +56,14 @@ TransparentCheckAndModifyCpuid(PGUEST_REGS Regs, INT32 CpuInfo[])
|
|||
BOOLEAN
|
||||
TransparentCheckAndModifyMsrRead(PGUEST_REGS Regs, UINT32 TargetMsr)
|
||||
{
|
||||
if ((g_TransparentEvadeMask & TRANSPARENT_EVADE_MASK_MSR) == 0)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Regs);
|
||||
UNREFERENCED_PARAMETER(TargetMsr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// The MSR range between 40000000H and 400000F0H is reserved and usually used by hypervisors
|
||||
// when the guest operating system is Windows to indicate the OS identifier
|
||||
|
|
@ -92,6 +106,14 @@ TransparentCheckAndModifyMsrRead(PGUEST_REGS Regs, UINT32 TargetMsr)
|
|||
BOOLEAN
|
||||
TransparentCheckAndModifyMsrWrite(PGUEST_REGS Regs, UINT32 TargetMsr)
|
||||
{
|
||||
if ((g_TransparentEvadeMask & TRANSPARENT_EVADE_MASK_MSR) == 0)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Regs);
|
||||
UNREFERENCED_PARAMETER(TargetMsr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// if (TargetMsr >= RESERVED_MSR_RANGE_LOW && TargetMsr <= RESERVED_MSR_RANGE_HI)
|
||||
// {
|
||||
// //
|
||||
|
|
@ -130,6 +152,11 @@ TransparentCheckAndModifyMsrWrite(PGUEST_REGS Regs, UINT32 TargetMsr)
|
|||
VOID
|
||||
TransparentCheckAndTrapFlagAfterVmexit()
|
||||
{
|
||||
if ((g_TransparentEvadeMask & TRANSPARENT_EVADE_MASK_TRAP_FLAG) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If RIP is incremented, then we emulate an instruction, and then
|
||||
// we need to handle the trap flag if it is set in a guest
|
||||
|
|
|
|||
|
|
@ -81,17 +81,17 @@ typedef struct _SYSTEM_PROCESS_INFORMATION
|
|||
* @brief SSDT structure
|
||||
*
|
||||
*/
|
||||
typedef struct _SSDTStruct
|
||||
typedef struct _SSDT_STRUCT
|
||||
{
|
||||
LONG * pServiceTable;
|
||||
PVOID pCounterTable;
|
||||
LONG * ServiceTable;
|
||||
PVOID CounterTable;
|
||||
#ifdef _WIN64
|
||||
UINT64 NumberOfServices;
|
||||
#else
|
||||
ULONG NumberOfServices;
|
||||
#endif
|
||||
PCHAR pArgumentTable;
|
||||
} SSDTStruct, *PSSDTStruct;
|
||||
PCHAR ArgumentTable;
|
||||
} SSDT_STRUCT, *PSSDT_STRUCT;
|
||||
|
||||
/**
|
||||
* @brief Module entry
|
||||
|
|
@ -128,7 +128,7 @@ typedef NTSTATUS(NTAPI * ZWQUERYSYSTEMINFORMATION)(
|
|||
IN ULONG SystemInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL);
|
||||
|
||||
NTSTATUS(*NtCreateFileOrig)
|
||||
NTSTATUS(*g_NtCreateFileOrig)
|
||||
(
|
||||
PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
|
|
@ -150,7 +150,7 @@ NTSTATUS(*NtCreateFileOrig)
|
|||
* @brief A variable holding the randomly chosen index for the genuine vendor list.
|
||||
* This is used for transparent vendor spoofing
|
||||
*/
|
||||
static WORD TRANSPARENT_GENUINE_VENDOR_STRING_INDEX = 0;
|
||||
static WORD g_TransparentGenuineVendorStringIndex = 0;
|
||||
|
||||
/**
|
||||
* @brief System call numbers information
|
||||
|
|
@ -161,7 +161,7 @@ SYSTEM_CALL_NUMBERS_INFORMATION g_SystemCallNumbersInformation;
|
|||
// Constants //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#if DISABLE_HYPERDBG_HYPEREVADE == FALSE
|
||||
#if ActivateHyperEvadeProject == TRUE
|
||||
|
||||
/**
|
||||
* @brief A list of windows processes, for which to ignore systemcall requests
|
||||
|
|
@ -241,7 +241,7 @@ static const PWCHAR TRANSPARENT_LEGIT_VENDOR_STRINGS_WCHAR[] = {
|
|||
* @brief A list of common Hypervisor specific process executables
|
||||
*
|
||||
*/
|
||||
static const PWCH HV_Processes[] = {
|
||||
static const PWCH HV_PROCESSES[] = {
|
||||
L"hyperdbg-cli.exe",
|
||||
L"vboxservice.exe",
|
||||
L"vmsrvc.exe",
|
||||
|
|
@ -559,11 +559,12 @@ static const PWCH HV_REGKEYS[] = {
|
|||
|
||||
};
|
||||
|
||||
//
|
||||
// @brief A list of registry keys which might contain hypervisor vendor information in their data
|
||||
//
|
||||
// NOTE: This is not a complete list, there are a lot of generic keys that also can have the identifiable data
|
||||
//
|
||||
/**
|
||||
* @brief A list of registry keys which might contain hypervisor vendor information in their data
|
||||
*
|
||||
* @details NOTE: This is not a complete list, there are a lot of generic keys that also can have the identifiable data
|
||||
*
|
||||
*/
|
||||
static const PWCH TRANSPARENT_DETECTABLE_REGISTRY_KEYS[] = {
|
||||
L"AcpiData",
|
||||
L"SMBiosData",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file Transparency.h
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief hide the debugger from anti-debugging and anti-hypervisor methods (headers)
|
||||
* @details
|
||||
* @version 0.1
|
||||
|
|
@ -64,6 +65,12 @@ typedef struct _TRANSPARENCY_PROCESS
|
|||
*/
|
||||
BOOLEAN g_TransparentMode;
|
||||
|
||||
/**
|
||||
* @brief The enabled transparent-mode feature mask
|
||||
*
|
||||
*/
|
||||
UINT32 g_TransparentEvadeMask;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* @file VmxFootprint.h
|
||||
* @file VmxFootprints.h
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Hide the debugger from VMX-footrpints of anti-debugging and anti-hypervisor methods (headers)
|
||||
* @brief Hide the debugger from VMX-footprints of anti-debugging and anti-hypervisor methods (headers)
|
||||
* @details
|
||||
* @version 0.14
|
||||
* @date 2024-08-06
|
||||
|
|
|
|||
|
|
@ -23,13 +23,6 @@
|
|||
|
||||
#ifdef HYPERDBG_ENV_WINDOWS
|
||||
|
||||
//
|
||||
// The DLL is flagged by antivirus software, since it contains anti-debugging and anti-hypervisor methods
|
||||
// as well as different anti-debugging strings
|
||||
// For now, we disable the HyperDbg Hyperevade module
|
||||
//
|
||||
# define DISABLE_HYPERDBG_HYPEREVADE TRUE
|
||||
|
||||
//
|
||||
// Windows defined functions
|
||||
//
|
||||
|
|
@ -68,7 +61,7 @@
|
|||
//
|
||||
// Hyperlog headers
|
||||
//
|
||||
#include "components/interface/HyperLogCallback.h"
|
||||
#include "components/callback/header/HyperLogCallback.h"
|
||||
#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h"
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@
|
|||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\include\components\interface\HyperLogCallback.c" />
|
||||
<ClCompile Include="..\include\components\callback\code\HyperLogCallback.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\AvlTree.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\BinarySearch.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\InsertionSort.c" />
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
<ClCompile Include="code\VmxFootprints.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\components\interface\HyperLogCallback.h" />
|
||||
<ClInclude Include="..\include\components\callback\header\HyperLogCallback.h" />
|
||||
<ClInclude Include="..\include\platform\kernel\header\PlatformIntrinsics.h" />
|
||||
<ClInclude Include="..\include\platform\kernel\header\PlatformMem.h" />
|
||||
<ClInclude Include="header\SyscallFootprints.h" />
|
||||
|
|
|
|||
|
|
@ -28,11 +28,14 @@
|
|||
<Filter Include="code\components\optimizations">
|
||||
<UniqueIdentifier>{da60b9fe-3816-4f3c-a6a9-21accd463156}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="code\interface">
|
||||
<UniqueIdentifier>{895edb89-17e8-4a1e-a648-b0ea360e98f8}</UniqueIdentifier>
|
||||
<Filter Include="code\components\callback">
|
||||
<UniqueIdentifier>{0e801893-09df-4299-a572-6e63049d4f9f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="header\interface">
|
||||
<UniqueIdentifier>{7c6fe4d9-4baf-4fd2-93e0-ee395cbc2ee9}</UniqueIdentifier>
|
||||
<Filter Include="header\components">
|
||||
<UniqueIdentifier>{78b7809e-ea12-450d-af96-8e658087628d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="header\components\callback">
|
||||
<UniqueIdentifier>{28025c67-f68b-437b-bcda-d23c9a752d42}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -60,9 +63,6 @@
|
|||
<ClCompile Include="..\include\components\optimizations\code\OptimizationsExamples.c">
|
||||
<Filter>code\components\optimizations</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\components\interface\HyperLogCallback.c">
|
||||
<Filter>code\interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\SyscallFootprints.c">
|
||||
<Filter>code</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -72,6 +72,9 @@
|
|||
<ClCompile Include="..\include\platform\kernel\code\PlatformIntrinsics.c">
|
||||
<Filter>code\platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\components\callback\code\HyperLogCallback.c">
|
||||
<Filter>code\components\callback</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="header\Transparency.h">
|
||||
|
|
@ -83,9 +86,6 @@
|
|||
<ClInclude Include="..\include\platform\kernel\header\PlatformMem.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\components\interface\HyperLogCallback.h">
|
||||
<Filter>header\interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="header\SyscallFootprints.h">
|
||||
<Filter>header</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -95,5 +95,8 @@
|
|||
<ClInclude Include="..\include\platform\kernel\header\PlatformIntrinsics.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\components\callback\header\HyperLogCallback.h">
|
||||
<Filter>header\components\callback</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -15,35 +15,35 @@
|
|||
* @brief Check whether the bit is set or not
|
||||
*
|
||||
* @param BitNumber
|
||||
* @param addr
|
||||
* @return int
|
||||
* @param Addr
|
||||
* @return INT
|
||||
*/
|
||||
int
|
||||
TestBit(int BitNumber, unsigned long * addr)
|
||||
INT
|
||||
TestBit(INT BitNumber, ULONG * Addr)
|
||||
{
|
||||
return (BITMAP_ENTRY(BitNumber, addr) >> BITMAP_SHIFT(BitNumber)) & 1;
|
||||
return (BITMAP_ENTRY(BitNumber, Addr) >> BITMAP_SHIFT(BitNumber)) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unset the bit
|
||||
*
|
||||
* @param BitNumber
|
||||
* @param addr
|
||||
* @param Addr
|
||||
*/
|
||||
void
|
||||
ClearBit(int BitNumber, unsigned long * addr)
|
||||
VOID
|
||||
ClearBit(INT BitNumber, ULONG * Addr)
|
||||
{
|
||||
BITMAP_ENTRY(BitNumber, addr) &= ~(1UL << BITMAP_SHIFT(BitNumber));
|
||||
BITMAP_ENTRY(BitNumber, Addr) &= ~(1UL << BITMAP_SHIFT(BitNumber));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief set the bit
|
||||
*
|
||||
* @param BitNumber
|
||||
* @param addr
|
||||
* @param Addr
|
||||
*/
|
||||
void
|
||||
SetBit(int BitNumber, unsigned long * addr)
|
||||
VOID
|
||||
SetBit(INT BitNumber, ULONG * Addr)
|
||||
{
|
||||
BITMAP_ENTRY(BitNumber, addr) |= (1UL << BITMAP_SHIFT(BitNumber));
|
||||
BITMAP_ENTRY(BitNumber, Addr) |= (1UL << BITMAP_SHIFT(BitNumber));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Common.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Common functions that needs to be used in all source code files
|
||||
|
|
@ -61,28 +61,28 @@ CommonGetProcessNameFromProcessControlBlock(PEPROCESS Eprocess)
|
|||
/**
|
||||
* @brief Detects whether the string starts with another string
|
||||
*
|
||||
* @param const char * pre
|
||||
* @param const char * str
|
||||
* @param pre
|
||||
* @param str
|
||||
* @return BOOLEAN Returns true if it starts with and false if not strats with
|
||||
*/
|
||||
BOOLEAN
|
||||
CommonIsStringStartsWith(const char * pre, const char * str)
|
||||
CommonIsStringStartsWith(const CHAR * pre, const CHAR * str)
|
||||
{
|
||||
size_t lenpre = strlen(pre),
|
||||
lenstr = strlen(str);
|
||||
return lenstr < lenpre ? FALSE : memcmp(pre, str, lenpre) == 0;
|
||||
SIZE_T LenPre = strlen(pre),
|
||||
LenStr = strlen(str);
|
||||
return LenStr < LenPre ? FALSE : memcmp(pre, str, LenPre) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get cpuid results
|
||||
*
|
||||
* @param UINT32 Func
|
||||
* @param UINT32 SubFunc
|
||||
* @param int * CpuInfo
|
||||
* @param Func
|
||||
* @param SubFunc
|
||||
* @param CpuInfo
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, int * CpuInfo)
|
||||
CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, INT * CpuInfo)
|
||||
{
|
||||
CpuCpuIdEx(CpuInfo, Func, SubFunc);
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ CommonWriteDebugInformation(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
|
||||
MemoryMapperReadMemorySafeOnTargetProcess(VCpu->LastVmexitRip, Instruction, MAXIMUM_INSTR_SIZE);
|
||||
|
||||
for (size_t i = 0; i < MAXIMUM_INSTR_SIZE; i++)
|
||||
for (SIZE_T i = 0; i < MAXIMUM_INSTR_SIZE; i++)
|
||||
{
|
||||
Log("%02X ", Instruction[i] & 0xffU);
|
||||
}
|
||||
|
|
@ -249,4 +249,4 @@ CommonIsXCr0Valid(XCR0 XCr0)
|
|||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Apic.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Routines for Advanced Programmable Interrupt Controller (APIC)
|
||||
|
|
@ -79,18 +79,18 @@ ApicDumpIoApic(IO_APIC_ENTRY_PACKETS * IoApicPackets)
|
|||
{
|
||||
UINT32 Index = 0;
|
||||
UINT32 Max;
|
||||
UINT64 ll, lh;
|
||||
UINT64 Ll, Lh;
|
||||
|
||||
UINT64 ApicBasePa = IO_APIC_DEFAULT_BASE_ADDR;
|
||||
|
||||
ll = IoApicRead(g_IoApicBase, IO_VERS_REGISTER),
|
||||
Ll = IoApicRead(g_IoApicBase, IO_VERS_REGISTER),
|
||||
|
||||
Max = (ll >> 16) & 0xff;
|
||||
Max = (Ll >> 16) & 0xff;
|
||||
|
||||
// Log("IoApic @ %08x ID:%x (%x) Arb:%x\n",
|
||||
// ApicBasePa,
|
||||
// IoApicRead(g_IoApicBase, IO_ID_REGISTER) >> 24,
|
||||
// ll & 0xFF,
|
||||
// Ll & 0xFF,
|
||||
// IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER));
|
||||
|
||||
//
|
||||
|
|
@ -99,7 +99,7 @@ ApicDumpIoApic(IO_APIC_ENTRY_PACKETS * IoApicPackets)
|
|||
IoApicPackets->ApicBasePa = (UINT32)ApicBasePa;
|
||||
IoApicPackets->ApicBaseVa = (UINT64)g_IoApicBase;
|
||||
IoApicPackets->IoIdReg = (UINT32)IoApicRead(g_IoApicBase, IO_ID_REGISTER);
|
||||
IoApicPackets->IoLl = (UINT32)ll;
|
||||
IoApicPackets->IoLl = (UINT32)Ll;
|
||||
IoApicPackets->IoArbIdReg = (UINT32)IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER);
|
||||
|
||||
//
|
||||
|
|
@ -117,11 +117,11 @@ ApicDumpIoApic(IO_APIC_ENTRY_PACKETS * IoApicPackets)
|
|||
return;
|
||||
}
|
||||
|
||||
ll = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 0);
|
||||
lh = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 1);
|
||||
Ll = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 0);
|
||||
Lh = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 1);
|
||||
|
||||
IoApicPackets->LlLhData[Index] = ll;
|
||||
IoApicPackets->LlLhData[Index + 1] = lh;
|
||||
IoApicPackets->LlLhData[Index] = Ll;
|
||||
IoApicPackets->LlLhData[Index + 1] = Lh;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ DirtyLoggingInitialize()
|
|||
// the 4 - KByte aligned physical address of the page - modification log.The page modification
|
||||
// log comprises 512 64 - bit entries
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (g_GuestState[i].PmlBufferAddress == NULL)
|
||||
{
|
||||
|
|
@ -65,7 +65,7 @@ DirtyLoggingInitialize()
|
|||
//
|
||||
// Allocation failed
|
||||
//
|
||||
for (size_t j = 0; j < ProcessorsCount; j++)
|
||||
for (SIZE_T j = 0; j < ProcessorsCount; j++)
|
||||
{
|
||||
if (g_GuestState[j].PmlBufferAddress != NULL)
|
||||
{
|
||||
|
|
@ -196,7 +196,7 @@ DirtyLoggingUninitialize()
|
|||
//
|
||||
// Free the allocated pool buffers
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (g_GuestState[i].PmlBufferAddress != NULL)
|
||||
{
|
||||
|
|
@ -218,7 +218,7 @@ DirtyLoggingHandlePageModificationLog(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// The guest-physical address of the access is written to the page-modification log
|
||||
//
|
||||
for (size_t i = 0; i < PML_ENTITY_NUM; i++)
|
||||
for (SIZE_T i = 0; i < PML_ENTITY_NUM; i++)
|
||||
{
|
||||
LogInfo("Address : %llx", VCpu->PmlBufferAddress[i]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,22 +80,22 @@ EptHookReservePreallocatedPoolsForEptHooks(UINT32 Count)
|
|||
// Request pages to be allocated for converting 2MB to 4KB pages
|
||||
// Each core needs its own splitting page-tables
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(VMM_EPT_DYNAMIC_SPLIT), Count * ProcessorsCount, SPLIT_2MB_PAGING_TO_4KB_PAGE);
|
||||
PoolManagerCallbackRequestAllocation(sizeof(VMM_EPT_DYNAMIC_SPLIT), Count * ProcessorsCount, SPLIT_2MB_PAGING_TO_4KB_PAGE);
|
||||
|
||||
//
|
||||
// Request pages to be allocated for paged hook details
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(EPT_HOOKED_PAGE_DETAIL), Count, TRACKING_HOOKED_PAGES);
|
||||
PoolManagerCallbackRequestAllocation(sizeof(EPT_HOOKED_PAGE_DETAIL), Count, TRACKING_HOOKED_PAGES);
|
||||
|
||||
//
|
||||
// Request pages to be allocated for Trampoline of Executable hooked pages
|
||||
//
|
||||
PoolManagerRequestAllocation(MAX_EXEC_TRAMPOLINE_SIZE, Count, EXEC_TRAMPOLINE);
|
||||
PoolManagerCallbackRequestAllocation(MAX_EXEC_TRAMPOLINE_SIZE, Count, EXEC_TRAMPOLINE);
|
||||
|
||||
//
|
||||
// Request pages to be allocated for detour hooked pages details
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(HIDDEN_HOOKS_DETOUR_DETAILS), Count, DETOUR_HOOK_DETAILS);
|
||||
PoolManagerCallbackRequestAllocation(sizeof(HIDDEN_HOOKS_DETOUR_DETAILS), Count, DETOUR_HOOK_DETAILS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,16 +120,16 @@ EptHookAllocateExtraHookingPagesForMemoryMonitorsAndExecEptHooks(UINT32 Count)
|
|||
// Request pages to be allocated for converting 2MB to 4KB pages
|
||||
// Each core needs its own splitting page-tables
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(VMM_EPT_DYNAMIC_SPLIT),
|
||||
Count * ProcessorsCount,
|
||||
SPLIT_2MB_PAGING_TO_4KB_PAGE);
|
||||
PoolManagerCallbackRequestAllocation(sizeof(VMM_EPT_DYNAMIC_SPLIT),
|
||||
Count * ProcessorsCount,
|
||||
SPLIT_2MB_PAGING_TO_4KB_PAGE);
|
||||
|
||||
//
|
||||
// Request pages to be allocated for paged hook details
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(EPT_HOOKED_PAGE_DETAIL),
|
||||
Count,
|
||||
TRACKING_HOOKED_PAGES);
|
||||
PoolManagerCallbackRequestAllocation(sizeof(EPT_HOOKED_PAGE_DETAIL),
|
||||
Count,
|
||||
TRACKING_HOOKED_PAGES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -199,7 +199,7 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
// Save the detail of hooked page to keep track of it
|
||||
//
|
||||
HookedPage = (EPT_HOOKED_PAGE_DETAIL *)PoolManagerRequestPool(TRACKING_HOOKED_PAGES, TRUE, sizeof(EPT_HOOKED_PAGE_DETAIL));
|
||||
HookedPage = (EPT_HOOKED_PAGE_DETAIL *)PoolManagerCallbackRequestPool(TRACKING_HOOKED_PAGES, TRUE, sizeof(EPT_HOOKED_PAGE_DETAIL));
|
||||
|
||||
if (!HookedPage)
|
||||
{
|
||||
|
|
@ -274,14 +274,14 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
// Split the 2MB page-table of each core to 4KB page-table
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
//
|
||||
// We need to split the large page to 4KB page using pre-allocated pools
|
||||
//
|
||||
if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TRUE, PhysicalBaseAddress))
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
//
|
||||
// Here also other previous pools should be specified, but we forget it for now
|
||||
|
|
@ -302,7 +302,7 @@ EptHookCreateHookPage(_Inout_ VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
if (!TargetPage)
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
//
|
||||
// Here also other previous pools should be specified, but we forget it for now
|
||||
|
|
@ -907,7 +907,7 @@ EptHookInstructionMemory(PEPT_HOOKED_PAGE_DETAIL Hook,
|
|||
//
|
||||
// Allocate some executable memory for the trampoline
|
||||
//
|
||||
Hook->Trampoline = (CHAR *)PoolManagerRequestPool(EXEC_TRAMPOLINE, TRUE, MAX_EXEC_TRAMPOLINE_SIZE);
|
||||
Hook->Trampoline = (CHAR *)PoolManagerCallbackRequestPool(EXEC_TRAMPOLINE, TRUE, MAX_EXEC_TRAMPOLINE_SIZE);
|
||||
|
||||
if (!Hook->Trampoline)
|
||||
{
|
||||
|
|
@ -956,7 +956,7 @@ EptHookInstructionMemory(PEPT_HOOKED_PAGE_DETAIL Hook,
|
|||
// function that changes the original function and if our structure is no ready after this
|
||||
// function then we probably see BSOD on other cores
|
||||
//
|
||||
DetourHookDetails = (HIDDEN_HOOKS_DETOUR_DETAILS *)PoolManagerRequestPool(DETOUR_HOOK_DETAILS, TRUE, sizeof(HIDDEN_HOOKS_DETOUR_DETAILS));
|
||||
DetourHookDetails = (HIDDEN_HOOKS_DETOUR_DETAILS *)PoolManagerCallbackRequestPool(DETOUR_HOOK_DETAILS, TRUE, sizeof(HIDDEN_HOOKS_DETOUR_DETAILS));
|
||||
DetourHookDetails->HookedFunctionAddress = TargetFunction;
|
||||
DetourHookDetails->ReturnAddress = Hook->Trampoline;
|
||||
|
||||
|
|
@ -1104,7 +1104,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
// Save the detail of hooked page to keep track of it
|
||||
//
|
||||
HookedPage = (EPT_HOOKED_PAGE_DETAIL *)PoolManagerRequestPool(TRACKING_HOOKED_PAGES, TRUE, sizeof(EPT_HOOKED_PAGE_DETAIL));
|
||||
HookedPage = (EPT_HOOKED_PAGE_DETAIL *)PoolManagerCallbackRequestPool(TRACKING_HOOKED_PAGES, TRUE, sizeof(EPT_HOOKED_PAGE_DETAIL));
|
||||
|
||||
if (!HookedPage)
|
||||
{
|
||||
|
|
@ -1155,7 +1155,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu,
|
|||
|
||||
if (!HookedPage->StartOfTargetPhysicalAddress)
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS);
|
||||
return FALSE;
|
||||
|
|
@ -1183,7 +1183,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu,
|
|||
|
||||
if (!HookedPage->EndOfTargetPhysicalAddress)
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
VmmCallbackSetLastError(DEBUGGER_ERROR_INVALID_ADDRESS);
|
||||
return FALSE;
|
||||
|
|
@ -1244,21 +1244,21 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
if (!EptHookInstructionMemory(HookedPage, ProcessCr3, TargetAddress, (PVOID)TargetAddressInSafeMemory, HookFunction))
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
VmmCallbackSetLastError(DEBUGGER_ERROR_COULD_NOT_BUILD_THE_EPT_HOOK);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
//
|
||||
// We need to split the large page to 4KB page using pre-allocated pools
|
||||
//
|
||||
if (!EptSplitLargePage(g_GuestState[i].EptPageTable, TRUE, PhysicalBaseAddress))
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
//
|
||||
// Here also other previous pools should be specified, but we forget it for now
|
||||
|
|
@ -1278,7 +1278,7 @@ EptHookPerformPageHookMonitorAndInlineHook(VIRTUAL_MACHINE_STATE * VCpu,
|
|||
//
|
||||
if (!TargetPage)
|
||||
{
|
||||
PoolManagerFreePool((UINT64)HookedPage);
|
||||
PoolManagerCallbackFreePool((UINT64)HookedPage);
|
||||
|
||||
//
|
||||
// Here also other previous pools should be specified, but we forget it for now
|
||||
|
|
@ -1862,7 +1862,7 @@ EptHookRemoveEntryAndFreePoolFromEptHook2sDetourList(UINT64 Address)
|
|||
//
|
||||
// Free the pool in next ioctl
|
||||
//
|
||||
if (!PoolManagerFreePool((UINT64)CurrentHookedDetails))
|
||||
if (!PoolManagerCallbackFreePool((UINT64)CurrentHookedDetails))
|
||||
{
|
||||
LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
|
||||
}
|
||||
|
|
@ -1964,7 +1964,7 @@ EptHookUnHookSingleAddressDetoursAndMonitor(PEPT_HOOKED_PAGE_DETAIL
|
|||
// we add the hooked entry to the list
|
||||
// of pools that will be deallocated on next IOCTL
|
||||
//
|
||||
if (!PoolManagerFreePool((UINT64)HookedEntry))
|
||||
if (!PoolManagerCallbackFreePool((UINT64)HookedEntry))
|
||||
{
|
||||
LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
|
||||
return FALSE;
|
||||
|
|
@ -2069,7 +2069,7 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H
|
|||
// is the HookedEntry that should be remove (not the first one as it has the
|
||||
// correct PreviousByte)
|
||||
//
|
||||
for (size_t i = 0; i < HookedEntry->CountOfBreakpoints; i++)
|
||||
for (SIZE_T i = 0; i < HookedEntry->CountOfBreakpoints; i++)
|
||||
{
|
||||
if (HookedEntry->BreakpointAddresses[i] == VirtualAddress)
|
||||
{
|
||||
|
|
@ -2113,7 +2113,7 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H
|
|||
// we add the hooked entry to the list
|
||||
// of pools that will be deallocated on next IOCTL
|
||||
//
|
||||
if (!PoolManagerFreePool((UINT64)HookedEntry))
|
||||
if (!PoolManagerCallbackFreePool((UINT64)HookedEntry))
|
||||
{
|
||||
LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
|
||||
}
|
||||
|
|
@ -2162,7 +2162,7 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H
|
|||
// in the array, then we'll ignore setting the previous bit as previous bit might
|
||||
// be modified for the previous command
|
||||
//
|
||||
for (size_t j = 0; j < HookedEntry->CountOfBreakpoints; j++)
|
||||
for (SIZE_T j = 0; j < HookedEntry->CountOfBreakpoints; j++)
|
||||
{
|
||||
if (HookedEntry->BreakpointAddresses[j] == VirtualAddress)
|
||||
{
|
||||
|
|
@ -2189,7 +2189,7 @@ EptHookUnHookSingleAddressHiddenBreakpoint(PEPT_HOOKED_PAGE_DETAIL H
|
|||
// all addresses to a lower array index (because one entry is
|
||||
// missing and might) be in the middle of the array
|
||||
//
|
||||
for (size_t j = i /* IndexToRemove */; j < HookedEntry->CountOfBreakpoints - 1; j++)
|
||||
for (SIZE_T j = i /* IndexToRemove */; j < HookedEntry->CountOfBreakpoints - 1; j++)
|
||||
{
|
||||
HookedEntry->BreakpointAddresses[j] = HookedEntry->BreakpointAddresses[j + 1];
|
||||
HookedEntry->PreviousBytesOnBreakpointAddresses[j] = HookedEntry->PreviousBytesOnBreakpointAddresses[j + 1];
|
||||
|
|
@ -2274,7 +2274,7 @@ EptHookPerformUnHookSingleAddress(UINT64 VirtualAdd
|
|||
//
|
||||
// It's a hidden breakpoint
|
||||
//
|
||||
for (size_t i = 0; i < CurrEntity->CountOfBreakpoints; i++)
|
||||
for (SIZE_T i = 0; i < CurrEntity->CountOfBreakpoints; i++)
|
||||
{
|
||||
if (CurrEntity->BreakpointAddresses[i] == VirtualAddress)
|
||||
{
|
||||
|
|
@ -2485,7 +2485,7 @@ EptHookUnHookAll()
|
|||
// As we are in vmx-root here, we add the hooked entry to the list
|
||||
// of pools that will be deallocated on next IOCTL
|
||||
//
|
||||
if (!PoolManagerFreePool((UINT64)CurrEntity))
|
||||
if (!PoolManagerCallbackFreePool((UINT64)CurrEntity))
|
||||
{
|
||||
LogError("Err, something goes wrong, the pool not found in the list of previously allocated pools by pool manager");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ ExecTrapTraverseThroughOsPageTables(PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE Targe
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 512; i++)
|
||||
for (SIZE_T i = 0; i < 512; i++)
|
||||
{
|
||||
// LogInfo("Address of Cr3Va: %llx", Cr3Va);
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ ExecTrapTraverseThroughOsPageTables(PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE Targe
|
|||
//
|
||||
if (PdptVa != NULL)
|
||||
{
|
||||
for (size_t j = 0; j < 512; j++)
|
||||
for (SIZE_T j = 0; j < 512; j++)
|
||||
{
|
||||
// LogInfo("Address of PdptVa: %llx", PdptVa);
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ ExecTrapTraverseThroughOsPageTables(PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE Targe
|
|||
//
|
||||
if (PdVa != NULL)
|
||||
{
|
||||
for (size_t k = 0; k < 512; k++)
|
||||
for (SIZE_T k = 0; k < 512; k++)
|
||||
{
|
||||
// LogInfo("Address of PdVa: %llx", PdVa);
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ ExecTrapTraverseThroughOsPageTables(PVMM_EPT_PAGE_TABLE EptTable, CR3_TYPE Targe
|
|||
//
|
||||
if (PtVa != NULL)
|
||||
{
|
||||
for (size_t l = 0; l < 512; l++)
|
||||
for (SIZE_T l = 0; l < 512; l++)
|
||||
{
|
||||
// LogInfo("Address of PtVa: %llx", PtVa);
|
||||
|
||||
|
|
@ -265,7 +265,7 @@ ExecTrapEnableExecuteOnlyPages(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
{
|
||||
//
|
||||
// We only set the top-level PML4 for intercepting user-mode execution
|
||||
|
|
@ -276,7 +276,7 @@ ExecTrapEnableExecuteOnlyPages(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML3s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
EptTable->PML3[i].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -284,9 +284,9 @@ ExecTrapEnableExecuteOnlyPages(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML2s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
for (size_t j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
{
|
||||
EptTable->PML2[i][j].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ ExecTrapEnableExecuteOnlyPages(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// *** disallow read or write for certain memory only (not MMIO) EPTP pages ***
|
||||
//
|
||||
for (size_t i = 0; i < MAX_PHYSICAL_RAM_RANGE_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < MAX_PHYSICAL_RAM_RANGE_COUNT; i++)
|
||||
{
|
||||
if (PhysicalRamRegions[i].RamPhysicalAddress != NULL64_ZERO)
|
||||
{
|
||||
|
|
@ -510,7 +510,7 @@ ExecTrapChangeToUserDisabledMbecEptp(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
// for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// {
|
||||
VCpu->EptPageTable->PML4[0].UserModeExecute = FALSE;
|
||||
|
||||
|
|
@ -551,7 +551,7 @@ ExecTrapChangeToKernelDisabledMbecEptp(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
// for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// {
|
||||
VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE;
|
||||
|
||||
|
|
@ -592,7 +592,7 @@ ExecTrapChangeToNormalMbecEptp(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
// for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
// {
|
||||
VCpu->EptPageTable->PML4[0].UserModeExecute = TRUE;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ ModeBasedExecHookDisableUserModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
{
|
||||
//
|
||||
// We only set the top-level PML4 for intercepting user-mode execution
|
||||
|
|
@ -36,7 +36,7 @@ ModeBasedExecHookDisableUserModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML3s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
EptTable->PML3[i].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -44,9 +44,9 @@ ModeBasedExecHookDisableUserModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML2s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
for (size_t j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
{
|
||||
EptTable->PML2[i][j].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ ModeBasedExecHookDisableKernelModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
{
|
||||
EptTable->PML4[i].UserModeExecute = TRUE;
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ ModeBasedExecHookDisableKernelModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML3s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
EptTable->PML3[i].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -98,9 +98,9 @@ ModeBasedExecHookDisableKernelModeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML2s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
for (size_t j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
{
|
||||
EptTable->PML2[i][j].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML4s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT; i++)
|
||||
{
|
||||
//
|
||||
// We only set the top-level PML4 for intercepting user-mode execution
|
||||
|
|
@ -134,7 +134,7 @@ ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML3s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
EptTable->PML3[i].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -142,9 +142,9 @@ ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML2s
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML3E_COUNT; i++)
|
||||
{
|
||||
for (size_t j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
for (SIZE_T j = 0; j < VMM_EPT_PML2E_COUNT; j++)
|
||||
{
|
||||
EptTable->PML2[i][j].UserModeExecute = TRUE;
|
||||
|
||||
|
|
@ -163,7 +163,7 @@ ModeBasedExecHookEnableUsermodeExecution(PVMM_EPT_PAGE_TABLE EptTable)
|
|||
//
|
||||
// Set execute access for PML1s
|
||||
//
|
||||
for (size_t k = 0; k < VMM_EPT_PML1E_COUNT; k++)
|
||||
for (SIZE_T k = 0; k < VMM_EPT_PML1E_COUNT; k++)
|
||||
{
|
||||
Pml1Entries[k].UserModeExecute = TRUE;
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ ModeBasedExecHookInitialize()
|
|||
//
|
||||
// Enable EPT user-mode execution bit for the target EPTP
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
ModeBasedExecHookEnableUsermodeExecution(g_GuestState[i].EptPageTable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file SyscallCallback.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief Implementation of the functions related to the callback for Syscall
|
||||
* @details
|
||||
*
|
||||
|
|
@ -75,6 +76,17 @@ SyscallCallbackInitialize()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the syscall callback is initialized
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
SyscallCallbackIsInitialized()
|
||||
{
|
||||
return g_SyscallCallbackStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the syscall callback
|
||||
*
|
||||
|
|
@ -86,9 +98,14 @@ SyscallCallbackUninitialize()
|
|||
if (g_SyscallCallbackStatus)
|
||||
{
|
||||
//
|
||||
// Disable the syscall callback
|
||||
// Unset the EPT hook from the syscall entry before disabling state.
|
||||
//
|
||||
g_SyscallCallbackStatus = FALSE;
|
||||
if (!ConfigureEptHookUnHookSingleAddress((UINT64)g_SystemCallHookAddress, (UINT64)NULL, (UINT32)(ULONG_PTR)PsGetCurrentProcessId()))
|
||||
{
|
||||
LogInfo("Error while removing the EPT hook from windows syscall handler at address 0x%p", g_SystemCallHookAddress);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Unset the trap flags #DBs and #BPs for the syscall callback
|
||||
|
|
@ -100,15 +117,9 @@ SyscallCallbackUninitialize()
|
|||
//
|
||||
PlatformMemFreePool(g_SyscallCallbackTrapFlagState);
|
||||
|
||||
MSR Msr = {0};
|
||||
Msr.Flags = CpuReadMsr(IA32_LSTAR);
|
||||
|
||||
if (!ConfigureEptHookUnHookSingleAddress((UINT64)(Msr.Flags + 3), (UINT64)NULL, (UINT32)(ULONG_PTR)PsGetCurrentProcessId()))
|
||||
{
|
||||
LogInfo("Error while removing the EPT hook from windows syscall handler at address 0x%p+3", Msr.Flags);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
g_SyscallCallbackTrapFlagState = NULL;
|
||||
g_SystemCallHookAddress = NULL;
|
||||
g_SyscallCallbackStatus = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,27 +86,6 @@ VmmCallbackVmcallHandler(UINT32 CoreId,
|
|||
return g_Callbacks.VmmCallbackVmcallHandler(CoreId, VmcallNumber, OptionalParam1, OptionalParam2, OptionalParam3);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to handle registered MTF
|
||||
*
|
||||
* @param CoreId
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
VmmCallbackRegisteredMtfHandler(UINT32 CoreId)
|
||||
{
|
||||
if (g_Callbacks.VmmCallbackRegisteredMtfHandler == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
g_Callbacks.VmmCallbackRegisteredMtfHandler(CoreId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to handle NMI requests
|
||||
*
|
||||
|
|
@ -200,6 +179,26 @@ VmmCallbackUnhandledEptViolation(UINT32 CoreId,
|
|||
return g_Callbacks.VmmCallbackCheckUnhandledEptViolations(CoreId, ViolationQualification, GuestPhysicalAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to handle MTF callback
|
||||
* @param CoreId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
VmmCallbackHandleMtfCallback(UINT32 CoreId)
|
||||
{
|
||||
if (g_Callbacks.VmmCallbackHandleMtfCallback == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it as it's not handled
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return g_Callbacks.VmmCallbackHandleMtfCallback(CoreId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to check if LBR is supported and get the LBR capacity if supported
|
||||
*
|
||||
|
|
@ -211,14 +210,14 @@ VmmCallbackUnhandledEptViolation(UINT32 CoreId,
|
|||
BOOLEAN
|
||||
HyperTraceCallbackLbrIsSupported(UINT32 * Capacity, BOOLEAN * IsArchLbr)
|
||||
{
|
||||
if (g_Callbacks.HyperTraceLbrIsSupported == NULL)
|
||||
if (g_Callbacks.HyperTraceCallbackLbrIsSupported == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it as it's not handled
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return g_Callbacks.HyperTraceLbrIsSupported(Capacity, IsArchLbr);
|
||||
return g_Callbacks.HyperTraceCallbackLbrIsSupported(Capacity, IsArchLbr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -284,6 +283,110 @@ DebuggingCallbackCheckThreadInterception(UINT32 CoreId)
|
|||
return g_Callbacks.DebuggingCallbackCheckThreadInterception(CoreId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to trigger on clock and IPI events for checking process or thread change
|
||||
*
|
||||
* @param CoreId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggingCallbackTriggerOnClockAndIpiEvents(UINT32 CoreId)
|
||||
{
|
||||
if (g_Callbacks.DebuggingCallbackTriggerOnClockAndIpiEvents == NULL)
|
||||
{
|
||||
//
|
||||
// not handled by user debugger
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return g_Callbacks.DebuggingCallbackTriggerOnClockAndIpiEvents(CoreId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to ignore handling mov 2 debug registers
|
||||
* @param CoreId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggingCallbackIgnoreHandlingMov2DebugRegs(UINT32 CoreId)
|
||||
{
|
||||
if (g_Callbacks.DebuggingCallbackIgnoreHandlingMov2DebugRegs == NULL)
|
||||
{
|
||||
//
|
||||
// not handled by user debugger
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return g_Callbacks.DebuggingCallbackIgnoreHandlingMov2DebugRegs(CoreId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to request pool allocation
|
||||
*
|
||||
* @param Size
|
||||
* @param Count
|
||||
* @param Intention The intention of the buffer (buffer tag)
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
PoolManagerCallbackRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
|
||||
{
|
||||
if (g_Callbacks.PoolManagerCallbackRequestAllocation == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it as it's not handled
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return g_Callbacks.PoolManagerCallbackRequestAllocation(Size, Count, Intention);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to request pool
|
||||
*
|
||||
* @param Intention The intention why we need this pool for (buffer tag)
|
||||
* @param RequestNewPool Create a request to allocate a new pool with the same size, next time
|
||||
* that it's safe to allocate (this way we never ran out of pools for this "Intention")
|
||||
* @param Size If the RequestNewPool is true the we should specify a size for the new pool
|
||||
*
|
||||
* @return UINT64 Returns a pool address or returns null if there was an error
|
||||
*/
|
||||
UINT64
|
||||
PoolManagerCallbackRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size)
|
||||
{
|
||||
if (g_Callbacks.PoolManagerCallbackRequestPool == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it as it's not handled
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
return g_Callbacks.PoolManagerCallbackRequestPool(Intention, RequestNewPool, Size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to free pool
|
||||
*
|
||||
* @param AddressToFree
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
PoolManagerCallbackFreePool(UINT64 AddressToFree)
|
||||
{
|
||||
if (g_Callbacks.PoolManagerCallbackFreePool == NULL)
|
||||
{
|
||||
//
|
||||
// ignore it as it's not handled
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
return g_Callbacks.PoolManagerCallbackFreePool(AddressToFree);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief routine callback to handle cr3 process change
|
||||
*
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ DispatchEventMode(VIRTUAL_MACHINE_STATE * VCpu, DEBUGGER_EVENT_MODE_TYPE TargetM
|
|||
//
|
||||
// If the thread is intercepted, we should not trigger the event
|
||||
// Being here means that the thread should be handled by the user-mode debugger
|
||||
//
|
||||
// ou
|
||||
|
||||
// LogInfo("Thread Id: %x, process Id: %x is intercepted by user-mode debugger - RIP: %llx",
|
||||
// PsGetCurrentThreadId(),
|
||||
|
|
@ -711,13 +711,9 @@ DispatchEventMov2DebugRegs(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
BOOLEAN PostEventTriggerReq = FALSE;
|
||||
|
||||
//
|
||||
// Handle access to debug registers, if we should not ignore it, it is
|
||||
// because on detecting thread scheduling we ignore the hardware debug
|
||||
// registers modifications
|
||||
// Check to see if we should ignore handling the mov 2 debug registers or not
|
||||
//
|
||||
if (g_Callbacks.KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId != NULL &&
|
||||
g_Callbacks.KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(VCpu->CoreId,
|
||||
DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_DEBUG_REGISTER_INTERCEPTION))
|
||||
if (DebuggingCallbackIgnoreHandlingMov2DebugRegs(VCpu->CoreId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -850,7 +846,7 @@ DispatchEventException(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
// Check if we're waiting for an NMI on this core and if the guest is NOT in
|
||||
// a instrument step-in ('i' command) routine
|
||||
//
|
||||
if (!VCpu->RegisterBreakOnMtf &&
|
||||
if (!VCpu->InstrumentationStepInMtf &&
|
||||
VmxBroadcastNmiHandler(VCpu, FALSE))
|
||||
{
|
||||
return;
|
||||
|
|
@ -885,7 +881,7 @@ DispatchEventException(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// So, we'll ignore the injection of Exception in this case
|
||||
//
|
||||
if (VCpu->RegisterBreakOnMtf)
|
||||
if (VCpu->InstrumentationStepInMtf)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -974,10 +970,11 @@ DispatchEventExternalInterrupts(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
if ((/* VCpu->CoreId == 0 && */ InterruptExit.Vector == CLOCK_INTERRUPT) ||
|
||||
(VCpu->CoreId != 0 && InterruptExit.Vector == IPI_INTERRUPT))
|
||||
{
|
||||
if (g_Callbacks.DebuggerCheckProcessOrThreadChange != NULL)
|
||||
{
|
||||
g_Callbacks.DebuggerCheckProcessOrThreadChange(VCpu->CoreId);
|
||||
}
|
||||
//
|
||||
// Calling the callback to trigger on clock and IPI events
|
||||
// This is usually used for detecting changes to processes and threads
|
||||
//
|
||||
DebuggingCallbackTriggerOnClockAndIpiEvents(VCpu->CoreId);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -63,29 +63,42 @@ VmFuncChangeIgnoreOneMtfState(UINT32 CoreId, BOOLEAN Set)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Register for break in the case of an MTF
|
||||
* @brief Set instrumentation step in MTF (used for single stepping with MTF)
|
||||
*
|
||||
* @param CoreId Target core's ID
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
VmFuncRegisterMtfBreak(UINT32 CoreId)
|
||||
VmFuncSetInstrumentationStepInState(UINT32 CoreId)
|
||||
{
|
||||
g_GuestState[CoreId].RegisterBreakOnMtf = TRUE;
|
||||
g_GuestState[CoreId].InstrumentationStepInMtf = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister for break in the case of an MTF
|
||||
* @brief Unset instrumentation step in MTF (used for single stepping with MTF)
|
||||
*
|
||||
* @param CoreId Target core's ID
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
VmFuncUnRegisterMtfBreak(UINT32 CoreId)
|
||||
VmFuncUnsetInstrumentationStepInState(UINT32 CoreId)
|
||||
{
|
||||
g_GuestState[CoreId].RegisterBreakOnMtf = FALSE;
|
||||
g_GuestState[CoreId].InstrumentationStepInMtf = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query instrumentation step in MTF state
|
||||
*
|
||||
* @param CoreId Target core's ID
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
VmFuncQueryInstrumentationStepInState(UINT32 CoreId)
|
||||
{
|
||||
return g_GuestState[CoreId].InstrumentationStepInMtf;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -941,10 +954,10 @@ VmFuncEventInjectInterruption(UINT32 InterruptionType,
|
|||
* @return NTSTATUS
|
||||
*/
|
||||
NTSTATUS
|
||||
VmFuncVmxVmcall(unsigned long long VmcallNumber,
|
||||
unsigned long long OptionalParam1,
|
||||
unsigned long long OptionalParam2,
|
||||
unsigned long long OptionalParam3)
|
||||
VmFuncVmxVmcall(UINT64 VmcallNumber,
|
||||
UINT64 OptionalParam1,
|
||||
UINT64 OptionalParam2,
|
||||
UINT64 OptionalParam3)
|
||||
{
|
||||
return AsmVmxVmcall(VmcallNumber, OptionalParam1, OptionalParam2, OptionalParam3);
|
||||
}
|
||||
|
|
@ -1045,14 +1058,14 @@ VmFuncVmxCompatibleWcsncmp(const WCHAR * Address1, const WCHAR * Address2, SIZE_
|
|||
* @return INT32
|
||||
*/
|
||||
INT32
|
||||
VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count)
|
||||
VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, SIZE_T Count)
|
||||
{
|
||||
return VmxCompatibleMemcmp(Address1, Address2, Count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables MTF and adjust external interrupt state
|
||||
* @param UINT32 CoreId
|
||||
* @param CoreId
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
|
|
@ -1065,7 +1078,7 @@ VmFuncEnableMtfAndChangeExternalInterruptState(UINT32 CoreId)
|
|||
/**
|
||||
* @brief Checks to enable and reinject previous interrupts
|
||||
*
|
||||
* @param UINT32 CoreId
|
||||
* @param CoreId
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file HyperEvade.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief Hyperevade function wrappers
|
||||
* @details
|
||||
*
|
||||
|
|
@ -24,6 +25,20 @@ BOOLEAN
|
|||
TransparentHideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest)
|
||||
{
|
||||
HYPEREVADE_CALLBACKS HyperevadeCallbacks = {0};
|
||||
UINT32 EvadeMask = TransparentModeRequest->EvadeMask;
|
||||
|
||||
if (EvadeMask == 0)
|
||||
{
|
||||
EvadeMask = TRANSPARENT_EVADE_MASK_DEFAULT;
|
||||
}
|
||||
|
||||
if ((EvadeMask & ~TRANSPARENT_EVADE_MASK_ALL) != 0)
|
||||
{
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TransparentModeRequest->EvadeMask = EvadeMask;
|
||||
|
||||
//
|
||||
// *** Fill the callbacks ***
|
||||
|
|
@ -66,20 +81,24 @@ TransparentHideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * Tra
|
|||
HyperevadeCallbacks.HvHandleTrapFlag = HvHandleTrapFlag;
|
||||
HyperevadeCallbacks.EventInjectGeneralProtection = EventInjectGeneralProtection;
|
||||
|
||||
//
|
||||
// Initialize the syscall callback mechanism from hypervisor
|
||||
//
|
||||
if (!SyscallCallbackInitialize())
|
||||
{
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Call the hyperevade hide debugger function
|
||||
//
|
||||
if (TransparentHideDebugger(&HyperevadeCallbacks, TransparentModeRequest))
|
||||
{
|
||||
//
|
||||
// Initialize the syscall callback mechanism from hypervisor after
|
||||
// transparent-mode accepts the request as the active state.
|
||||
//
|
||||
if ((EvadeMask & TRANSPARENT_EVADE_MASK_SYSCALL_HOOK) != 0 && !SyscallCallbackInitialize())
|
||||
{
|
||||
TransparentUnhideDebugger();
|
||||
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER;
|
||||
g_CheckForFootprints = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Status is set within the transparent mode (hyperevade) module
|
||||
//
|
||||
|
|
@ -105,10 +124,15 @@ TransparentHideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * Tra
|
|||
BOOLEAN
|
||||
TransparentUnhideDebuggerWrapper(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE * TransparentModeRequest)
|
||||
{
|
||||
//
|
||||
// Uninitialize the syscall callback mechanism from hypervisor
|
||||
//
|
||||
SyscallCallbackUninitialize();
|
||||
if (SyscallCallbackIsInitialized() && !SyscallCallbackUninitialize())
|
||||
{
|
||||
if (TransparentModeRequest != NULL)
|
||||
{
|
||||
TransparentModeRequest->KernelStatus = DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (TransparentUnhideDebugger())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Conversion.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Functions for address checks
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
*
|
||||
* @param Address Address to check
|
||||
*
|
||||
* @param UINT32 ProcId
|
||||
* @param ProcId
|
||||
* @return BOOLEAN Returns true if the address is valid; otherwise, false
|
||||
*/
|
||||
BOOLEAN
|
||||
|
|
@ -210,7 +210,7 @@ CheckAccessValidityAndSafetyWrapper(UINT64 TargetAddress, UINT32 Size, UINT32 Pr
|
|||
// UINT64 AlignedPage = (UINT64)PAGE_ALIGN(TargetAddress);
|
||||
// UINT64 PageCount = ((TargetAddress - AlignedPage) + Size) / PAGE_SIZE;
|
||||
//
|
||||
// for (size_t i = 0; i <= PageCount; i++)
|
||||
// for (SIZE_T i = 0; i <= PageCount; i++)
|
||||
// {
|
||||
// UINT64 CheckAddr = AlignedPage + (PAGE_SIZE * i);
|
||||
// if (!CheckAddressValidityUsingTsx(CheckAddr))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file MemoryMapper.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief This file shows the functions to map memory to reserved system ranges
|
||||
|
|
@ -685,7 +685,7 @@ MemoryMapperInitialize()
|
|||
//
|
||||
// Set the core's id and initialize memory mapper
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
//
|
||||
// *** Initialize memory mapper for each core ***
|
||||
|
|
@ -717,7 +717,7 @@ MemoryMapperUninitialize()
|
|||
{
|
||||
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
//
|
||||
// Unmap and free the reserved buffer
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Ept.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author Gbps
|
||||
|
|
@ -201,7 +201,7 @@ EptBuildMtrrMap(VOID)
|
|||
const UINT32 K64Base = 0x0;
|
||||
const UINT32 K64Size = 0x10000;
|
||||
IA32_MTRR_FIXED_RANGE_TYPE K64Types = {CpuReadMsr(IA32_MTRR_FIX64K_00000)};
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
Descriptor = &g_EptState->MemoryRanges[g_EptState->NumberOfEnabledMemoryRanges++];
|
||||
Descriptor->MemoryType = K64Types.s.Types[i];
|
||||
|
|
@ -212,10 +212,10 @@ EptBuildMtrrMap(VOID)
|
|||
|
||||
const UINT32 K16Base = 0x80000;
|
||||
const UINT32 K16Size = 0x4000;
|
||||
for (unsigned int i = 0; i < 2; i++)
|
||||
for (UINT32 i = 0; i < 2; i++)
|
||||
{
|
||||
IA32_MTRR_FIXED_RANGE_TYPE K16Types = {CpuReadMsr(IA32_MTRR_FIX16K_80000 + i)};
|
||||
for (unsigned int j = 0; j < 8; j++)
|
||||
for (UINT32 j = 0; j < 8; j++)
|
||||
{
|
||||
Descriptor = &g_EptState->MemoryRanges[g_EptState->NumberOfEnabledMemoryRanges++];
|
||||
Descriptor->MemoryType = K16Types.s.Types[j];
|
||||
|
|
@ -227,11 +227,11 @@ EptBuildMtrrMap(VOID)
|
|||
|
||||
const UINT32 K4Base = 0xC0000;
|
||||
const UINT32 K4Size = 0x1000;
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
IA32_MTRR_FIXED_RANGE_TYPE K4Types = {CpuReadMsr(IA32_MTRR_FIX4K_C0000 + i)};
|
||||
|
||||
for (unsigned int j = 0; j < 8; j++)
|
||||
for (UINT32 j = 0; j < 8; j++)
|
||||
{
|
||||
Descriptor = &g_EptState->MemoryRanges[g_EptState->NumberOfEnabledMemoryRanges++];
|
||||
Descriptor->MemoryType = K4Types.s.Types[j];
|
||||
|
|
@ -502,7 +502,7 @@ EptSplitLargePage(PVMM_EPT_PAGE_TABLE EptPageTable,
|
|||
//
|
||||
if (UsePreAllocatedBuffer)
|
||||
{
|
||||
NewSplit = (PVMM_EPT_DYNAMIC_SPLIT)PoolManagerRequestPool(SPLIT_2MB_PAGING_TO_4KB_PAGE, TRUE, sizeof(VMM_EPT_DYNAMIC_SPLIT));
|
||||
NewSplit = (PVMM_EPT_DYNAMIC_SPLIT)PoolManagerCallbackRequestPool(SPLIT_2MB_PAGING_TO_4KB_PAGE, TRUE, sizeof(VMM_EPT_DYNAMIC_SPLIT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -763,7 +763,7 @@ EptAllocateAndCreateIdentityPageTable(VOID)
|
|||
//
|
||||
// Copt the template into each of the 512 PML3 entry slots for the reserved entries
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT - 1; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT - 1; i++)
|
||||
{
|
||||
CpuStosQ((SIZE_T *)&PageTable->PML3_RSVD[i][0], PML3TemplateLarge.AsUInt, VMM_EPT_PML3E_COUNT);
|
||||
}
|
||||
|
|
@ -783,9 +783,9 @@ EptAllocateAndCreateIdentityPageTable(VOID)
|
|||
//
|
||||
// For each of the 512 PML3 reserved entries for reserved PML3 entries
|
||||
//
|
||||
for (size_t i = 0; i < VMM_EPT_PML4E_COUNT - 1; i++)
|
||||
for (SIZE_T i = 0; i < VMM_EPT_PML4E_COUNT - 1; i++)
|
||||
{
|
||||
for (size_t j = 0; j < VMM_EPT_PML3E_COUNT; j++)
|
||||
for (SIZE_T j = 0; j < VMM_EPT_PML3E_COUNT; j++)
|
||||
{
|
||||
//
|
||||
// Map the 1GB PML3 reserved entry to 512 PML3 (1GB) entries to describe each large page
|
||||
|
|
@ -862,7 +862,7 @@ EptLogicalProcessorInitialize(VOID)
|
|||
//
|
||||
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
//
|
||||
// Allocate the identity mapped page table
|
||||
|
|
@ -874,7 +874,7 @@ EptLogicalProcessorInitialize(VOID)
|
|||
//
|
||||
// Try to deallocate previous pools (if any)
|
||||
//
|
||||
for (size_t j = 0; j < ProcessorsCount; j++)
|
||||
for (SIZE_T j = 0; j < ProcessorsCount; j++)
|
||||
{
|
||||
if (g_GuestState[j].EptPageTable != NULL)
|
||||
{
|
||||
|
|
@ -1225,7 +1225,7 @@ EptCheckAndHandleEptHookBreakpoints(VIRTUAL_MACHINE_STATE * VCpu, UINT64 GuestRi
|
|||
|
||||
if (HookedEntry->IsExecutionHook)
|
||||
{
|
||||
for (size_t i = 0; i < HookedEntry->CountOfBreakpoints; i++)
|
||||
for (SIZE_T i = 0; i < HookedEntry->CountOfBreakpoints; i++)
|
||||
{
|
||||
if (HookedEntry->BreakpointAddresses[i] == GuestRip)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Hv.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief This file describes the routines in Hypervisor
|
||||
|
|
@ -299,7 +299,7 @@ HvResumeToNextInstruction()
|
|||
{
|
||||
UINT64 ResumeRIP = NULL64_ZERO;
|
||||
UINT64 CurrentRIP = NULL64_ZERO;
|
||||
size_t ExitInstructionLength = 0;
|
||||
SIZE_T ExitInstructionLength = 0;
|
||||
|
||||
VmxVmread64P(VMCS_GUEST_RIP, &CurrentRIP);
|
||||
VmxVmread64P(VMCS_VMEXIT_INSTRUCTION_LENGTH, &ExitInstructionLength);
|
||||
|
|
@ -519,7 +519,7 @@ HvRestoreRegisters()
|
|||
VmxVmread64P(VMCS_GUEST_GDTR_BASE, &GdtrBase);
|
||||
VmxVmread64P(VMCS_GUEST_GDTR_LIMIT, &GdtrLimit);
|
||||
|
||||
AsmReloadGdtr((void *)GdtrBase, (unsigned long)GdtrLimit);
|
||||
AsmReloadGdtr((PVOID)GdtrBase, (ULONG)GdtrLimit);
|
||||
|
||||
//
|
||||
// Restore Segment Selector
|
||||
|
|
@ -539,7 +539,7 @@ HvRestoreRegisters()
|
|||
VmxVmread64P(VMCS_GUEST_IDTR_BASE, &IdtrBase);
|
||||
VmxVmread64P(VMCS_GUEST_IDTR_LIMIT, &IdtrLimit);
|
||||
|
||||
AsmReloadIdtr((void *)IdtrBase, (unsigned long)IdtrLimit);
|
||||
AsmReloadIdtr((PVOID)IdtrBase, (ULONG)IdtrLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1111,7 +1111,6 @@ HvSetExternalInterruptExiting(VIRTUAL_MACHINE_STATE * VCpu, BOOLEAN Set)
|
|||
* @brief Checks to enable and reinject previous interrupts
|
||||
*
|
||||
* @param VCpu The virtual processor's state
|
||||
* @param Set Set or unset the External Interrupt Exiting
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file IdtEmulation.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Handlers of Guest's IDT Emulator
|
||||
|
|
@ -55,9 +55,9 @@ IdtEmulationQueryIdtEntriesRequest(PINTERRUPT_DESCRIPTOR_TABLE_ENTRIES_PACKETS I
|
|||
//
|
||||
for (UINT32 i = 0; i < MAX_NUMBER_OF_IDT_ENTRIES; i++)
|
||||
{
|
||||
IdtQueryRequest->IdtEntry[i] = (UINT64)((unsigned long long)IdtEntries[i].HighestPart << 32) |
|
||||
((unsigned long long)IdtEntries[i].HighPart << 16) |
|
||||
(unsigned long long)IdtEntries[i].LowPart;
|
||||
IdtQueryRequest->IdtEntry[i] = (UINT64)((UINT64)IdtEntries[i].HighestPart << 32) |
|
||||
((UINT64)IdtEntries[i].HighPart << 16) |
|
||||
(UINT64)IdtEntries[i].LowPart;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ IdtEmulationPrepareHostIdt(_Inout_ VIRTUAL_MACHINE_STATE * VCpu)
|
|||
HOST_IDT_DESCRIPTOR_COUNT * sizeof(SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64));
|
||||
|
||||
/*
|
||||
for (size_t i = 0; i < HOST_IDT_DESCRIPTOR_COUNT; i++)
|
||||
for (SIZE_T i = 0; i < HOST_IDT_DESCRIPTOR_COUNT; i++)
|
||||
{
|
||||
SEGMENT_DESCRIPTOR_INTERRUPT_GATE_64 CurrentEntry = WindowsIdt[i];
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ IdtEmulationHandleExceptionAndNmi(_Inout_ VIRTUAL_MACHINE_STATE * VCpu,
|
|||
|
||||
if (VCpu->EnableExternalInterruptsOnContinue ||
|
||||
VCpu->EnableExternalInterruptsOnContinueMtf ||
|
||||
VCpu->RegisterBreakOnMtf)
|
||||
VCpu->InstrumentationStepInMtf)
|
||||
{
|
||||
//
|
||||
// Ignore the nmi
|
||||
|
|
@ -481,7 +481,7 @@ IdtEmulationInjectInterruptWhenInterruptWindowIsOpen(_Inout_ VIRTUAL_MACHINE_STA
|
|||
// We can't inject interrupt because the guest's state is not interruptible
|
||||
// we have to queue it an re-inject it when the interrupt window is opened !
|
||||
//
|
||||
for (size_t i = 0; i < PENDING_INTERRUPTS_BUFFER_CAPACITY; i++)
|
||||
for (SIZE_T i = 0; i < PENDING_INTERRUPTS_BUFFER_CAPACITY; i++)
|
||||
{
|
||||
//
|
||||
// Find an empty space
|
||||
|
|
@ -677,7 +677,7 @@ IdtEmulationHandleInterruptWindowExiting(_Inout_ VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
if (!InjectPageFault)
|
||||
{
|
||||
for (size_t i = 0; i < PENDING_INTERRUPTS_BUFFER_CAPACITY; i++)
|
||||
for (SIZE_T i = 0; i < PENDING_INTERRUPTS_BUFFER_CAPACITY; i++)
|
||||
{
|
||||
//
|
||||
// Find an empty space
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ IoHandleIoVmExits(VIRTUAL_MACHINE_STATE * VCpu, VMX_EXIT_QUALIFICATION_IO_INSTRU
|
|||
|
||||
union
|
||||
{
|
||||
unsigned char * AsBytePtr;
|
||||
unsigned short * AsWordPtr;
|
||||
unsigned long * AsDwordPtr;
|
||||
UCHAR * AsBytePtr;
|
||||
USHORT * AsWordPtr;
|
||||
ULONG * AsDwordPtr;
|
||||
|
||||
void * AsPtr;
|
||||
UINT64 AsUint64;
|
||||
PVOID AsPtr;
|
||||
UINT64 AsUInt64;
|
||||
|
||||
} PortValue;
|
||||
|
||||
|
|
@ -215,11 +215,11 @@ IoHandleSetIoBitmap(VIRTUAL_MACHINE_STATE * VCpu, UINT32 Port)
|
|||
{
|
||||
if (Port <= 0x7FFF)
|
||||
{
|
||||
SetBit(Port, (unsigned long *)VCpu->IoBitmapVirtualAddressA);
|
||||
SetBit(Port, (ULONG *)VCpu->IoBitmapVirtualAddressA);
|
||||
}
|
||||
else if ((0x8000 <= Port) && (Port <= 0xFFFF))
|
||||
{
|
||||
SetBit(Port - 0x8000, (unsigned long *)VCpu->IoBitmapVirtualAddressB);
|
||||
SetBit(Port - 0x8000, (ULONG *)VCpu->IoBitmapVirtualAddressB);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -245,8 +245,8 @@ IoHandlePerformIoBitmapChange(VIRTUAL_MACHINE_STATE * VCpu, UINT32 Port)
|
|||
//
|
||||
// Means all the bitmaps should be put to 1
|
||||
//
|
||||
memset((void *)VCpu->IoBitmapVirtualAddressA, 0xFF, PAGE_SIZE);
|
||||
memset((void *)VCpu->IoBitmapVirtualAddressB, 0xFF, PAGE_SIZE);
|
||||
memset((PVOID)VCpu->IoBitmapVirtualAddressA, 0xFF, PAGE_SIZE);
|
||||
memset((PVOID)VCpu->IoBitmapVirtualAddressB, 0xFF, PAGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -270,6 +270,6 @@ IoHandlePerformIoBitmapReset(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Means all the bitmaps should be put to 0
|
||||
//
|
||||
memset((void *)VCpu->IoBitmapVirtualAddressA, 0x0, PAGE_SIZE);
|
||||
memset((void *)VCpu->IoBitmapVirtualAddressB, 0x0, PAGE_SIZE);
|
||||
memset((PVOID)VCpu->IoBitmapVirtualAddressA, 0x0, PAGE_SIZE);
|
||||
memset((PVOID)VCpu->IoBitmapVirtualAddressB, 0x0, PAGE_SIZE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file MsrHandlers.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Handle for MSR-related tasks in VMX-root
|
||||
|
|
@ -11,6 +11,49 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
/**
|
||||
* @brief Checks whether an MSR belongs to the Hyper-V synthetic MSR set
|
||||
* @details The ranges and individual registers are defined by Hyper-V TLFS
|
||||
* synthetic MSRs and mirrored in HypervTlfs.h.
|
||||
*
|
||||
* @param TargetMsr The target MSR
|
||||
* @return BOOLEAN Returns TRUE if the MSR should be forwarded to the
|
||||
* top-level Hyper-V compatible hypervisor
|
||||
*/
|
||||
BOOLEAN
|
||||
MsrHandleIsHypervSyntheticMsr(_In_ UINT32 TargetMsr)
|
||||
{
|
||||
switch (TargetMsr)
|
||||
{
|
||||
case HV_X64_MSR_GUEST_OS_ID:
|
||||
case HV_X64_MSR_HYPERCALL:
|
||||
case HV_X64_MSR_VP_INDEX:
|
||||
case HV_X64_MSR_RESET:
|
||||
case HV_X64_MSR_VP_RUNTIME:
|
||||
case HV_X64_MSR_TIME_REF_COUNT:
|
||||
case HV_X64_MSR_REFERENCE_TSC:
|
||||
case HV_X64_MSR_TSC_FREQUENCY:
|
||||
case HV_X64_MSR_APIC_FREQUENCY:
|
||||
case HV_X64_MSR_NPIEP_CONFIG:
|
||||
case HV_X64_MSR_GUEST_IDLE:
|
||||
case HV_X64_MSR_REENLIGHTENMENT_CONTROL:
|
||||
case HV_X64_MSR_TSC_EMULATION_CONTROL:
|
||||
case HV_X64_MSR_TSC_EMULATION_STATUS:
|
||||
case HV_X64_MSR_STIME_UNHALTED_TIMER_CONFIG:
|
||||
case HV_X64_MSR_STIME_UNHALTED_TIMER_COUNT:
|
||||
case HV_X64_MSR_NESTED_VP_INDEX:
|
||||
return TRUE;
|
||||
default:
|
||||
return (TargetMsr >= HV_X64_MSR_EOI && TargetMsr <= HV_X64_MSR_TPR) ||
|
||||
(TargetMsr >= HV_X64_MSR_SCONTROL && TargetMsr <= HV_X64_MSR_EOM) ||
|
||||
(TargetMsr >= HV_X64_MSR_SINT0 && TargetMsr <= HV_X64_MSR_SINT15) ||
|
||||
(TargetMsr >= HV_X64_MSR_STIMER0_CONFIG && TargetMsr <= HV_X64_MSR_STIMER3_COUNT) ||
|
||||
(TargetMsr >= HV_X64_MSR_CRASH_P0 && TargetMsr <= HV_X64_MSR_CRASH_CTL) ||
|
||||
(TargetMsr >= HV_X64_MSR_NESTED_SCONTROL && TargetMsr <= HV_X64_MSR_NESTED_EOM) ||
|
||||
(TargetMsr >= HV_X64_MSR_NESTED_SINT0 && TargetMsr <= HV_X64_MSR_NESTED_SINT15);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles in the cases when RDMSR causes a vm-exit
|
||||
*
|
||||
|
|
@ -53,6 +96,17 @@ MsrHandleRdmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
// LogInfo("MSR read (RDMSR) VM-exit, MSR: %x, from: %llx",
|
||||
// TargetMsr,
|
||||
// VCpu->LastVmexitRip);
|
||||
//
|
||||
// Checking whether it is a synthetic MSR for Hyper-V.
|
||||
if (MsrHandleIsHypervSyntheticMsr(TargetMsr))
|
||||
{
|
||||
Msr.Flags = CpuReadMsr(TargetMsr);
|
||||
|
||||
GuestRegs->rax = Msr.Fields.Low;
|
||||
GuestRegs->rdx = Msr.Fields.High;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for sanity of MSR if they're valid or they're for reserved range for WRMSR and RDMSR
|
||||
|
|
@ -114,7 +168,7 @@ MsrHandleRdmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Check whether the MSR should cause #GP or not
|
||||
//
|
||||
if (TargetMsr <= 0xfff && TestBit(TargetMsr, (unsigned long *)g_MsrBitmapInvalidMsrs) != NULL64_ZERO)
|
||||
if (TargetMsr <= 0xfff && TestBit(TargetMsr, (ULONG *)g_MsrBitmapInvalidMsrs) != NULL64_ZERO)
|
||||
{
|
||||
//
|
||||
// Invalid MSR between 0x0 to 0xfff
|
||||
|
|
@ -203,6 +257,13 @@ MsrHandleWrmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
// GuestRegs->rax,
|
||||
// GuestRegs->rdx,
|
||||
// VCpu->LastVmexitRip);
|
||||
//
|
||||
// Checking whether it is a synthetic MSR for Hyper-V.
|
||||
if (MsrHandleIsHypervSyntheticMsr(TargetMsr))
|
||||
{
|
||||
CpuWriteMsr(TargetMsr, Msr.Flags);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for sanity of MSR if they're valid or they're for reserved range for WRMSR and RDMSR
|
||||
|
|
@ -278,7 +339,7 @@ MsrHandleWrmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Perform the WRMSR
|
||||
//
|
||||
CpuWriteMsr((unsigned long)GuestRegs->rcx, Msr.Flags);
|
||||
CpuWriteMsr((ULONG)GuestRegs->rcx, Msr.Flags);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -317,22 +378,22 @@ MsrHandleSetMsrBitmap(VIRTUAL_MACHINE_STATE * VCpu, UINT32 Msr, BOOLEAN ReadDete
|
|||
{
|
||||
if (ReadDetection)
|
||||
{
|
||||
SetBit(Msr, (unsigned long *)VCpu->MsrBitmapVirtualAddress);
|
||||
SetBit(Msr, (ULONG *)VCpu->MsrBitmapVirtualAddress);
|
||||
}
|
||||
if (WriteDetection)
|
||||
{
|
||||
SetBit(Msr, (unsigned long *)VCpu->MsrBitmapVirtualAddress + 2048);
|
||||
SetBit(Msr, (ULONG *)VCpu->MsrBitmapVirtualAddress + 2048);
|
||||
}
|
||||
}
|
||||
else if ((0xC0000000 <= Msr) && (Msr <= 0xC0001FFF))
|
||||
{
|
||||
if (ReadDetection)
|
||||
{
|
||||
SetBit(Msr - 0xC0000000, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
SetBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
}
|
||||
if (WriteDetection)
|
||||
{
|
||||
SetBit(Msr - 0xC0000000, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
SetBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -366,22 +427,22 @@ MsrHandleUnSetMsrBitmap(VIRTUAL_MACHINE_STATE * VCpu, UINT32 Msr, BOOLEAN ReadDe
|
|||
{
|
||||
if (ReadDetection)
|
||||
{
|
||||
ClearBit(Msr, (unsigned long *)VCpu->MsrBitmapVirtualAddress);
|
||||
ClearBit(Msr, (ULONG *)VCpu->MsrBitmapVirtualAddress);
|
||||
}
|
||||
if (WriteDetection)
|
||||
{
|
||||
ClearBit(Msr, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(Msr, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
}
|
||||
}
|
||||
else if ((0xC0000000 <= Msr) && (Msr <= 0xC0001FFF))
|
||||
{
|
||||
if (ReadDetection)
|
||||
{
|
||||
ClearBit(Msr - 0xC0000000, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
ClearBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
}
|
||||
if (WriteDetection)
|
||||
{
|
||||
ClearBit(Msr - 0xC0000000, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
ClearBit(Msr - 0xC0000000, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -404,13 +465,13 @@ MsrHandleFilterMsrReadBitmap(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Ignore IA32_KERNEL_GSBASE (0xC0000102)
|
||||
//
|
||||
ClearBit(0x102, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
ClearBit(0x102, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 1024));
|
||||
|
||||
//
|
||||
// Ignore IA32_MPERF (0x000000e7), and IA32_APERF (0x000000e8)
|
||||
//
|
||||
ClearBit(0xe7, (unsigned long *)VCpu->MsrBitmapVirtualAddress);
|
||||
ClearBit(0xe8, (unsigned long *)VCpu->MsrBitmapVirtualAddress);
|
||||
ClearBit(0xe7, (ULONG *)VCpu->MsrBitmapVirtualAddress);
|
||||
ClearBit(0xe8, (ULONG *)VCpu->MsrBitmapVirtualAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -426,19 +487,19 @@ MsrHandleFilterMsrWriteBitmap(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Ignore IA32_KERNEL_GSBASE (0xC0000102)
|
||||
//
|
||||
ClearBit(0x102, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
ClearBit(0x102, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 3072));
|
||||
|
||||
//
|
||||
// Ignore IA32_MPERF (0x000000e7), and IA32_APERF (0x000000e8)
|
||||
//
|
||||
ClearBit(0xe7, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0xe8, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0xe7, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0xe8, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
|
||||
//
|
||||
// Ignore IA32_SPEC_CTRL (0x00000048), and IA32_PRED_CMD (0x00000049)
|
||||
//
|
||||
ClearBit(0x48, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0x49, (unsigned long *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0x48, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
ClearBit(0x49, (ULONG *)(VCpu->MsrBitmapVirtualAddress + 2048));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -457,7 +518,7 @@ MsrHandlePerformMsrBitmapReadChange(VIRTUAL_MACHINE_STATE * VCpu, UINT32 MsrMask
|
|||
//
|
||||
// Means all the bitmaps should be put to 1
|
||||
//
|
||||
memset((void *)VCpu->MsrBitmapVirtualAddress, 0xff, 2048);
|
||||
memset((PVOID)VCpu->MsrBitmapVirtualAddress, 0xff, 2048);
|
||||
|
||||
//
|
||||
// Filter MSR Bitmap for special MSRs
|
||||
|
|
@ -486,7 +547,7 @@ MsrHandlePerformMsrBitmapReadReset(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Means all the bitmaps should be put to 0
|
||||
//
|
||||
memset((void *)VCpu->MsrBitmapVirtualAddress, 0x0, 2048);
|
||||
memset((PVOID)VCpu->MsrBitmapVirtualAddress, 0x0, 2048);
|
||||
}
|
||||
/**
|
||||
* @brief Change MSR Bitmap for write
|
||||
|
|
@ -504,7 +565,7 @@ MsrHandlePerformMsrBitmapWriteChange(VIRTUAL_MACHINE_STATE * VCpu, UINT32 MsrMas
|
|||
//
|
||||
// Means all the bitmaps should be put to 1
|
||||
//
|
||||
memset((void *)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0xff, 2048);
|
||||
memset((PVOID)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0xff, 2048);
|
||||
|
||||
//
|
||||
// Filter MSR Bitmap for special MSRs
|
||||
|
|
@ -533,5 +594,5 @@ MsrHandlePerformMsrBitmapWriteReset(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
//
|
||||
// Means all the bitmaps should be put to 0
|
||||
//
|
||||
memset((void *)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0x0, 2048);
|
||||
memset((PVOID)((UINT64)VCpu->MsrBitmapVirtualAddress + 2048), 0x0, 2048);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,18 +33,10 @@ MtfHandleVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
VCpu->IgnoreMtfUnset = FALSE;
|
||||
|
||||
//
|
||||
// Check if we need to re-apply a breakpoint or not
|
||||
// We check it separately because the guest might step
|
||||
// instructions on an MTF so we want to check for the step too
|
||||
// Check for KD related MTFs
|
||||
//
|
||||
if (g_Callbacks.BreakpointCheckAndHandleReApplyingBreakpoint != NULL &&
|
||||
g_Callbacks.BreakpointCheckAndHandleReApplyingBreakpoint(VCpu->CoreId))
|
||||
if (VmmCallbackHandleMtfCallback(VCpu->CoreId))
|
||||
{
|
||||
//
|
||||
// Check for re-enabling external interrupts
|
||||
//
|
||||
HvEnableAndCheckForPreviousExternalInterrupts(VCpu);
|
||||
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
|
|
@ -77,48 +69,6 @@ MtfHandleVmexit(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
HvEnableAndCheckForPreviousExternalInterrupts(VCpu);
|
||||
}
|
||||
|
||||
//
|
||||
// Check for instrumentation step-in
|
||||
//
|
||||
if (VCpu->RegisterBreakOnMtf)
|
||||
{
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
IsMtfHandled = TRUE;
|
||||
|
||||
//
|
||||
// Change the MTF registration state (might be changed in the caller)
|
||||
//
|
||||
VCpu->RegisterBreakOnMtf = FALSE;
|
||||
|
||||
//
|
||||
// Handle MTF in the debugger
|
||||
//
|
||||
VmmCallbackRegisteredMtfHandler(VCpu->CoreId);
|
||||
}
|
||||
|
||||
//
|
||||
// check the condition of passing the execution to NMIs
|
||||
//
|
||||
// This one wastes one week of my life!
|
||||
// During the testing we realized the !epthook command in Debugger Mode
|
||||
// is not working. After some tests, it's because if in the middle of a
|
||||
// command in vmx-root and NMI is sent and the debugger waits for another
|
||||
// MTF, we'll ignore that MTF and a new MTF is not set again.
|
||||
// That's why we moved this check here so every command that needs a task
|
||||
// from MTF is doing its tasks and when we reached here, the check for halting
|
||||
// the debuggee in MTF is performed
|
||||
//
|
||||
else if (g_Callbacks.KdCheckAndHandleNmiCallback != NULL &&
|
||||
g_Callbacks.KdCheckAndHandleNmiCallback(VCpu->CoreId))
|
||||
{
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
IsMtfHandled = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for ignored MTFs
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Vmx.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief VMX Instructions and VMX Related Functions
|
||||
|
|
@ -25,7 +25,7 @@ VmxCheckVmxSupport()
|
|||
//
|
||||
// Gets Processor Info and Feature Bits
|
||||
//
|
||||
CpuCpuId((int *)&Data, 1);
|
||||
CpuCpuId((INT *)&Data, 1);
|
||||
|
||||
//
|
||||
// Check For VMX Bit CPUID.ECX[5]
|
||||
|
|
@ -132,7 +132,7 @@ VmxInitialize()
|
|||
|
||||
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
for (size_t ProcessorID = 0; ProcessorID < ProcessorsCount; ProcessorID++)
|
||||
for (SIZE_T ProcessorID = 0; ProcessorID < ProcessorsCount; ProcessorID++)
|
||||
{
|
||||
//
|
||||
// *** Launching VM for Test (in the all logical processor) ***
|
||||
|
|
@ -317,15 +317,6 @@ VmxPerformVirtualizationOnAllCores()
|
|||
LogDebugInfo("MTRR memory map built successfully");
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize Pool Manager
|
||||
//
|
||||
if (!PoolManagerInitialize())
|
||||
{
|
||||
LogError("Err, could not initialize pool manager");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!EptLogicalProcessorInitialize())
|
||||
{
|
||||
//
|
||||
|
|
@ -1034,7 +1025,7 @@ VmxPerformVmxoff(VIRTUAL_MACHINE_STATE * VCpu)
|
|||
// since immediately after vmxoff, an interrupt might occur and context switch
|
||||
// might change the XMM registers
|
||||
//
|
||||
AsmVmxoffRestoreXmmRegs((unsigned long long)VCpu->XmmRegs);
|
||||
AsmVmxoffRestoreXmmRegs((UINT64)VCpu->XmmRegs);
|
||||
|
||||
//
|
||||
// Before using vmxoff, you first need to use vmclear on any VMCSes that you want to be able to use again.
|
||||
|
|
@ -1142,7 +1133,7 @@ VmxPerformTermination()
|
|||
//
|
||||
// Free Identity Page Table
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (g_GuestState[i].EptPageTable != NULL)
|
||||
{
|
||||
|
|
@ -1158,11 +1149,6 @@ VmxPerformTermination()
|
|||
PlatformMemFreePool(g_EptState);
|
||||
g_EptState = NULL;
|
||||
|
||||
//
|
||||
// Free the Pool manager
|
||||
//
|
||||
PoolManagerUninitialize();
|
||||
|
||||
//
|
||||
// Uninitialize memory mapper
|
||||
//
|
||||
|
|
@ -1273,9 +1259,9 @@ VmxCompatibleStrlen(const CHAR * S)
|
|||
* string
|
||||
*/
|
||||
UINT32
|
||||
VmxCompatibleWcslen(const wchar_t * S)
|
||||
VmxCompatibleWcslen(const WCHAR * S)
|
||||
{
|
||||
wchar_t Temp = NULL_ZERO;
|
||||
WCHAR Temp = NULL_ZERO;
|
||||
UINT32 Count = 0;
|
||||
UINT64 AlignedAddress;
|
||||
CR3_TYPE GuestCr3;
|
||||
|
|
@ -1299,7 +1285,7 @@ VmxCompatibleWcslen(const wchar_t * S)
|
|||
//
|
||||
// First check
|
||||
//
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1317,7 +1303,7 @@ VmxCompatibleWcslen(const wchar_t * S)
|
|||
/*
|
||||
Temp = *S;
|
||||
*/
|
||||
MemoryMapperReadMemorySafe((UINT64)S, &Temp, sizeof(wchar_t));
|
||||
MemoryMapperReadMemorySafe((UINT64)S, &Temp, sizeof(WCHAR));
|
||||
|
||||
if (Temp != '\0\0')
|
||||
{
|
||||
|
|
@ -1335,7 +1321,7 @@ VmxCompatibleWcslen(const wchar_t * S)
|
|||
|
||||
if (!((UINT64)S & (PAGE_SIZE - 1)))
|
||||
{
|
||||
if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety((UINT64)S, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1528,12 +1514,12 @@ VmxCompatibleStrcmp(const CHAR * Address1,
|
|||
* @return INT32 0x2 indicates error, otherwise the same result as wcscmp in string.h
|
||||
*/
|
||||
INT32
|
||||
VmxCompatibleWcscmp(const wchar_t * Address1,
|
||||
const wchar_t * Address2,
|
||||
SIZE_T Num,
|
||||
BOOLEAN IsWcsncmp)
|
||||
VmxCompatibleWcscmp(const WCHAR * Address1,
|
||||
const WCHAR * Address2,
|
||||
SIZE_T Num,
|
||||
BOOLEAN IsWcsncmp)
|
||||
{
|
||||
wchar_t C1 = NULL_ZERO, C2 = NULL_ZERO;
|
||||
WCHAR C1 = NULL_ZERO, C2 = NULL_ZERO;
|
||||
INT32 Result = 0;
|
||||
UINT32 Count = 0;
|
||||
UINT64 AlignedAddress1, AlignedAddress2;
|
||||
|
|
@ -1557,7 +1543,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1,
|
|||
//
|
||||
// First check
|
||||
//
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(WCHAR)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1596,19 +1582,19 @@ VmxCompatibleWcscmp(const wchar_t * Address1,
|
|||
/*
|
||||
C1 = *Address1;
|
||||
*/
|
||||
MemoryMapperReadMemorySafe((UINT64)Address1, &C1, sizeof(wchar_t));
|
||||
MemoryMapperReadMemorySafe((UINT64)Address1, &C1, sizeof(WCHAR));
|
||||
|
||||
/*
|
||||
C2 = *Address2;
|
||||
*/
|
||||
MemoryMapperReadMemorySafe((UINT64)Address2, &C2, sizeof(wchar_t));
|
||||
MemoryMapperReadMemorySafe((UINT64)Address2, &C2, sizeof(WCHAR));
|
||||
|
||||
Address1++;
|
||||
Address2++;
|
||||
|
||||
if (!((UINT64)AlignedAddress1 & (PAGE_SIZE - 1)))
|
||||
{
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1624,7 +1610,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1,
|
|||
|
||||
if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1)))
|
||||
{
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1666,7 +1652,7 @@ VmxCompatibleWcscmp(const wchar_t * Address1,
|
|||
* @return INT32 0x2 indicates error, otherwise the same result as memcmp in string.h
|
||||
*/
|
||||
INT32
|
||||
VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count)
|
||||
VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, SIZE_T Count)
|
||||
{
|
||||
CHAR C1 = NULL_ZERO, C2 = NULL_ZERO;
|
||||
INT32 Result = 0;
|
||||
|
|
@ -1691,7 +1677,7 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count)
|
|||
//
|
||||
// First check
|
||||
//
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(wchar_t)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety(AlignedAddress1, sizeof(WCHAR)) || !CheckAccessValidityAndSafety(AlignedAddress2, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1721,7 +1707,7 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count)
|
|||
|
||||
if (!((UINT64)AlignedAddress1 & (PAGE_SIZE - 1)))
|
||||
{
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress1, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
@ -1737,7 +1723,7 @@ VmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count)
|
|||
|
||||
if (!((UINT64)AlignedAddress2 & (PAGE_SIZE - 1)))
|
||||
{
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(wchar_t)))
|
||||
if (!CheckAccessValidityAndSafety((UINT64)AlignedAddress2, sizeof(WCHAR)))
|
||||
{
|
||||
//
|
||||
// Error
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ VmxBroadcastNmi(VIRTUAL_MACHINE_STATE * VCpu, NMI_BROADCAST_ACTION_TYPE VmxBroad
|
|||
//
|
||||
// Indicate that we're waiting for NMI
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (i != VCpu->CoreId)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file VmxRegions.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @brief Implement allocations for VMX Regions (VMXON Region, VMCS, MSR Bitmap and etc.)
|
||||
|
|
@ -281,7 +281,7 @@ VmxAllocateInvalidMsrBimap()
|
|||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
SetBit(i, (unsigned long *)InvalidMsrBitmap);
|
||||
SetBit(i, (ULONG *)InvalidMsrBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@
|
|||
* @brief Enable VMX Operation
|
||||
*
|
||||
*/
|
||||
extern void inline AsmEnableVmxOperation();
|
||||
extern VOID inline AsmEnableVmxOperation();
|
||||
|
||||
/**
|
||||
* @brief Restore in vmxoff state
|
||||
*
|
||||
*/
|
||||
extern void inline AsmRestoreToVmxOffState();
|
||||
extern VOID inline AsmRestoreToVmxOffState();
|
||||
|
||||
/**
|
||||
* @brief Request Vmcall
|
||||
|
|
@ -37,18 +37,18 @@ extern void inline AsmRestoreToVmxOffState();
|
|||
* @param OptionalParam3
|
||||
* @return NTSTATUS
|
||||
*/
|
||||
extern NTSTATUS inline AsmVmxVmcall(unsigned long long VmcallNumber,
|
||||
unsigned long long OptionalParam1,
|
||||
unsigned long long OptionalParam2,
|
||||
long long OptionalParam3);
|
||||
extern NTSTATUS inline AsmVmxVmcall(UINT64 VmcallNumber,
|
||||
UINT64 OptionalParam1,
|
||||
UINT64 OptionalParam2,
|
||||
UINT64 OptionalParam3);
|
||||
|
||||
/**
|
||||
* @brief Hyper-v vmcall handler
|
||||
*
|
||||
* @param GuestRegisters
|
||||
* @return void
|
||||
* @return VOID
|
||||
*/
|
||||
extern void inline AsmHypervVmcall(unsigned long long GuestRegisters);
|
||||
extern VOID inline AsmHypervVmcall(UINT64 GuestRegisters);
|
||||
|
||||
/**
|
||||
* @brief VMFUNC instruction
|
||||
|
|
@ -56,9 +56,9 @@ extern void inline AsmHypervVmcall(unsigned long long GuestRegisters);
|
|||
* @param EptpIndex
|
||||
* @param Function
|
||||
*
|
||||
* @return unsigned long long I'm not sure what it returns
|
||||
* @return UINT64 I'm not sure what it returns
|
||||
*/
|
||||
extern unsigned long long inline AsmVmfunc(unsigned long EptpIndex, unsigned long Function);
|
||||
extern UINT64 inline AsmVmfunc(ULONG EptpIndex, ULONG Function);
|
||||
|
||||
//
|
||||
// ==================== Vmx Context State Operations ====================
|
||||
|
|
@ -69,14 +69,14 @@ extern unsigned long long inline AsmVmfunc(unsigned long EptpIndex, unsigned lon
|
|||
* @brief Save state on vmx
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
AsmVmxSaveState();
|
||||
|
||||
/**
|
||||
* @brief Restore state on vmx
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
AsmVmxRestoreState();
|
||||
|
||||
//
|
||||
|
|
@ -88,20 +88,20 @@ AsmVmxRestoreState();
|
|||
* @brief Vm-exit handler
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
AsmVmexitHandler();
|
||||
|
||||
/**
|
||||
* @brief Save vmxoff state
|
||||
*
|
||||
*/
|
||||
extern void inline AsmSaveVmxOffState();
|
||||
extern VOID inline AsmSaveVmxOffState();
|
||||
|
||||
/**
|
||||
* @brief Restore XMM registers
|
||||
*
|
||||
*/
|
||||
extern void inline AsmVmxoffRestoreXmmRegs(unsigned long long XmmRegs);
|
||||
extern VOID inline AsmVmxoffRestoreXmmRegs(UINT64 XmmRegs);
|
||||
|
||||
//
|
||||
// ==================== Extended Page Tables ====================
|
||||
|
|
@ -113,18 +113,18 @@ extern void inline AsmVmxoffRestoreXmmRegs(unsigned long long XmmRegs);
|
|||
*
|
||||
* @param Type
|
||||
* @param Descriptors
|
||||
* @return unsigned char
|
||||
* @return UCHAR
|
||||
*/
|
||||
extern unsigned char inline AsmInvept(unsigned long Type, void * Descriptors);
|
||||
extern UCHAR inline AsmInvept(ULONG Type, PVOID Descriptors);
|
||||
|
||||
/**
|
||||
* @brief INVVPID wrapper
|
||||
*
|
||||
* @param Type
|
||||
* @param Descriptors
|
||||
* @return unsigned char
|
||||
* @return UCHAR
|
||||
*/
|
||||
extern unsigned char inline AsmInvvpid(unsigned long Type, void * Descriptors);
|
||||
extern UCHAR inline AsmInvvpid(ULONG Type, PVOID Descriptors);
|
||||
|
||||
//
|
||||
// ==================== Get segment registers ====================
|
||||
|
|
@ -136,77 +136,77 @@ extern unsigned char inline AsmInvvpid(unsigned long Type, void * Descriptors);
|
|||
/**
|
||||
* @brief Get CS Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetCs();
|
||||
|
||||
/**
|
||||
* @brief Get DS Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetDs();
|
||||
|
||||
extern void
|
||||
AsmSetDs(unsigned short DsSelector);
|
||||
extern VOID
|
||||
AsmSetDs(UINT16 DsSelector);
|
||||
|
||||
/**
|
||||
* @brief Get ES Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetEs();
|
||||
|
||||
extern void
|
||||
AsmSetEs(unsigned short EsSelector);
|
||||
extern VOID
|
||||
AsmSetEs(UINT16 EsSelector);
|
||||
|
||||
/**
|
||||
* @brief Get SS Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetSs();
|
||||
|
||||
extern void
|
||||
AsmSetSs(unsigned short SsSelector);
|
||||
extern VOID
|
||||
AsmSetSs(UINT16 SsSelector);
|
||||
|
||||
/**
|
||||
* @brief Get FS Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetFs();
|
||||
|
||||
extern void
|
||||
AsmSetFs(unsigned short FsSelector);
|
||||
extern VOID
|
||||
AsmSetFs(UINT16 FsSelector);
|
||||
|
||||
/**
|
||||
* @brief Get GS Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetGs();
|
||||
|
||||
/**
|
||||
* @brief Get LDTR Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetLdtr();
|
||||
|
||||
/**
|
||||
* @brief Get TR Register
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetTr();
|
||||
|
||||
/* ******* Gdt related functions ******* */
|
||||
|
|
@ -214,16 +214,16 @@ AsmGetTr();
|
|||
/**
|
||||
* @brief get GDT base
|
||||
*
|
||||
* @return unsigned long long
|
||||
* @return UINT64
|
||||
*/
|
||||
extern unsigned long long inline AsmGetGdtBase();
|
||||
extern UINT64 inline AsmGetGdtBase();
|
||||
|
||||
/**
|
||||
* @brief Get GDT Limit
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetGdtLimit();
|
||||
|
||||
/* ******* Idt related functions ******* */
|
||||
|
|
@ -231,20 +231,20 @@ AsmGetGdtLimit();
|
|||
/**
|
||||
* @brief Get IDT base
|
||||
*
|
||||
* @return unsigned long long
|
||||
* @return UINT64
|
||||
*/
|
||||
extern unsigned long long inline AsmGetIdtBase();
|
||||
extern UINT64 inline AsmGetIdtBase();
|
||||
|
||||
/**
|
||||
* @brief Get IDT limit
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetIdtLimit();
|
||||
|
||||
extern UINT32
|
||||
AsmGetAccessRights(unsigned short Selector);
|
||||
AsmGetAccessRights(UINT16 Selector);
|
||||
//
|
||||
// ==================== Common Functions ====================
|
||||
// File : AsmCommon.asm
|
||||
|
|
@ -253,22 +253,22 @@ AsmGetAccessRights(unsigned short Selector);
|
|||
/**
|
||||
* @brief Get R/EFLAGS
|
||||
*
|
||||
* @return unsigned short
|
||||
* @return UINT16
|
||||
*/
|
||||
extern unsigned short
|
||||
extern UINT16
|
||||
AsmGetRflags();
|
||||
|
||||
/**
|
||||
* @brief Run CLI Instruction
|
||||
*
|
||||
*/
|
||||
extern void inline AsmCliInstruction();
|
||||
extern VOID inline AsmCliInstruction();
|
||||
|
||||
/**
|
||||
* @brief Run STI Instruction
|
||||
*
|
||||
*/
|
||||
extern void inline AsmStiInstruction();
|
||||
extern VOID inline AsmStiInstruction();
|
||||
|
||||
/**
|
||||
* @brief Reload new GDTR
|
||||
|
|
@ -276,23 +276,24 @@ extern void inline AsmStiInstruction();
|
|||
* @param GdtBase
|
||||
* @param GdtLimit
|
||||
*/
|
||||
extern void
|
||||
AsmReloadGdtr(void * GdtBase, unsigned long GdtLimit);
|
||||
extern VOID
|
||||
AsmReloadGdtr(PVOID GdtBase, ULONG GdtLimit);
|
||||
|
||||
/**
|
||||
* @brief Reload new IDTR
|
||||
*
|
||||
* @param GdtBase
|
||||
* @param GdtLimit
|
||||
* @param IdtrBase
|
||||
* @param IdtrLimit
|
||||
*/
|
||||
extern void
|
||||
AsmReloadIdtr(void * GdtBase, unsigned long GdtLimit);
|
||||
extern VOID
|
||||
AsmReloadIdtr(PVOID IdtrBase, ULONG IdtrLimit);
|
||||
|
||||
/**
|
||||
* @brief Read SSP
|
||||
*
|
||||
* @return UINT64
|
||||
*/
|
||||
extern unsigned long long
|
||||
extern UINT64
|
||||
AsmReadSsp();
|
||||
|
||||
//
|
||||
|
|
@ -304,8 +305,8 @@ AsmReadSsp();
|
|||
* @brief Detour hook handler
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
AsmGeneralDetourHook(void);
|
||||
extern VOID
|
||||
AsmGeneralDetourHook(VOID);
|
||||
|
||||
//
|
||||
// ==================== Kernel Test Functions ====================
|
||||
|
|
@ -316,11 +317,11 @@ AsmGeneralDetourHook(void);
|
|||
* @brief Tests with test tags wrapper
|
||||
*
|
||||
*/
|
||||
extern unsigned long long
|
||||
AsmTestWrapperWithTestTags(unsigned long long Param1,
|
||||
unsigned long long Param2,
|
||||
unsigned long long Param3,
|
||||
unsigned long long Param4);
|
||||
extern UINT64
|
||||
AsmTestWrapperWithTestTags(UINT64 Param1,
|
||||
UINT64 Param2,
|
||||
UINT64 Param3,
|
||||
UINT64 Param4);
|
||||
|
||||
//
|
||||
// ==================== Interrupt Handler Functions ====================
|
||||
|
|
@ -331,215 +332,215 @@ AsmTestWrapperWithTestTags(unsigned long long Param1,
|
|||
* @brief The 0th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler0();
|
||||
|
||||
/**
|
||||
* @brief The 1st entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler1();
|
||||
|
||||
/**
|
||||
* @brief The 2nd entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler2();
|
||||
|
||||
/**
|
||||
* @brief The 3rd entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler3();
|
||||
|
||||
/**
|
||||
* @brief The 4th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler4();
|
||||
|
||||
/**
|
||||
* @brief The 5th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler5();
|
||||
|
||||
/**
|
||||
* @brief The 6th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler6();
|
||||
|
||||
/**
|
||||
* @brief The 7th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler7();
|
||||
|
||||
/**
|
||||
* @brief The 8th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler8();
|
||||
|
||||
/**
|
||||
* @brief The 9th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler9();
|
||||
|
||||
/**
|
||||
* @brief The 10th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler10();
|
||||
|
||||
/**
|
||||
* @brief The 11th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler11();
|
||||
|
||||
/**
|
||||
* @brief The 12th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler12();
|
||||
|
||||
/**
|
||||
* @brief The 13th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler13();
|
||||
|
||||
/**
|
||||
* @brief The 14th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler14();
|
||||
|
||||
/**
|
||||
* @brief The 15th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler15();
|
||||
|
||||
/**
|
||||
* @brief The 16th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler16();
|
||||
|
||||
/**
|
||||
* @brief The 17th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler17();
|
||||
|
||||
/**
|
||||
* @brief The 18th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler18();
|
||||
|
||||
/**
|
||||
* @brief The 19th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler19();
|
||||
|
||||
/**
|
||||
* @brief The 20th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler20();
|
||||
|
||||
/**
|
||||
* @brief The 21st entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler21();
|
||||
|
||||
/**
|
||||
* @brief The 22nd entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler22();
|
||||
|
||||
/**
|
||||
* @brief The 23rd entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler23();
|
||||
|
||||
/**
|
||||
* @brief The 24th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler24();
|
||||
|
||||
/**
|
||||
* @brief The 25th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler25();
|
||||
|
||||
/**
|
||||
* @brief The 26th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler26();
|
||||
|
||||
/**
|
||||
* @brief The 27th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler27();
|
||||
|
||||
/**
|
||||
* @brief The 28th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler28();
|
||||
|
||||
/**
|
||||
* @brief The 29th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler29();
|
||||
|
||||
/**
|
||||
* @brief The 30th entry in IDT
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
InterruptHandler30();
|
||||
|
|
|
|||
|
|
@ -15,11 +15,11 @@
|
|||
// Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
int
|
||||
TestBit(int BitNumber, unsigned long * Addr);
|
||||
INT
|
||||
TestBit(INT BitNumber, ULONG * Addr);
|
||||
|
||||
void
|
||||
ClearBit(int BitNumber, unsigned long * Addr);
|
||||
VOID
|
||||
ClearBit(INT BitNumber, ULONG * Addr);
|
||||
|
||||
void
|
||||
SetBit(int BitNumber, unsigned long * Addr);
|
||||
VOID
|
||||
SetBit(INT BitNumber, ULONG * Addr);
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@
|
|||
*/
|
||||
#define RPL_MASK 3
|
||||
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
#define ORDER_LONG (sizeof(unsigned long) == 4 ? 5 : 6)
|
||||
#define BITS_PER_LONG (sizeof(ULONG) * 8)
|
||||
#define ORDER_LONG (sizeof(ULONG) == 4 ? 5 : 6)
|
||||
|
||||
#define BITMAP_ENTRY(_nr, _bmap) ((_bmap))[(_nr) / BITS_PER_LONG]
|
||||
#define BITMAP_SHIFT(_nr) ((_nr) % BITS_PER_LONG)
|
||||
|
|
@ -82,10 +82,10 @@ typedef SEGMENT_DESCRIPTOR_32 * PSEGMENT_DESCRIPTOR;
|
|||
*/
|
||||
typedef struct _CPUID
|
||||
{
|
||||
int eax;
|
||||
int ebx;
|
||||
int ecx;
|
||||
int edx;
|
||||
INT eax;
|
||||
INT ebx;
|
||||
INT ecx;
|
||||
INT edx;
|
||||
} CPUID, *PCPUID;
|
||||
|
||||
typedef union _CR_FIXED
|
||||
|
|
@ -94,8 +94,8 @@ typedef union _CR_FIXED
|
|||
|
||||
struct
|
||||
{
|
||||
unsigned long Low;
|
||||
long High;
|
||||
ULONG Low;
|
||||
LONG High;
|
||||
|
||||
} Fields;
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ typedef struct _NT_KPROCESS
|
|||
* @brief Prototype to run a function on a logical core
|
||||
*
|
||||
*/
|
||||
typedef void (*RunOnLogicalCoreFunc)(ULONG ProcessorId);
|
||||
typedef VOID (*RunOnLogicalCoreFunc)(ULONG ProcessorId);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// External Functions //
|
||||
|
|
@ -153,7 +153,7 @@ BOOLEAN
|
|||
CommonAffinityBroadcastToProcessors(_In_ ULONG ProcessorNumber, _In_ RunOnLogicalCoreFunc Routine);
|
||||
|
||||
BOOLEAN
|
||||
CommonIsStringStartsWith(const char * pre, const char * str);
|
||||
CommonIsStringStartsWith(const CHAR * pre, const CHAR * str);
|
||||
|
||||
BOOLEAN
|
||||
CommonIsGuestOnUsermode32Bit();
|
||||
|
|
@ -162,7 +162,7 @@ PCHAR
|
|||
CommonGetProcessNameFromProcessControlBlock(PEPROCESS eprocess);
|
||||
|
||||
VOID
|
||||
CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, int * CpuInfo);
|
||||
CommonCpuidInstruction(UINT32 Func, UINT32 SubFunc, INT * CpuInfo);
|
||||
|
||||
VOID
|
||||
CommonWriteDebugInformation(VIRTUAL_MACHINE_STATE * VCpu);
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ typedef struct _VIRTUAL_MACHINE_STATE
|
|||
BOOLEAN WaitForImmediateVmexit; // Whether the current core is waiting for an immediate vm-exit or not
|
||||
BOOLEAN EnableExternalInterruptsOnContinue; // Whether to enable external interrupts on the continue or not
|
||||
BOOLEAN EnableExternalInterruptsOnContinueMtf; // Whether to enable external interrupts on the continue state of MTF or not
|
||||
BOOLEAN RegisterBreakOnMtf; // Registered Break in the case of MTFs (used in instrumentation step-in)
|
||||
BOOLEAN InstrumentationStepInMtf; // Instrumentation step in MTF or not (used for single stepping with MTF)
|
||||
BOOLEAN IgnoreOneMtf; // Ignore (mark as handled) for one MTF
|
||||
BOOLEAN NotNormalEptp; // Indicate that the target processor is on the normal EPTP or not
|
||||
BOOLEAN MbecEnabled; // Indicate that the target processor is on MBEC-enabled mode or not
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
// Exported Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
__declspec(dllexport) NTSTATUS DllInitialize(_In_ PUNICODE_STRING RegistryPath);
|
||||
__declspec(dllexport) NTSTATUS
|
||||
DllInitialize(_In_ PUNICODE_STRING RegistryPath);
|
||||
|
||||
__declspec(dllexport) NTSTATUS DllUnload(void);
|
||||
__declspec(dllexport) NTSTATUS DllUnload(VOID);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/**
|
||||
* @file SyscallHook.h
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author jtaw5649
|
||||
* @brief Header for syscall hook callbacks
|
||||
* @details
|
||||
*
|
||||
|
|
@ -78,6 +79,9 @@ typedef struct _SYSCALL_CALLBACK_TRAP_FLAG_STATE
|
|||
BOOLEAN
|
||||
SyscallCallbackInitialize();
|
||||
|
||||
BOOLEAN
|
||||
SyscallCallbackIsInitialized();
|
||||
|
||||
BOOLEAN
|
||||
SyscallCallbackUninitialize();
|
||||
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ VmmCallbackUnhandledEptViolation(UINT32 CoreId,
|
|||
UINT64 ViolationQualification,
|
||||
UINT64 GuestPhysicalAddr);
|
||||
|
||||
VOID
|
||||
VmmCallbackSetLastError(UINT32 LastError);
|
||||
BOOLEAN
|
||||
VmmCallbackHandleMtfCallback(UINT32 CoreId);
|
||||
|
||||
VOID
|
||||
VmmCallbackRegisteredMtfHandler(UINT32 CoreId);
|
||||
VmmCallbackSetLastError(UINT32 LastError);
|
||||
|
||||
VOID
|
||||
VmmCallbackNmiBroadcastRequestHandler(UINT32 CoreId, BOOLEAN IsOnVmxNmiHandler);
|
||||
|
|
@ -72,6 +72,25 @@ DebuggingCallbackHandleDebugBreakpointException(UINT32 CoreId);
|
|||
BOOLEAN
|
||||
DebuggingCallbackCheckThreadInterception(UINT32 CoreId);
|
||||
|
||||
BOOLEAN
|
||||
DebuggingCallbackTriggerOnClockAndIpiEvents(UINT32 CoreId);
|
||||
|
||||
BOOLEAN
|
||||
DebuggingCallbackIgnoreHandlingMov2DebugRegs(UINT32 CoreId);
|
||||
|
||||
//
|
||||
// Pool Manager Callbacks
|
||||
//
|
||||
|
||||
BOOLEAN
|
||||
PoolManagerCallbackRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention);
|
||||
|
||||
UINT64
|
||||
PoolManagerCallbackRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size);
|
||||
|
||||
BOOLEAN
|
||||
PoolManagerCallbackFreePool(UINT64 AddressToFree);
|
||||
|
||||
//
|
||||
// Interception Callbacks
|
||||
//
|
||||
|
|
|
|||
|
|
@ -57,55 +57,55 @@ IoInDword(UINT16 port)
|
|||
return CpuIoInDword(port);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoInByteString(UINT16 port, UINT8 * data, UINT32 size)
|
||||
{
|
||||
CpuIoInByteString(port, data, size);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoInWordString(UINT16 port, UINT16 * data, UINT32 size)
|
||||
{
|
||||
CpuIoInWordString(port, data, size);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoInDwordString(UINT16 port, UINT32 * data, UINT32 size)
|
||||
{
|
||||
CpuIoInDwordString(port, data, size);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutByte(UINT16 port, UINT8 value)
|
||||
{
|
||||
CpuIoOutByte(port, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutWord(UINT16 port, UINT16 value)
|
||||
{
|
||||
CpuIoOutWord(port, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutDword(UINT16 port, UINT32 value)
|
||||
{
|
||||
CpuIoOutDword(port, value);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutByteString(UINT16 port, UINT8 * data, UINT32 count)
|
||||
{
|
||||
CpuIoOutByteString(port, data, count);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutWordString(UINT16 port, UINT16 * data, UINT32 count)
|
||||
{
|
||||
CpuIoOutWordString(port, data, count);
|
||||
}
|
||||
|
||||
inline void
|
||||
inline VOID
|
||||
IoOutDwordString(UINT16 port, UINT32 * data, UINT32 count)
|
||||
{
|
||||
CpuIoOutDwordString(port, data, count);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@
|
|||
// Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
BOOLEAN
|
||||
MsrHandleIsHypervSyntheticMsr(_In_ UINT32 TargetMsr);
|
||||
|
||||
VOID
|
||||
MsrHandleRdmsrVmexit(VIRTUAL_MACHINE_STATE * VCpu);
|
||||
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ UINT32
|
|||
VmxCompatibleStrlen(const CHAR * S);
|
||||
|
||||
UINT32
|
||||
VmxCompatibleWcslen(const wchar_t * S);
|
||||
VmxCompatibleWcslen(const WCHAR * S);
|
||||
|
||||
INT32
|
||||
VmxCompatibleStrcmp(const CHAR * Address1,
|
||||
|
|
@ -311,12 +311,12 @@ VmxCompatibleStrcmp(const CHAR * Address1,
|
|||
BOOLEAN IsStrncmp);
|
||||
|
||||
INT32
|
||||
VmxCompatibleWcscmp(const wchar_t * Address1,
|
||||
const wchar_t * Address2,
|
||||
SIZE_T Num,
|
||||
BOOLEAN IsWcsncmp);
|
||||
VmxCompatibleWcscmp(const WCHAR * Address1,
|
||||
const WCHAR * Address2,
|
||||
SIZE_T Num,
|
||||
BOOLEAN IsWcsncmp);
|
||||
|
||||
INT32
|
||||
VmxCompatibleMemcmp(const CHAR * Address1,
|
||||
const CHAR * Address2,
|
||||
size_t Count);
|
||||
SIZE_T Count);
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@
|
|||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\include\components\interface\HyperLogCallback.c" />
|
||||
<ClCompile Include="..\include\components\callback\code\HyperLogCallback.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\AvlTree.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\BinarySearch.c" />
|
||||
<ClCompile Include="..\include\components\optimizations\code\InsertionSort.c" />
|
||||
|
|
@ -165,7 +165,6 @@
|
|||
<ClCompile Include="code\memory\Layout.c" />
|
||||
<ClCompile Include="code\memory\MemoryManager.c" />
|
||||
<ClCompile Include="code\memory\MemoryMapper.c" />
|
||||
<ClCompile Include="code\memory\PoolManager.c" />
|
||||
<ClCompile Include="code\memory\Segmentation.c" />
|
||||
<ClCompile Include="code\memory\SwitchLayout.c" />
|
||||
<ClCompile Include="code\mmio\MmioShadowing.c" />
|
||||
|
|
@ -234,7 +233,7 @@
|
|||
<ClInclude Include="..\dependencies\zydis\include\Zydis\Status.h" />
|
||||
<ClInclude Include="..\dependencies\zydis\include\Zydis\Utils.h" />
|
||||
<ClInclude Include="..\dependencies\zydis\include\Zydis\Zydis.h" />
|
||||
<ClInclude Include="..\include\components\interface\HyperLogCallback.h" />
|
||||
<ClInclude Include="..\include\components\callback\header\HyperLogCallback.h" />
|
||||
<ClInclude Include="..\include\components\optimizations\header\AvlTree.h" />
|
||||
<ClInclude Include="..\include\components\optimizations\header\BinarySearch.h" />
|
||||
<ClInclude Include="..\include\components\optimizations\header\InsertionSort.h" />
|
||||
|
|
@ -272,7 +271,6 @@
|
|||
<ClInclude Include="header\memory\Conversion.h" />
|
||||
<ClInclude Include="header\memory\Layout.h" />
|
||||
<ClInclude Include="header\memory\MemoryMapper.h" />
|
||||
<ClInclude Include="header\memory\PoolManager.h" />
|
||||
<ClInclude Include="header\memory\Segmentation.h" />
|
||||
<ClInclude Include="header\memory\SwitchLayout.h" />
|
||||
<ClInclude Include="header\mmio\MmioShadowing.h" />
|
||||
|
|
|
|||
|
|
@ -141,6 +141,12 @@
|
|||
<Filter Include="header\mmio">
|
||||
<UniqueIdentifier>{c310c4a9-c337-454d-94ca-4c6b1216cf41}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="code\components\callback">
|
||||
<UniqueIdentifier>{20e523af-8b6d-4293-bd6d-ce6087f2d4a2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="header\components\callback">
|
||||
<UniqueIdentifier>{58bb81a8-dd12-4e47-b6c8-7d61981fef62}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="code\common\Common.c">
|
||||
|
|
@ -197,9 +203,6 @@
|
|||
<ClCompile Include="code\memory\MemoryMapper.c">
|
||||
<Filter>code\memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\memory\PoolManager.c">
|
||||
<Filter>code\memory</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\components\registers\DebugRegisters.c">
|
||||
<Filter>code\components\registers</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -314,9 +317,6 @@
|
|||
<ClCompile Include="code\mmio\MmioShadowing.c">
|
||||
<Filter>code\mmio</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\components\interface\HyperLogCallback.c">
|
||||
<Filter>code\interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\hooks\syscall-hook\SyscallCallback.c">
|
||||
<Filter>code\hooks\syscall-hook</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -338,6 +338,9 @@
|
|||
<ClCompile Include="..\include\platform\kernel\code\PlatformBroadcast.c">
|
||||
<Filter>code\platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\include\components\callback\code\HyperLogCallback.c">
|
||||
<Filter>code\components\callback</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
|
@ -388,9 +391,6 @@
|
|||
<ClInclude Include="header\memory\MemoryMapper.h">
|
||||
<Filter>header\memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="header\memory\PoolManager.h">
|
||||
<Filter>header\memory</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="header\vmm\vmx\VmxMechanisms.h">
|
||||
<Filter>header\vmm\vmx</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -601,9 +601,6 @@
|
|||
<ClInclude Include="header\mmio\MmioShadowing.h">
|
||||
<Filter>header\mmio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\components\interface\HyperLogCallback.h">
|
||||
<Filter>header\interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="header\hooks\SyscallCallback.h">
|
||||
<Filter>header\hooks</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -622,6 +619,9 @@
|
|||
<ClInclude Include="..\include\platform\kernel\header\PlatformBroadcast.h">
|
||||
<Filter>header\platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\include\components\callback\header\HyperLogCallback.h">
|
||||
<Filter>header\components\callback</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="code\assembly\AsmCommon.asm">
|
||||
|
|
|
|||
|
|
@ -95,7 +95,6 @@
|
|||
#include "memory/MemoryMapper.h"
|
||||
#include "interface/Dispatch.h"
|
||||
#include "common/Msr.h"
|
||||
#include "memory/PoolManager.h"
|
||||
#include "common/Trace.h"
|
||||
#include "assembly/InlineAsm.h"
|
||||
#include "vmm/ept/Vpid.h"
|
||||
|
|
@ -176,7 +175,7 @@
|
|||
//
|
||||
#include "SDK/modules/HyperLog.h"
|
||||
#include "SDK/imports/kernel/HyperDbgHyperLogIntrinsics.h"
|
||||
#include "components/interface/HyperLogCallback.h"
|
||||
#include "components/callback/header/HyperLogCallback.h"
|
||||
|
||||
//
|
||||
// Transparent-mode (hyperevade) headers
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ BreakpointCheckAndPerformActionsOnTrapFlags(UINT32 ProcessId, UINT32 ThreadId, B
|
|||
Result = BinarySearchPerformSearchItem((UINT64 *)&g_TrapFlagState.ThreadInformation[0],
|
||||
g_TrapFlagState.NumberOfItems,
|
||||
&Index,
|
||||
ProcThrdInfo.asUInt);
|
||||
ProcThrdInfo.AsUInt);
|
||||
|
||||
//
|
||||
// Indicate whether the trap flag is set by the debugger or not
|
||||
|
|
@ -195,7 +195,7 @@ BreakpointRestoreTheTrapFlagOnceTriggered(UINT32 ProcessId, UINT32 ThreadId)
|
|||
Result = BinarySearchPerformSearchItem((UINT64 *)&g_TrapFlagState.ThreadInformation[0],
|
||||
g_TrapFlagState.NumberOfItems,
|
||||
&Index,
|
||||
ProcThrdInfo.asUInt);
|
||||
ProcThrdInfo.AsUInt);
|
||||
|
||||
if (Result)
|
||||
{
|
||||
|
|
@ -215,7 +215,7 @@ BreakpointRestoreTheTrapFlagOnceTriggered(UINT32 ProcessId, UINT32 ThreadId)
|
|||
&g_TrapFlagState.NumberOfItems,
|
||||
MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS,
|
||||
&Index, // not used
|
||||
ProcThrdInfo.asUInt);
|
||||
ProcThrdInfo.AsUInt);
|
||||
goto Return;
|
||||
}
|
||||
|
||||
|
|
@ -432,15 +432,14 @@ BreakpointClearAndDeallocateMemory(PDEBUGGEE_BP_DESCRIPTOR BreakpointDesc)
|
|||
/**
|
||||
* @brief Check and reapply breakpoint
|
||||
*
|
||||
* @param CoreId
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
BreakpointCheckAndHandleReApplyingBreakpoint(UINT32 CoreId)
|
||||
BreakpointCheckAndHandleReApplyingBreakpoint(PROCESSOR_DEBUGGING_STATE * DbgState)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
|
||||
BOOLEAN Result = FALSE;
|
||||
|
||||
if (DbgState->SoftwareBreakpointState != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ CallstackWalkthroughStack(PDEBUGGER_SINGLE_CALLSTACK_FRAME AddressToSaveFrames,
|
|||
//
|
||||
// Walkthrough the stack
|
||||
//
|
||||
for (size_t i = 0; i < FrameIndex; i++)
|
||||
for (SIZE_T i = 0; i < FrameIndex; i++)
|
||||
{
|
||||
//
|
||||
// Compute the current stack position address
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ DebuggerCommandReadRegisters(GUEST_REGS * Regs,
|
|||
//
|
||||
// Add General purpose registers
|
||||
//
|
||||
memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)),
|
||||
memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION)),
|
||||
Regs,
|
||||
sizeof(GUEST_REGS));
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ DebuggerCommandReadRegisters(GUEST_REGS * Regs,
|
|||
//
|
||||
// copy at the end of ReadRegisterRequest structure
|
||||
//
|
||||
memcpy((void *)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)),
|
||||
memcpy((PVOID)((CHAR *)ReadRegisterRequest + sizeof(DEBUGGEE_REGISTER_READ_DESCRIPTION) + sizeof(GUEST_REGS)),
|
||||
&ERegs,
|
||||
sizeof(GUEST_EXTRA_REGISTERS));
|
||||
}
|
||||
|
|
@ -357,7 +357,7 @@ DebuggerReadOrWriteMsr(PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UI
|
|||
//
|
||||
// Means that we should apply it on all cores
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
g_DbgState[i].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
|
||||
g_DbgState[i].MsrState.Value = ReadOrWriteMsrRequest->Value;
|
||||
|
|
@ -411,7 +411,7 @@ DebuggerReadOrWriteMsr(PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UI
|
|||
//
|
||||
// Means that we should apply it on all cores
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
g_DbgState[i].MsrState.Msr = ReadOrWriteMsrRequest->Msr;
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ DebuggerReadOrWriteMsr(PDEBUGGER_READ_AND_WRITE_ON_MSR ReadOrWriteMsrRequest, UI
|
|||
// When we reach here, all processors read their shits
|
||||
// so we have to fill that fucking buffer for user mode
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
UserBuffer[i] = g_DbgState[i].MsrState.Value;
|
||||
}
|
||||
|
|
@ -542,7 +542,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
|
|||
//
|
||||
// Edit the memory
|
||||
//
|
||||
for (size_t i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
{
|
||||
DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
|
||||
SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
|
||||
|
|
@ -570,7 +570,7 @@ DebuggerCommandEditMemory(PDEBUGGER_EDIT_MEMORY EditMemRequest)
|
|||
//
|
||||
// Edit the physical memory
|
||||
//
|
||||
for (size_t i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
{
|
||||
DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
|
||||
SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
|
||||
|
|
@ -659,7 +659,7 @@ DebuggerCommandEditMemoryVmxRoot(PDEBUGGER_EDIT_MEMORY EditMemRequest)
|
|||
//
|
||||
// Edit the memory
|
||||
//
|
||||
for (size_t i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
{
|
||||
DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
|
||||
SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
|
||||
|
|
@ -687,7 +687,7 @@ DebuggerCommandEditMemoryVmxRoot(PDEBUGGER_EDIT_MEMORY EditMemRequest)
|
|||
//
|
||||
// Edit the physical memory
|
||||
//
|
||||
for (size_t i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
for (SIZE_T i = 0; i < EditMemRequest->CountOf64Chunks; i++)
|
||||
{
|
||||
DestinationAddress = (PVOID)((UINT64)EditMemRequest->Address + (i * LengthOfEachChunk));
|
||||
SourceAddress = (PVOID)((UINT64)EditMemRequest + SIZEOF_DEBUGGER_EDIT_MEMORY + (i * sizeof(UINT64)));
|
||||
|
|
@ -805,7 +805,7 @@ PerformSearchAddress(UINT64 * AddressToSaveResults,
|
|||
//
|
||||
SourceAddress = (PVOID)((UINT64)SearchMemRequest + SIZEOF_DEBUGGER_SEARCH_MEMORY);
|
||||
|
||||
for (size_t BaseIterator = (size_t)StartAddress; BaseIterator < ((UINT64)EndAddress); BaseIterator += LengthOfEachChunk)
|
||||
for (SIZE_T BaseIterator = (SIZE_T)StartAddress; BaseIterator < ((UINT64)EndAddress); BaseIterator += LengthOfEachChunk)
|
||||
{
|
||||
//
|
||||
// *** Search the memory ***
|
||||
|
|
@ -844,7 +844,7 @@ PerformSearchAddress(UINT64 * AddressToSaveResults,
|
|||
// Try to check each element (we don't start from the very first element as
|
||||
// it checked before )
|
||||
//
|
||||
for (size_t i = LengthOfEachChunk; i < SearchMemRequest->CountOf64Chunks; i++)
|
||||
for (SIZE_T i = LengthOfEachChunk; i < SearchMemRequest->CountOf64Chunks; i++)
|
||||
{
|
||||
//
|
||||
// I know, we have a double check here ;)
|
||||
|
|
@ -1252,7 +1252,7 @@ DebuggerCommandSearchMemory(PDEBUGGER_SEARCH_MEMORY SearchMemRequest)
|
|||
// that we used aligned page addresses so the results should be checked to
|
||||
// see whether the results are between the user's entered addresses or not
|
||||
//
|
||||
for (size_t i = 0; i < MaximumSearchResults; i++)
|
||||
for (SIZE_T i = 0; i < MaximumSearchResults; i++)
|
||||
{
|
||||
CurrentValue = SearchResultsStorage[i];
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
VOID
|
||||
SerialConnectionTest()
|
||||
{
|
||||
for (size_t i = 0; i < 100; i++)
|
||||
for (SIZE_T i = 0; i < 100; i++)
|
||||
{
|
||||
KdHyperDbgTest((UINT16)i);
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ SerialConnectionSend(CHAR * Buffer, UINT32 Length)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < Length; i++)
|
||||
for (SIZE_T i = 0; i < Length; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer[i], TRUE);
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ SerialConnectionSendTwoBuffers(CHAR * Buffer1, UINT32 Length1, CHAR * Buffer2, U
|
|||
//
|
||||
// Send first buffer
|
||||
//
|
||||
for (size_t i = 0; i < Length1; i++)
|
||||
for (SIZE_T i = 0; i < Length1; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer1[i], TRUE);
|
||||
}
|
||||
|
|
@ -214,7 +214,7 @@ SerialConnectionSendTwoBuffers(CHAR * Buffer1, UINT32 Length1, CHAR * Buffer2, U
|
|||
//
|
||||
// Send second buffer
|
||||
//
|
||||
for (size_t i = 0; i < Length2; i++)
|
||||
for (SIZE_T i = 0; i < Length2; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer2[i], TRUE);
|
||||
}
|
||||
|
|
@ -261,7 +261,7 @@ SerialConnectionSendThreeBuffers(CHAR * Buffer1,
|
|||
//
|
||||
// Send first buffer
|
||||
//
|
||||
for (size_t i = 0; i < Length1; i++)
|
||||
for (SIZE_T i = 0; i < Length1; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer1[i], TRUE);
|
||||
}
|
||||
|
|
@ -269,7 +269,7 @@ SerialConnectionSendThreeBuffers(CHAR * Buffer1,
|
|||
//
|
||||
// Send second buffer
|
||||
//
|
||||
for (size_t i = 0; i < Length2; i++)
|
||||
for (SIZE_T i = 0; i < Length2; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer2[i], TRUE);
|
||||
}
|
||||
|
|
@ -277,7 +277,7 @@ SerialConnectionSendThreeBuffers(CHAR * Buffer1,
|
|||
//
|
||||
// Send third buffer
|
||||
//
|
||||
for (size_t i = 0; i < Length3; i++)
|
||||
for (SIZE_T i = 0; i < Length3; i++)
|
||||
{
|
||||
KdHyperDbgSendByte(Buffer3[i], TRUE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,41 +47,106 @@ DebuggerSetLastError(UINT32 LastError)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize Debugger Structures and Routines
|
||||
* @brief Initialize script engine global variables and per-core stack buffers
|
||||
*
|
||||
* @return BOOLEAN Shows whether the initialization process was successful
|
||||
* or not
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerInitialize()
|
||||
DebuggerInitializeScriptEngine()
|
||||
{
|
||||
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
PROCESSOR_DEBUGGING_STATE * CurrentDebuggerState = NULL;
|
||||
|
||||
//
|
||||
// Also allocate the debugging state
|
||||
// Initialize script engines global variables holder
|
||||
//
|
||||
if (!GlobalDebuggingStateAllocateZeroedMemory())
|
||||
if (!g_ScriptGlobalVariables)
|
||||
{
|
||||
g_ScriptGlobalVariables = PlatformMemAllocateNonPagedPool(MAX_VAR_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
if (!g_ScriptGlobalVariables)
|
||||
{
|
||||
//
|
||||
// Out of resource, initialization of script engine's global variable holders failed
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate buffer for saving events
|
||||
// Zero the global variables memory
|
||||
//
|
||||
if (GlobalEventsAllocateZeroedMemory() == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
RtlZeroMemory(g_ScriptGlobalVariables, MAX_VAR_COUNT * sizeof(UINT64));
|
||||
|
||||
//
|
||||
// Set the core's IDs
|
||||
// Initialize the local and temp variables
|
||||
//
|
||||
for (UINT32 i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
g_DbgState[i].CoreId = i;
|
||||
CurrentDebuggerState = &g_DbgState[i];
|
||||
|
||||
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
|
||||
{
|
||||
CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer = PlatformMemAllocateNonPagedPool(MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
|
||||
{
|
||||
//
|
||||
// Out of resource, initialization of script engine's stack buffer holders failed
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Zero stack buffer memory
|
||||
//
|
||||
RtlZeroMemory(CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize trap flag state and breakpoint related structures
|
||||
*
|
||||
* @return BOOLEAN Shows whether the initialization process was successful
|
||||
* or not
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerInitializeTrapsAndBreakpoints()
|
||||
{
|
||||
//
|
||||
// Zero the TRAP FLAG state memory
|
||||
//
|
||||
RtlZeroMemory(&g_TrapFlagState, sizeof(DEBUGGER_TRAP_FLAG_STATE));
|
||||
|
||||
//
|
||||
// Request pages for breakpoint detail
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(DEBUGGEE_BP_DESCRIPTOR),
|
||||
MAXIMUM_BREAKPOINTS_WITHOUT_CONTINUE,
|
||||
BREAKPOINT_DEFINITION_STRUCTURE);
|
||||
|
||||
//
|
||||
// Initialize list of breakpoints and breakpoint id
|
||||
//
|
||||
g_MaximumBreakpointId = 0;
|
||||
InitializeListHead(&g_BreakpointsListHead);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize VMM operations (events and related operations)
|
||||
*
|
||||
* @return BOOLEAN Shows whether the initialization process was successful
|
||||
* or not
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerInitializeVmmOperations()
|
||||
{
|
||||
//
|
||||
// Initialize lists relating to the debugger events store
|
||||
//
|
||||
|
|
@ -113,85 +178,6 @@ DebuggerInitialize()
|
|||
InitializeListHead(&g_Events->ControlRegisterModifiedEventsHead);
|
||||
InitializeListHead(&g_Events->XsetbvInstructionExecutionEventsHead);
|
||||
|
||||
//
|
||||
// Enabled Debugger Events
|
||||
//
|
||||
g_EnableDebuggerEvents = TRUE;
|
||||
|
||||
//
|
||||
// Set initial state of triggering events for VMCALLs
|
||||
//
|
||||
VmFuncSetTriggerEventForVmcalls(FALSE);
|
||||
|
||||
//
|
||||
// Set initial state of triggering events for VMCALLs
|
||||
//
|
||||
VmFuncSetTriggerEventForCpuids(FALSE);
|
||||
|
||||
//
|
||||
// Initialize script engines global variables holder
|
||||
//
|
||||
if (!g_ScriptGlobalVariables)
|
||||
{
|
||||
g_ScriptGlobalVariables = PlatformMemAllocateNonPagedPool(MAX_VAR_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
if (!g_ScriptGlobalVariables)
|
||||
{
|
||||
//
|
||||
// Out of resource, initialization of script engine's global variable holders failed
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Zero the global variables memory
|
||||
//
|
||||
RtlZeroMemory(g_ScriptGlobalVariables, MAX_VAR_COUNT * sizeof(UINT64));
|
||||
|
||||
//
|
||||
// Zero the TRAP FLAG state memory
|
||||
//
|
||||
RtlZeroMemory(&g_TrapFlagState, sizeof(DEBUGGER_TRAP_FLAG_STATE));
|
||||
|
||||
//
|
||||
// Initialize the local and temp variables
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
CurrentDebuggerState = &g_DbgState[i];
|
||||
|
||||
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
|
||||
{
|
||||
CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer = PlatformMemAllocateNonPagedPool(MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
if (!CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer)
|
||||
{
|
||||
//
|
||||
// Out of resource, initialization of script engine's stack buffer holders failed
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Zero stack buffer memory
|
||||
//
|
||||
RtlZeroMemory(CurrentDebuggerState->ScriptEngineCoreSpecificStackBuffer, MAX_STACK_BUFFER_COUNT * sizeof(UINT64));
|
||||
}
|
||||
|
||||
//
|
||||
// Request pages for breakpoint detail
|
||||
//
|
||||
PoolManagerRequestAllocation(sizeof(DEBUGGEE_BP_DESCRIPTOR),
|
||||
MAXIMUM_BREAKPOINTS_WITHOUT_CONTINUE,
|
||||
BREAKPOINT_DEFINITION_STRUCTURE);
|
||||
|
||||
//
|
||||
// Initialize list of breakpoints and breakpoint id
|
||||
//
|
||||
g_MaximumBreakpointId = 0;
|
||||
InitializeListHead(&g_BreakpointsListHead);
|
||||
|
||||
//
|
||||
// Initialize NMI broadcasting mechanism
|
||||
|
|
@ -199,22 +185,16 @@ DebuggerInitialize()
|
|||
VmFuncVmxBroadcastInitialize();
|
||||
|
||||
//
|
||||
// Initialize attaching mechanism,
|
||||
// we'll use the functionalities of the attaching in reading modules
|
||||
// of user mode applications (other than attaching mechanism itself)
|
||||
// Set initial state of triggering events for VMCALLs
|
||||
//
|
||||
if (!AttachingInitialize())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
VmFuncSetTriggerEventForVmcalls(FALSE);
|
||||
|
||||
//
|
||||
// Initialize the HyperTrace (if supported by the processor)
|
||||
// By default, the debugger module initialize it for a hypervisor environment
|
||||
// Set initial state of triggering events for CPUIDs
|
||||
//
|
||||
LoaderInitHyperTrace(TRUE);
|
||||
VmFuncSetTriggerEventForCpuids(FALSE);
|
||||
|
||||
//
|
||||
//
|
||||
// Pre-allocate pools for possible EPT hooks
|
||||
//
|
||||
ConfigureEptHookReservePreallocatedPoolsForEptHooks(MAXIMUM_NUMBER_OF_INITIAL_PREALLOCATED_EPT_HOOKS);
|
||||
|
|
@ -228,21 +208,96 @@ DebuggerInitialize()
|
|||
//
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Enabled Debugger VMX Events
|
||||
//
|
||||
g_EnableDebuggerVmxEvents = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize Debugger Structures and Routines
|
||||
* @brief Initialize Debugger Structures and Routines
|
||||
*
|
||||
* @return BOOLEAN Shows whether the initialization process was successful
|
||||
* or not
|
||||
*/
|
||||
BOOLEAN
|
||||
DebuggerInitialize()
|
||||
{
|
||||
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
//
|
||||
// Also allocate the debugging state
|
||||
//
|
||||
if (!GlobalDebuggingStateAllocateZeroedMemory())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate buffer for saving events
|
||||
//
|
||||
if (GlobalEventsAllocateZeroedMemory() == FALSE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the core's IDs
|
||||
//
|
||||
for (UINT32 i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
g_DbgState[i].CoreId = i;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize Pool Manager
|
||||
//
|
||||
if (!PoolManagerInitialize())
|
||||
{
|
||||
LogError("Err, could not initialize pool manager");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize script engine global variables and per-core stack buffers
|
||||
//
|
||||
if (!DebuggerInitializeScriptEngine())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize trap flag state and breakpoint related structures
|
||||
//
|
||||
if (!DebuggerInitializeTrapsAndBreakpoints())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize attaching mechanism,
|
||||
// we'll use the functionalities of the attaching in reading modules
|
||||
// of user mode applications (other than attaching mechanism itself)
|
||||
//
|
||||
if (!AttachingInitialize())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize Debugger VMM Operations (Events and other related operations)
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
DebuggerUninitialize()
|
||||
DebuggerUninitializeVmmOperations()
|
||||
{
|
||||
ULONG ProcessorsCount;
|
||||
PROCESSOR_DEBUGGING_STATE * CurrentDebuggerState = NULL;
|
||||
|
||||
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
//
|
||||
// *** Disable, terminate and clear all the events ***
|
||||
//
|
||||
|
|
@ -259,7 +314,7 @@ DebuggerUninitialize()
|
|||
//
|
||||
// Disable triggering events
|
||||
//
|
||||
g_EnableDebuggerEvents = FALSE;
|
||||
g_EnableDebuggerVmxEvents = FALSE;
|
||||
|
||||
//
|
||||
// Clear all events (Check if the kernel debugger is enable
|
||||
|
|
@ -274,11 +329,6 @@ DebuggerUninitialize()
|
|||
DebuggerClearAllEvents(FALSE, FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// Uninitialize the HyperTrace (if it was initialized)
|
||||
//
|
||||
HyperTraceUnInit();
|
||||
|
||||
//
|
||||
// Uninitialize kernel debugger
|
||||
//
|
||||
|
|
@ -293,6 +343,25 @@ DebuggerUninitialize()
|
|||
// Uninitialize NMI broadcasting mechanism
|
||||
//
|
||||
VmFuncVmxBroadcastUninitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize Debugger Structures and Routines
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
DebuggerUninitialize()
|
||||
{
|
||||
ULONG ProcessorsCount;
|
||||
PROCESSOR_DEBUGGING_STATE * CurrentDebuggerState = NULL;
|
||||
|
||||
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
//
|
||||
// Free the Pool manager
|
||||
//
|
||||
PoolManagerUninitialize();
|
||||
|
||||
//
|
||||
// Free g_Events
|
||||
|
|
@ -1002,7 +1071,7 @@ DebuggerAddActionToEvent(PDEBUGGER_EVENT Event,
|
|||
//
|
||||
// Copy the memory of script to our non-paged pool
|
||||
//
|
||||
RtlCopyMemory((void *)Action->ScriptConfiguration.ScriptBuffer, (const void *)InTheCaseOfRunScript->ScriptBuffer, InTheCaseOfRunScript->ScriptLength);
|
||||
RtlCopyMemory((PVOID)Action->ScriptConfiguration.ScriptBuffer, (const PVOID)InTheCaseOfRunScript->ScriptBuffer, InTheCaseOfRunScript->ScriptLength);
|
||||
|
||||
//
|
||||
// Set other fields
|
||||
|
|
@ -1093,7 +1162,7 @@ DebuggerTriggerEvents(VMM_EVENT_TYPE_ENUM EventType,
|
|||
//
|
||||
// Check if triggering debugging actions are allowed or not
|
||||
//
|
||||
if (!g_EnableDebuggerEvents || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer)
|
||||
if (!g_EnableDebuggerVmxEvents || g_InterceptBreakpointsAndEventsForCommandsInRemoteComputer)
|
||||
{
|
||||
//
|
||||
// Debugger is not enabled
|
||||
|
|
@ -1825,7 +1894,7 @@ DebuggerGetEventByTag(UINT64 Tag)
|
|||
//
|
||||
// We have to iterate through all events
|
||||
//
|
||||
for (size_t i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
{
|
||||
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
|
||||
TempList2 = TempList;
|
||||
|
|
@ -1869,7 +1938,7 @@ DebuggerEnableOrDisableAllEvents(BOOLEAN IsEnable)
|
|||
//
|
||||
// We have to iterate through all events
|
||||
//
|
||||
for (size_t i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
{
|
||||
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
|
||||
TempList2 = TempList;
|
||||
|
|
@ -1926,7 +1995,7 @@ DebuggerTerminateAllEvents(BOOLEAN InputFromVmxRoot)
|
|||
//
|
||||
// We have to iterate through all events
|
||||
//
|
||||
for (size_t i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
{
|
||||
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
|
||||
TempList2 = TempList;
|
||||
|
|
@ -1978,7 +2047,7 @@ DebuggerRemoveAllEvents(BOOLEAN PoolManagerAllocatedMemory)
|
|||
//
|
||||
// We have to iterate through all events
|
||||
//
|
||||
for (size_t i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
{
|
||||
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
|
||||
TempList2 = TempList;
|
||||
|
|
@ -2492,7 +2561,7 @@ DebuggerRemoveEventFromEventList(UINT64 Tag)
|
|||
//
|
||||
// We have to iterate through all events
|
||||
//
|
||||
for (size_t i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
for (SIZE_T i = 0; i < sizeof(DEBUGGER_CORE_EVENTS) / sizeof(LIST_ENTRY); i++)
|
||||
{
|
||||
TempList = (PLIST_ENTRY)((UINT64)(g_Events) + (i * sizeof(LIST_ENTRY)));
|
||||
TempList2 = TempList;
|
||||
|
|
@ -2544,12 +2613,12 @@ DebuggerRemoveAllActionsFromEvent(PDEBUGGER_EVENT Event, BOOLEAN PoolManagerAllo
|
|||
//
|
||||
// Remove all actions
|
||||
//
|
||||
TempList = &Event->ActionsListHead;
|
||||
TempList2 = TempList;
|
||||
TempList = Event->ActionsListHead.Flink;
|
||||
TempList2 = &Event->ActionsListHead;
|
||||
|
||||
while (TempList2 != TempList->Flink)
|
||||
while (TempList != TempList2)
|
||||
{
|
||||
TempList = TempList->Flink;
|
||||
PLIST_ENTRY NextList = TempList->Flink;
|
||||
PDEBUGGER_EVENT_ACTION CurrentAction = CONTAINING_RECORD(TempList, DEBUGGER_EVENT_ACTION, ActionsList);
|
||||
|
||||
//
|
||||
|
|
@ -2576,6 +2645,8 @@ DebuggerRemoveAllActionsFromEvent(PDEBUGGER_EVENT Event, BOOLEAN PoolManagerAllo
|
|||
// if it's a custom buffer then the buffer
|
||||
// is appended to the Action
|
||||
//
|
||||
RemoveEntryList(&CurrentAction->ActionsList);
|
||||
|
||||
if (PoolManagerAllocatedMemory)
|
||||
{
|
||||
PoolManagerFreePool((UINT64)CurrentAction);
|
||||
|
|
@ -2584,6 +2655,8 @@ DebuggerRemoveAllActionsFromEvent(PDEBUGGER_EVENT Event, BOOLEAN PoolManagerAllo
|
|||
{
|
||||
PlatformMemFreePool(CurrentAction);
|
||||
}
|
||||
|
||||
TempList = NextList;
|
||||
}
|
||||
//
|
||||
// Remember to free the pool
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ HaltedCoreBroadcastTaskAllCores(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
//
|
||||
if (Synchronize)
|
||||
{
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (DbgState->CoreId != i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ ApplyEventMonitorEvent(PDEBUGGER_EVENT Event,
|
|||
|
||||
// LogInfo("Start address: %llx, end address: %llx", TempStartAddress, TempEndAddress, RemainingSize);
|
||||
|
||||
for (size_t i = 0; i <= PagesBytes; i++)
|
||||
for (SIZE_T i = 0; i <= PagesBytes; i++)
|
||||
{
|
||||
if (RemainingSize >= PAGE_SIZE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file Kd.c
|
||||
* @author Sina Karvandi (sina@hyperdbg.org)
|
||||
* @author Alee Amini (alee@hyperdbg.org)
|
||||
|
|
@ -24,7 +24,7 @@ KdInitializeKernelDebugger()
|
|||
//
|
||||
// Allocate DPC routine
|
||||
//
|
||||
// for (size_t i = 0; i < CoreCount; i++)
|
||||
// for (SIZE_T i = 0; i < CoreCount; i++)
|
||||
// {
|
||||
// g_DbgState[i].KdDpcObject = PlatformMemAllocateNonPagedPool(sizeof(KDPC));
|
||||
//
|
||||
|
|
@ -245,6 +245,24 @@ KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32
|
|||
return Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Query to ignore handling mov 2 debug regs exiting
|
||||
* @param CoreId
|
||||
*
|
||||
* @return BOOLEAN whether it's activated or not
|
||||
*/
|
||||
BOOLEAN
|
||||
KdQueryIgnoreHandlingMov2DebugRegs(UINT32 CoreId)
|
||||
{
|
||||
//
|
||||
// Handle access to debug registers, if we should not ignore it, it is
|
||||
// because on detecting thread scheduling we ignore the hardware debug
|
||||
// registers modifications
|
||||
//
|
||||
return KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(CoreId,
|
||||
DEBUGGER_THREAD_PROCESS_TRACING_INTERCEPT_CLOCK_DEBUG_REGISTER_INTERCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief calculate the checksum of received buffer from debugger
|
||||
*
|
||||
|
|
@ -443,7 +461,7 @@ KdRegularStepOver(UINT64 LastRip, BOOLEAN IsNextInstructionACall, UINT32 CallLen
|
|||
//
|
||||
// Add hardware debug breakpoints on all core on vm-entry
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
g_DbgState[i].HardwareDebugRegisterForStepping = NextAddressForHardwareDebugBp;
|
||||
}
|
||||
|
|
@ -643,7 +661,7 @@ KdContinueDebuggee(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
// Unlock all the cores
|
||||
//
|
||||
ULONG ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
SpinlockUnlock(&g_DbgState[i].Lock);
|
||||
}
|
||||
|
|
@ -930,14 +948,14 @@ KdHandleHaltsWhenNmiReceivedFromVmxRoot(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
* @brief Tries to get the lock and won't return until successfully get the lock
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
* @param LONG Lock variable
|
||||
* @param Lock The lock variable
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
KdCustomDebuggerBreakSpinlockLock(PROCESSOR_DEBUGGING_STATE * DbgState, volatile LONG * Lock)
|
||||
{
|
||||
unsigned wait = 1;
|
||||
UINT32 Wait = 1;
|
||||
|
||||
//
|
||||
// *** Lock handling breaks ***
|
||||
|
|
@ -945,7 +963,7 @@ KdCustomDebuggerBreakSpinlockLock(PROCESSOR_DEBUGGING_STATE * DbgState, volatile
|
|||
|
||||
while (!SpinlockTryLock(Lock))
|
||||
{
|
||||
for (unsigned i = 0; i < wait; ++i)
|
||||
for (UINT32 i = 0; i < Wait; ++i)
|
||||
{
|
||||
CpuPause();
|
||||
}
|
||||
|
|
@ -984,13 +1002,13 @@ KdCustomDebuggerBreakSpinlockLock(PROCESSOR_DEBUGGING_STATE * DbgState, volatile
|
|||
// clamp it to the MaxWait.
|
||||
//
|
||||
|
||||
if (wait * 2 > 65536)
|
||||
if (Wait * 2 > 65536)
|
||||
{
|
||||
wait = 65536;
|
||||
Wait = 65536;
|
||||
}
|
||||
else
|
||||
{
|
||||
wait = wait * 2;
|
||||
Wait = Wait * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1076,19 +1094,57 @@ KdHandleBreakpointAndDebugBreakpointsCallback(UINT32
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Handle #DBs and #BPs for kernel debugger
|
||||
* @details This function can be used in vmx-root
|
||||
* @brief Handle NMI state for MTF
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
*
|
||||
* @param CoreId
|
||||
* @details This function should be called in vmx-root mode
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdCheckAndHandleNmiStateForMtf(PROCESSOR_DEBUGGING_STATE * DbgState)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
|
||||
if (DbgState->NmiState.WaitingToBeLocked)
|
||||
{
|
||||
//
|
||||
// The NMI wait is handled here
|
||||
//
|
||||
Result = TRUE;
|
||||
|
||||
//
|
||||
// Handle break of the core
|
||||
//
|
||||
if (DbgState->NmiState.NmiCalledInVmxRootRelatedToHaltDebuggee)
|
||||
{
|
||||
//
|
||||
// Handle it like an NMI is received from VMX root
|
||||
//
|
||||
KdHandleHaltsWhenNmiReceivedFromVmxRoot(DbgState);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Handle halt of the current core as an NMI
|
||||
//
|
||||
KdHandleNmi(DbgState);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle instrumentation step-in for kernel debugger
|
||||
* @details This function will be called from vmx-root mode
|
||||
*
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
_Use_decl_annotations_
|
||||
VOID
|
||||
KdHandleRegisteredMtfCallback(UINT32 CoreId)
|
||||
KdHandleInstrumentationStepIn(PROCESSOR_DEBUGGING_STATE * DbgState)
|
||||
{
|
||||
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
|
||||
|
||||
//
|
||||
// Check for tracing instructions
|
||||
//
|
||||
|
|
@ -1107,7 +1163,7 @@ KdHandleRegisteredMtfCallback(UINT32 CoreId)
|
|||
//
|
||||
UINT64 CsSel = NULL64_ZERO;
|
||||
DEBUGGER_TRIGGERED_EVENT_DETAILS TargetContext = {0};
|
||||
UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(CoreId);
|
||||
UINT64 LastVmexitRip = VmFuncGetLastVmexitRip(DbgState->CoreId);
|
||||
|
||||
//
|
||||
// Check if the cs selector changed or not, which indicates that the
|
||||
|
|
@ -1144,6 +1200,82 @@ KdHandleRegisteredMtfCallback(UINT32 CoreId)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Monitor Trap Flag (MTF) callback for kernel debugger
|
||||
* @details This function will be called from vmx-root mode
|
||||
*
|
||||
* @param CoreId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdHandleMtfCallback(UINT32 CoreId)
|
||||
{
|
||||
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
|
||||
BOOLEAN IsMtfHandled = FALSE;
|
||||
|
||||
//
|
||||
// *** Check if we need to re-apply a breakpoint or not
|
||||
// We check it separately because the guest might step
|
||||
// instructions on an MTF so we want to check for the step too ***
|
||||
//
|
||||
if (BreakpointCheckAndHandleReApplyingBreakpoint(DbgState))
|
||||
{
|
||||
//
|
||||
// Check for re-enabling external interrupts
|
||||
//
|
||||
VmFuncEnableAndCheckForPreviousExternalInterrupts(DbgState->CoreId);
|
||||
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
IsMtfHandled = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// *** Check for instrumentation step-in ***
|
||||
//
|
||||
if (VmFuncQueryInstrumentationStepInState(DbgState->CoreId))
|
||||
{
|
||||
//
|
||||
// Unset the MTF instrumentation state (might be changed in the caller)
|
||||
//
|
||||
VmFuncUnsetInstrumentationStepInState(DbgState->CoreId);
|
||||
|
||||
//
|
||||
// Handle MTF in the debugger
|
||||
//
|
||||
KdHandleInstrumentationStepIn(DbgState);
|
||||
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
IsMtfHandled = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// check the condition of passing the execution to NMIs
|
||||
//
|
||||
// This one wastes one week of my life!
|
||||
// During the testing we realized the !epthook command in Debugger Mode
|
||||
// is not working. After some tests, it's because if in the middle of a
|
||||
// command in vmx-root and NMI is sent and the debugger waits for another
|
||||
// MTF, we'll ignore that MTF and a new MTF is not set again.
|
||||
// That's why we moved this check here so every command that needs a task
|
||||
// from MTF is doing its tasks and when we reached here, the check for halting
|
||||
// the debuggee in MTF is performed
|
||||
//
|
||||
else if (KdCheckAndHandleNmiStateForMtf(DbgState))
|
||||
{
|
||||
//
|
||||
// MTF is handled
|
||||
//
|
||||
IsMtfHandled = TRUE;
|
||||
}
|
||||
|
||||
return IsMtfHandled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle #DBs and #BPs for kernel debugger
|
||||
* @details This function can be used in vmx-root
|
||||
|
|
@ -1255,49 +1387,6 @@ KdHandleBreakpointAndDebugBreakpoints(PROCESSOR_DEBUGGING_STATE * DbgState
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle NMI vm-exits
|
||||
* @param CoreId
|
||||
*
|
||||
* @details This function should be called in vmx-root mode
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
_Use_decl_annotations_
|
||||
BOOLEAN
|
||||
KdCheckAndHandleNmiCallback(UINT32 CoreId)
|
||||
{
|
||||
BOOLEAN Result = FALSE;
|
||||
PROCESSOR_DEBUGGING_STATE * DbgState = &g_DbgState[CoreId];
|
||||
|
||||
if (DbgState->NmiState.WaitingToBeLocked)
|
||||
{
|
||||
//
|
||||
// The NMI wait is handled here
|
||||
//
|
||||
Result = TRUE;
|
||||
|
||||
//
|
||||
// Handle break of the core
|
||||
//
|
||||
if (DbgState->NmiState.NmiCalledInVmxRootRelatedToHaltDebuggee)
|
||||
{
|
||||
//
|
||||
// Handle it like an NMI is received from VMX root
|
||||
//
|
||||
KdHandleHaltsWhenNmiReceivedFromVmxRoot(DbgState);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Handle halt of the current core as an NMI
|
||||
//
|
||||
KdHandleNmi(DbgState);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle NMI Vm-exits
|
||||
* @param DbgState The state of the debugger on the current core
|
||||
|
|
@ -1365,9 +1454,9 @@ KdGuaranteedStepInstruction(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
DbgState->InstrumentationStepInTrace.CsSel = (UINT16)CsSel;
|
||||
|
||||
//
|
||||
// Set an indicator of a break in the case of an MTF
|
||||
// Set an indicator of instrumentation step-in MTF
|
||||
//
|
||||
VmFuncRegisterMtfBreak(DbgState->CoreId);
|
||||
VmFuncSetInstrumentationStepInState(DbgState->CoreId);
|
||||
|
||||
//
|
||||
// Not unset MTF again
|
||||
|
|
@ -1560,7 +1649,7 @@ KdQueryRflagTrapState()
|
|||
g_TrapFlagState.NumberOfItems,
|
||||
g_TrapFlagState.NumberOfItems);
|
||||
|
||||
for (size_t i = 0; i < MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS; i++)
|
||||
for (SIZE_T i = 0; i < MAXIMUM_NUMBER_OF_THREAD_INFORMATION_FOR_TRAPS; i++)
|
||||
{
|
||||
LogInfo("g_TrapFlagState.ThreadInformation[%d].ProcessId = %x | ThreadId = %x",
|
||||
i,
|
||||
|
|
@ -1584,7 +1673,7 @@ KdCheckAllCoresAreLocked()
|
|||
//
|
||||
// Query core debugging Lock info
|
||||
//
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (!SpinlockCheckLock(&g_DbgState[i].Lock))
|
||||
{
|
||||
|
|
@ -1647,7 +1736,7 @@ KdQuerySystemState()
|
|||
//
|
||||
Log("================================================ Debugging Lock Info ================================================\n");
|
||||
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (SpinlockCheckLock(&g_DbgState[i].Lock))
|
||||
{
|
||||
|
|
@ -1665,7 +1754,7 @@ KdQuerySystemState()
|
|||
//
|
||||
Log("\n================================================ NMI Receiver State =======+=========================================\n");
|
||||
|
||||
for (size_t i = 0; i < ProcessorsCount; i++)
|
||||
for (SIZE_T i = 0; i < ProcessorsCount; i++)
|
||||
{
|
||||
if (g_DbgState[i].NmiState.NmiCalledInVmxRootRelatedToHaltDebuggee)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,9 +68,15 @@ PoolManagerInitialize()
|
|||
InitializeListHead(&g_ListOfAllocatedPoolsHead);
|
||||
|
||||
//
|
||||
// Nothing to deallocate
|
||||
// Nothing to deallocate or allocate at the beginning
|
||||
//
|
||||
g_IsNewRequestForDeAllocation = FALSE;
|
||||
g_IsNewRequestForDeAllocation = FALSE;
|
||||
g_IsNewRequestForAllocationReceived = FALSE;
|
||||
|
||||
//
|
||||
// Memory allocator is initialized
|
||||
//
|
||||
g_PoolManagerInitialized = TRUE;
|
||||
|
||||
//
|
||||
// Initialized successfully
|
||||
|
|
@ -86,8 +92,12 @@ PoolManagerInitialize()
|
|||
VOID
|
||||
PoolManagerUninitialize()
|
||||
{
|
||||
PLIST_ENTRY ListTemp = 0;
|
||||
ListTemp = &g_ListOfAllocatedPoolsHead;
|
||||
PLIST_ENTRY ListTemp = &g_ListOfAllocatedPoolsHead;
|
||||
|
||||
//
|
||||
// Pool manager is not initialized anymore
|
||||
//
|
||||
g_PoolManagerInitialized = FALSE;
|
||||
|
||||
SpinlockLock(&LockForReadingPool);
|
||||
|
||||
|
|
@ -252,7 +262,7 @@ PoolManagerRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPo
|
|||
BOOLEAN
|
||||
PoolManagerAllocateAndAddToPoolTable(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention)
|
||||
{
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
for (SIZE_T i = 0; i < Count; i++)
|
||||
{
|
||||
POOL_TABLE * SinglePool = NULL;
|
||||
|
||||
|
|
@ -305,12 +315,14 @@ PoolManagerCheckAndPerformAllocationAndDeallocation()
|
|||
PLIST_ENTRY ListTemp = 0;
|
||||
|
||||
//
|
||||
// let's make sure we're on vmx non-root and also we have new allocation
|
||||
// Make sure we're on vmx non-root and also we have new allocation
|
||||
// and also pool manager is initialized, otherwise we shouldn't allocate or deallocate
|
||||
//
|
||||
if (VmxGetCurrentExecutionMode() == TRUE)
|
||||
if (!g_PoolManagerInitialized || VmFuncVmxGetCurrentExecutionMode() == TRUE)
|
||||
{
|
||||
//
|
||||
// allocation's can't be done from vmx root
|
||||
// or pool manager is not initialized yet
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -320,6 +332,8 @@ PoolManagerCheckAndPerformAllocationAndDeallocation()
|
|||
//
|
||||
PAGED_CODE();
|
||||
|
||||
SpinlockLock(&LockForReadingPool);
|
||||
|
||||
//
|
||||
// Check for new allocation
|
||||
//
|
||||
|
|
@ -352,8 +366,6 @@ PoolManagerCheckAndPerformAllocationAndDeallocation()
|
|||
{
|
||||
ListTemp = &g_ListOfAllocatedPoolsHead;
|
||||
|
||||
SpinlockLock(&LockForReadingPool);
|
||||
|
||||
while (&g_ListOfAllocatedPoolsHead != ListTemp->Flink)
|
||||
{
|
||||
ListTemp = ListTemp->Flink;
|
||||
|
|
@ -390,8 +402,6 @@ PoolManagerCheckAndPerformAllocationAndDeallocation()
|
|||
PlatformMemFreePool(PoolTable);
|
||||
}
|
||||
}
|
||||
|
||||
SpinlockUnlock(&LockForReadingPool);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -400,6 +410,8 @@ PoolManagerCheckAndPerformAllocationAndDeallocation()
|
|||
g_IsNewRequestForDeAllocation = FALSE;
|
||||
g_IsNewRequestForAllocationReceived = FALSE;
|
||||
|
||||
SpinlockUnlock(&LockForReadingPool);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
@ -26,9 +26,9 @@ TracingPerformInstrumentationStepIn(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
DbgState->TracingMode = TRUE;
|
||||
|
||||
//
|
||||
// Register break on MTF
|
||||
// Set instrumentation step-in state
|
||||
//
|
||||
VmFuncRegisterMtfBreak(DbgState->CoreId);
|
||||
VmFuncSetInstrumentationStepInState(DbgState->CoreId);
|
||||
|
||||
VmFuncEnableMtfAndChangeExternalInterruptState(DbgState->CoreId);
|
||||
}
|
||||
|
|
@ -73,9 +73,9 @@ TracingRestoreSystemState(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
DbgState->TracingMode = FALSE;
|
||||
|
||||
//
|
||||
// Unregister break on MTF
|
||||
// Uset the instrumentation step-in state
|
||||
//
|
||||
VmFuncUnRegisterMtfBreak(DbgState->CoreId);
|
||||
VmFuncUnsetInstrumentationStepInState(DbgState->CoreId);
|
||||
|
||||
//
|
||||
// Check for reenabling external interrupts
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ AttachingAdjustNopSledBuffer(UINT64 ReservedBuffAddress, UINT32 ProcessId)
|
|||
//
|
||||
// Fill the memory with nops
|
||||
//
|
||||
memset((void *)ReservedBuffAddress, 0x90, PAGE_SIZE);
|
||||
memset((PVOID)ReservedBuffAddress, 0x90, PAGE_SIZE);
|
||||
|
||||
//
|
||||
// Set jmps to form a loop (little endians)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ ThreadHolderIsAnyPausedThreadInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS Proce
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId != NULL_ZERO && ThreadHolder->Threads[i].IsPaused)
|
||||
{
|
||||
|
|
@ -118,7 +118,7 @@ ThreadHolderUnpauseAllThreadsInProcess(PUSERMODE_DEBUGGING_PROCESS_DETAILS Proce
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId != NULL_ZERO && ThreadHolder->Threads[i].IsPaused)
|
||||
{
|
||||
|
|
@ -165,7 +165,7 @@ ThreadHolderGetProcessThreadDetailsByProcessIdAndThreadId(UINT32 ProcessId, UINT
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId == ThreadId)
|
||||
{
|
||||
|
|
@ -213,7 +213,7 @@ ThreadHolderGetProcessFirstThreadDetailsByProcessId(UINT32 ProcessId)
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId != NULL_ZERO)
|
||||
{
|
||||
|
|
@ -262,7 +262,7 @@ ThreadHolderGetProcessDebuggingDetailsByThreadId(UINT32 ThreadId)
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList2, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId == ThreadId)
|
||||
{
|
||||
|
|
@ -305,7 +305,7 @@ ThreadHolderFindOrCreateThreadDebuggingDetail(UINT32 ThreadId, PUSERMODE_DEBUGGI
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId == ThreadId)
|
||||
{
|
||||
|
|
@ -337,7 +337,7 @@ ThreadHolderFindOrCreateThreadDebuggingDetail(UINT32 ThreadId, PUSERMODE_DEBUGGI
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId == NULL_ZERO)
|
||||
{
|
||||
|
|
@ -415,7 +415,7 @@ ThreadHolderApplyActionToPausedThreads(PUSERMODE_DEBUGGING_PROCESS_DETAILS Proce
|
|||
//
|
||||
// Apply the command
|
||||
//
|
||||
for (size_t i = 0; i < MAX_USER_ACTIONS_FOR_THREADS; i++)
|
||||
for (SIZE_T i = 0; i < MAX_USER_ACTIONS_FOR_THREADS; i++)
|
||||
{
|
||||
if (ThreadDebuggingDetails->UdAction[i].ActionType == DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE)
|
||||
{
|
||||
|
|
@ -454,12 +454,12 @@ ThreadHolderApplyActionToPausedThreads(PUSERMODE_DEBUGGING_PROCESS_DETAILS Proce
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].ThreadId != NULL_ZERO &&
|
||||
ThreadHolder->Threads[i].IsPaused)
|
||||
{
|
||||
for (size_t j = 0; j < MAX_USER_ACTIONS_FOR_THREADS; j++)
|
||||
for (SIZE_T j = 0; j < MAX_USER_ACTIONS_FOR_THREADS; j++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].UdAction[j].ActionType == DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE)
|
||||
{
|
||||
|
|
@ -554,7 +554,7 @@ ThreadHolderQueryCountOfActiveDebuggingThreadsAndProcesses()
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList2, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].IsPaused)
|
||||
{
|
||||
|
|
@ -631,7 +631,7 @@ ThreadHolderQueryDetailsOfActiveDebuggingThreadsAndProcesses(
|
|||
PUSERMODE_DEBUGGING_THREAD_HOLDER ThreadHolder =
|
||||
CONTAINING_RECORD(TempList2, USERMODE_DEBUGGING_THREAD_HOLDER, ThreadHolderList);
|
||||
|
||||
for (size_t i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
for (SIZE_T i = 0; i < MAX_THREADS_IN_A_PROCESS_HOLDER; i++)
|
||||
{
|
||||
if (ThreadHolder->Threads[i].IsPaused)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -582,7 +582,7 @@ UdCheckForCommand(PROCESSOR_DEBUGGING_STATE * DbgState,
|
|||
// Here, we're sure that this thread is looking for command, let
|
||||
// see if we find anything
|
||||
//
|
||||
for (size_t i = 0; i < MAX_USER_ACTIONS_FOR_THREADS; i++)
|
||||
for (SIZE_T i = 0; i < MAX_USER_ACTIONS_FOR_THREADS; i++)
|
||||
{
|
||||
if (ThreadDebuggingDetails->UdAction[i].ActionType != DEBUGGER_UD_COMMAND_ACTION_TYPE_NONE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ UserAccessPrintLoadedModulesX86(PEPROCESS Proc,
|
|||
}
|
||||
|
||||
TempSize = TempSize * 2;
|
||||
memcpy(&ModulesList[CurrentSavedModules].FilePath, (const void *)Entry->FullDllName.Buffer, TempSize);
|
||||
memcpy(&ModulesList[CurrentSavedModules].FilePath, (const PVOID)Entry->FullDllName.Buffer, TempSize);
|
||||
|
||||
CurrentSavedModules++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@ DrvUnload(PDRIVER_OBJECT DriverObject)
|
|||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
|
||||
//
|
||||
// Unloading VMM and Debugger
|
||||
// Unloading Log Tracer
|
||||
//
|
||||
LoaderUninitializeLogTracer();
|
||||
LoaderUninitLogTracer();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,10 +155,15 @@ DrvCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|||
}
|
||||
|
||||
//
|
||||
// Initialize the vmm and the debugger
|
||||
// Initialize HyperLog and Log Tracer
|
||||
//
|
||||
if (LoaderInitVmmAndDebugger())
|
||||
if (LoaderInitHyperLog())
|
||||
{
|
||||
//
|
||||
// Set the variable so next CreateFile won't call log initializer again
|
||||
//
|
||||
g_HandleInUse = TRUE;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,7 +18,7 @@
|
|||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitHyperTrace(BOOLEAN RunningOnHypervisorEnvironment)
|
||||
LoaderInitHyperTrace(PDEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTracePacket, BOOLEAN RunningOnHypervisorEnvironment)
|
||||
{
|
||||
HYPERTRACE_CALLBACKS HyperTraceCallbacks = {0};
|
||||
|
||||
|
|
@ -81,6 +81,17 @@ LoaderInitHyperTrace(BOOLEAN RunningOnHypervisorEnvironment)
|
|||
if (HyperTraceInitCallback(&HyperTraceCallbacks, RunningOnHypervisorEnvironment))
|
||||
{
|
||||
LogDebugInfo("HyperDbg's hypertrace loaded successfully");
|
||||
|
||||
//
|
||||
// Mark hypertrace as initialized
|
||||
//
|
||||
g_HyperTraceInitialized = TRUE;
|
||||
|
||||
//
|
||||
// Set the kernel status to success
|
||||
//
|
||||
InitHyperTracePacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -89,25 +100,25 @@ LoaderInitHyperTrace(BOOLEAN RunningOnHypervisorEnvironment)
|
|||
// We won't fail the loading just because of hypertrace, so we just log the error and continue without loading hypertrace
|
||||
//
|
||||
LogDebugInfo("Err, HyperDbg's hypertrace was not loaded");
|
||||
|
||||
//
|
||||
// Set the kernel status to indicate failure
|
||||
//
|
||||
InitHyperTracePacket->KernelStatus = DEBUGGER_ERROR_HYPERTRACE_NOT_INITIALIZED;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the VMM and Debugger
|
||||
* @brief Initialize the hyper log module
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitVmmAndDebugger()
|
||||
LoaderInitHyperLog()
|
||||
{
|
||||
MESSAGE_TRACING_CALLBACKS MsgTracingCallbacks = {0};
|
||||
VMM_CALLBACKS VmmCallbacks = {0};
|
||||
|
||||
//
|
||||
// Allow to server IOCTL
|
||||
//
|
||||
g_AllowIoctlFromUsermode = TRUE;
|
||||
|
||||
//
|
||||
// *** Fill the callbacks for the message tracer ***
|
||||
|
|
@ -116,6 +127,58 @@ LoaderInitVmmAndDebugger()
|
|||
MsgTracingCallbacks.CheckImmediateMessageSending = KdCheckImmediateMessagingMechanism;
|
||||
MsgTracingCallbacks.SendImmediateMessage = KdLoggingResponsePacketToDebugger;
|
||||
|
||||
//
|
||||
// Initialize message tracer (if not already initialized)
|
||||
//
|
||||
if (g_HyperLogInitialized == FALSE && LogInitialize(&MsgTracingCallbacks))
|
||||
{
|
||||
g_HyperLogInitialized = TRUE;
|
||||
|
||||
LogDebugInfo("HyperDbg's hyperlog loaded successfully");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// We use DbgPrint here because if the hyperlog is not loaded we can't use it to log the error
|
||||
// so we just log the error with DbgPrint and continue without loading hyperlog
|
||||
//
|
||||
DbgPrint("Err, HyperDbg's hyperlog was not loaded or already loaded");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the VMM
|
||||
*
|
||||
* @param InitVmmPacket The packet to fill the result of the initialization
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitVmm(PDEBUGGER_INIT_VMM_PACKET InitVmmPacket)
|
||||
{
|
||||
VMM_CALLBACKS VmmCallbacks = {0};
|
||||
|
||||
//
|
||||
// Check if KD is not already initialized, if so we cannot initialize VMM
|
||||
//
|
||||
if (!g_KdInitialized)
|
||||
{
|
||||
InitVmmPacket->KernelStatus = DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_DEBUGGER_IS_NOT_LOADED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if HyperTrace is already initialized, if so we cannot initialize VMM
|
||||
//
|
||||
if (g_HyperTraceInitialized)
|
||||
{
|
||||
InitVmmPacket->KernelStatus = DEBUGGER_ERROR_VMM_CANNOT_BE_INITIALIZED_IF_HYPERTRACE_IS_LOADED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// *** Fill the callbacks for using hyperlog in VMM ***
|
||||
//
|
||||
|
|
@ -127,7 +190,7 @@ LoaderInitVmmAndDebugger()
|
|||
//
|
||||
// Fill the HyperTrace callback(s)
|
||||
//
|
||||
VmmCallbacks.HyperTraceLbrIsSupported = HyperTraceLbrIsSupported;
|
||||
VmmCallbacks.HyperTraceCallbackLbrIsSupported = HyperTraceLbrIsSupported;
|
||||
|
||||
//
|
||||
// Fill the VMM callbacks
|
||||
|
|
@ -135,22 +198,27 @@ LoaderInitVmmAndDebugger()
|
|||
VmmCallbacks.VmmCallbackTriggerEvents = DebuggerTriggerEvents;
|
||||
VmmCallbacks.VmmCallbackSetLastError = DebuggerSetLastError;
|
||||
VmmCallbacks.VmmCallbackVmcallHandler = DebuggerVmcallHandler;
|
||||
VmmCallbacks.VmmCallbackRegisteredMtfHandler = KdHandleRegisteredMtfCallback;
|
||||
VmmCallbacks.VmmCallbackNmiBroadcastRequestHandler = KdHandleNmiBroadcastDebugBreaks;
|
||||
VmmCallbacks.VmmCallbackQueryTerminateProtectedResource = TerminateQueryDebuggerResource;
|
||||
VmmCallbacks.VmmCallbackRestoreEptState = UserAccessCheckForLoadedModuleDetails;
|
||||
VmmCallbacks.VmmCallbackCheckUnhandledEptViolations = AttachingCheckUnhandledEptViolation;
|
||||
VmmCallbacks.VmmCallbackHandleMtfCallback = KdHandleMtfCallback;
|
||||
|
||||
//
|
||||
// Fill the debugging callbacks
|
||||
//
|
||||
VmmCallbacks.DebuggingCallbackHandleBreakpointException = BreakpointHandleBreakpoints;
|
||||
VmmCallbacks.DebuggingCallbackHandleDebugBreakpointException = BreakpointCheckAndHandleDebugBreakpoint;
|
||||
VmmCallbacks.BreakpointCheckAndHandleReApplyingBreakpoint = BreakpointCheckAndHandleReApplyingBreakpoint;
|
||||
VmmCallbacks.DebuggerCheckProcessOrThreadChange = DebuggerCheckProcessOrThreadChange;
|
||||
VmmCallbacks.DebuggingCallbackCheckThreadInterception = AttachingCheckThreadInterceptionWithUserDebugger;
|
||||
VmmCallbacks.KdCheckAndHandleNmiCallback = KdCheckAndHandleNmiCallback;
|
||||
VmmCallbacks.KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId = KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId;
|
||||
VmmCallbacks.DebuggingCallbackHandleBreakpointException = BreakpointHandleBreakpoints;
|
||||
VmmCallbacks.DebuggingCallbackHandleDebugBreakpointException = BreakpointCheckAndHandleDebugBreakpoint;
|
||||
VmmCallbacks.DebuggingCallbackCheckThreadInterception = AttachingCheckThreadInterceptionWithUserDebugger;
|
||||
VmmCallbacks.DebuggingCallbackTriggerOnClockAndIpiEvents = DebuggerCheckProcessOrThreadChange;
|
||||
VmmCallbacks.DebuggingCallbackIgnoreHandlingMov2DebugRegs = KdQueryIgnoreHandlingMov2DebugRegs;
|
||||
|
||||
//
|
||||
// Fill the pool manager callbacks
|
||||
//
|
||||
VmmCallbacks.PoolManagerCallbackRequestAllocation = PoolManagerRequestAllocation;
|
||||
VmmCallbacks.PoolManagerCallbackRequestPool = PoolManagerRequestPool;
|
||||
VmmCallbacks.PoolManagerCallbackFreePool = PoolManagerFreePool;
|
||||
|
||||
//
|
||||
// Fill the interception callbacks
|
||||
|
|
@ -158,70 +226,226 @@ LoaderInitVmmAndDebugger()
|
|||
VmmCallbacks.InterceptionCallbackTriggerCr3ProcessChange = ProcessTriggerCr3ProcessChange;
|
||||
|
||||
//
|
||||
// Initialize message tracer
|
||||
// Initialize VMX
|
||||
//
|
||||
if (LogInitialize(&MsgTracingCallbacks))
|
||||
if (VmFuncInitVmm(&VmmCallbacks))
|
||||
{
|
||||
LogDebugInfo("HyperDbg's hypervisor loaded successfully");
|
||||
|
||||
//
|
||||
// Initialize VMX
|
||||
// Initialize VMM opeartions (event related state from the debugger)
|
||||
//
|
||||
if (VmFuncInitVmm(&VmmCallbacks))
|
||||
if (!DebuggerInitializeVmmOperations())
|
||||
{
|
||||
LogDebugInfo("HyperDbg's hypervisor loaded successfully");
|
||||
|
||||
//
|
||||
// Initialize the debugger
|
||||
//
|
||||
if (DebuggerInitialize())
|
||||
{
|
||||
LogDebugInfo("HyperDbg's debugger loaded successfully");
|
||||
|
||||
//
|
||||
// Set the variable so no one else can get a handle anymore
|
||||
//
|
||||
g_HandleInUse = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Err, HyperDbg's debugger was not loaded");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Err, HyperDbg's hypervisor was not loaded");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// VMM module initialized
|
||||
//
|
||||
g_VmmInitialized = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Err, HyperDbg's message tracing module was not loaded");
|
||||
LogError("Err, HyperDbg's hypervisor was not loaded");
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the debugger
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitKd()
|
||||
{
|
||||
//
|
||||
// If the debugger is already initialized, we don't need to initialize it again
|
||||
// and simply return true
|
||||
//
|
||||
if (g_KdInitialized)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Not loaded
|
||||
// The debugger is not initialized, so we try to initialize it
|
||||
//
|
||||
g_AllowIoctlFromUsermode = FALSE;
|
||||
if (DebuggerInitialize())
|
||||
{
|
||||
LogDebugInfo("HyperDbg's debugger loaded successfully");
|
||||
|
||||
//
|
||||
// KD module initialized
|
||||
//
|
||||
g_KdInitialized = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LogError("Err, HyperDbg's debugger was not loaded");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the debugger and the vmm
|
||||
*
|
||||
* @param InitVmmPacket The packet to fill the result of the initialization
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
LoaderInitDebuggerAndVmm(PDEBUGGER_INIT_VMM_PACKET InitVmmPacket)
|
||||
{
|
||||
//
|
||||
// First we need to initialize the debugger
|
||||
// because the VMM relies on the debugger for some of its functionalities,
|
||||
// so if we cannot initialize the debugger we cannot initialize the VMM
|
||||
//
|
||||
if (!LoaderInitKd())
|
||||
{
|
||||
//
|
||||
// Unable to initialize the debugger, so we cannot initialize the VMM, and we return false
|
||||
//
|
||||
InitVmmPacket->KernelStatus = DEBUGGER_ERROR_CANNOT_INITIALIZE_DEBUGGER;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Now we can initialize the VMM
|
||||
//
|
||||
if (!LoaderInitVmm(InitVmmPacket))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the kernel status to success
|
||||
//
|
||||
InitVmmPacket->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the hyper trace module
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitHyperTrace()
|
||||
{
|
||||
//
|
||||
// Mark hypertrace as uninitialized before uninitializing it to avoid any potential reentrancy issues during the uninitialization process
|
||||
//
|
||||
g_HyperTraceInitialized = FALSE;
|
||||
|
||||
//
|
||||
// Uninitialize the hypertrace
|
||||
//
|
||||
HyperTraceUninit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the VMM
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitVmm()
|
||||
{
|
||||
//
|
||||
// Mark VMM as uninitialized before uninitializing it to avoid any potential reentrancy issues during the uninitialization process
|
||||
//
|
||||
g_VmmInitialized = FALSE;
|
||||
|
||||
//
|
||||
// Uninitialize the HyperTrace (if it was initialized)
|
||||
//
|
||||
// If the trace module is currently loaded, it must be unloaded before the VMM module can be unloaded
|
||||
// HyperTrace can operate both with and without the VMM module. When loaded after the VMM module, HyperTrace can make
|
||||
// use of hypervisor-specific features. Otherwise, it will operate normally, but those features will not be available
|
||||
// The trace module will be unloaded automatically and may be reloaded later if needed
|
||||
//
|
||||
// Note: The user mode should automatically request to unload the 'trace' module if it is already loaded
|
||||
// however, here we also unload it just in case if this function is directly called or the user mode
|
||||
// code did not unload it
|
||||
//
|
||||
LoaderUninitHyperTrace();
|
||||
|
||||
//
|
||||
// First remove all VMM related state from the debugger
|
||||
//
|
||||
DebuggerUninitializeVmmOperations();
|
||||
|
||||
//
|
||||
// Terminate VMM and its sub-mechanisms
|
||||
//
|
||||
VmFuncUninitVmm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the debugger
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitKd()
|
||||
{
|
||||
//
|
||||
// Mark KD as uninitialized before uninitializing it to avoid any potential reentrancy issues during the uninitialization process
|
||||
//
|
||||
g_KdInitialized = FALSE;
|
||||
|
||||
//
|
||||
// Uninitialize the debugger and its sub-mechanisms
|
||||
//
|
||||
DebuggerUninitialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the VMM and the debugger
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitVmmAndDebugger()
|
||||
{
|
||||
//
|
||||
// Uninitialize the VMM first because it relies on the debugger for some
|
||||
//
|
||||
LoaderUninitVmm();
|
||||
|
||||
//
|
||||
// Uninitialize the debugger
|
||||
//
|
||||
LoaderUninitKd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the log tracer
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
LoaderUninitializeLogTracer()
|
||||
LoaderUninitLogTracer()
|
||||
{
|
||||
LogDebugInfo("Unloading HyperDbg's debugger...\n");
|
||||
|
||||
#if !UseDbgPrintInsteadOfUsermodeMessageTracking
|
||||
|
||||
LogDebugInfo("Unloading hyperlog...\n");
|
||||
|
||||
//
|
||||
// Uinitialize log buffer
|
||||
// Uinitialize log buffer if it was initialized
|
||||
//
|
||||
LogDebugInfo("Uninitializing logs\n");
|
||||
LogUnInitialize();
|
||||
if (g_HyperLogInitialized)
|
||||
{
|
||||
g_HyperLogInitialized = FALSE;
|
||||
LogUnInitialize();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,14 @@
|
|||
/**
|
||||
* @brief Tests with test tags wrapper
|
||||
*
|
||||
* @param Param1
|
||||
* @param Param2
|
||||
* @param Param3
|
||||
* @param Param4
|
||||
* @return UINT64
|
||||
*/
|
||||
extern unsigned long long
|
||||
AsmTestWrapperWithTestTags(unsigned long long Param1, unsigned long long Param2, unsigned long long Param3, unsigned long long Param4);
|
||||
extern UINT64
|
||||
AsmTestWrapperWithTestTags(UINT64 Param1, UINT64 Param2, UINT64 Param3, UINT64 Param4);
|
||||
|
||||
//
|
||||
// ==================== Kernel Test Functions ====================
|
||||
|
|
@ -35,10 +40,10 @@ AsmTestWrapperWithTestTags(unsigned long long Param1, unsigned long long Param2,
|
|||
* @param Param2
|
||||
* @param Param3
|
||||
* @param Param4
|
||||
* @return unsigned long long
|
||||
* @return VOID
|
||||
*/
|
||||
extern void
|
||||
AsmDebuggerCustomCodeHandler(unsigned long long Param1, unsigned long long Param2, unsigned long long Param3, unsigned long long Param4);
|
||||
extern VOID
|
||||
AsmDebuggerCustomCodeHandler(UINT64 Param1, UINT64 Param2, UINT64 Param3, UINT64 Param4);
|
||||
|
||||
/**
|
||||
* @brief default condition code handler
|
||||
|
|
@ -46,14 +51,14 @@ AsmDebuggerCustomCodeHandler(unsigned long long Param1, unsigned long long Param
|
|||
* @param Param1
|
||||
* @param Param2
|
||||
* @param Param3
|
||||
* @return unsigned long long
|
||||
* @return UINT64
|
||||
*/
|
||||
extern unsigned long long
|
||||
AsmDebuggerConditionCodeHandler(unsigned long long Param1, unsigned long long Param2, unsigned long long Param3);
|
||||
extern UINT64
|
||||
AsmDebuggerConditionCodeHandler(UINT64 Param1, UINT64 Param2, UINT64 Param3);
|
||||
|
||||
/**
|
||||
* @brief Spin on thread
|
||||
*
|
||||
*/
|
||||
extern void
|
||||
extern VOID
|
||||
AsmDebuggerSpinOnThread();
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ BreakpointCheckAndHandleDebuggerDefinedBreakpoints(PROCESSOR_DEBUGGING_STATE * D
|
|||
BOOLEAN ChangeMtfState);
|
||||
|
||||
BOOLEAN
|
||||
BreakpointCheckAndHandleReApplyingBreakpoint(UINT32 CoreId);
|
||||
BreakpointCheckAndHandleReApplyingBreakpoint(PROCESSOR_DEBUGGING_STATE * DbgState);
|
||||
|
||||
BOOLEAN
|
||||
BreakpointCheckAndHandleDebugBreakpoint(UINT32 CoreId);
|
||||
|
|
|
|||
|
|
@ -188,9 +188,21 @@ DebuggerGetLastError();
|
|||
VOID
|
||||
DebuggerSetLastError(UINT32 LastError);
|
||||
|
||||
BOOLEAN
|
||||
DebuggerInitializeScriptEngine();
|
||||
|
||||
BOOLEAN
|
||||
DebuggerInitializeTrapsAndBreakpoints();
|
||||
|
||||
BOOLEAN
|
||||
DebuggerInitializeVmmOperations();
|
||||
|
||||
BOOLEAN
|
||||
DebuggerInitialize();
|
||||
|
||||
VOID
|
||||
DebuggerUninitializeVmmOperations();
|
||||
|
||||
VOID
|
||||
DebuggerUninitialize();
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ typedef struct _DEBUGGER_PROCESS_THREAD_INFORMATION
|
|||
{
|
||||
union
|
||||
{
|
||||
UINT64 asUInt;
|
||||
UINT64 AsUInt;
|
||||
|
||||
struct
|
||||
{
|
||||
|
|
|
|||
|
|
@ -167,8 +167,6 @@ KdHandleDebugEventsWhenKernelDebuggerIsAttached(PROCESSOR_DEBUGGING_STATE * DbgS
|
|||
VOID
|
||||
KdManageSystemHaltOnVmxRoot(PROCESSOR_DEBUGGING_STATE * DbgState,
|
||||
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails);
|
||||
BOOLEAN
|
||||
KdCheckAndHandleNmiCallback(_In_ UINT32 CoreId);
|
||||
|
||||
VOID
|
||||
KdHandleNmi(_Inout_ PROCESSOR_DEBUGGING_STATE * DbgState);
|
||||
|
|
@ -197,12 +195,12 @@ KdHandleBreakpointAndDebugBreakpoints(_Inout_ PROCESSOR_DEBUGGING_STATE * DbgSta
|
|||
_In_ DEBUGGEE_PAUSING_REASON Reason,
|
||||
PDEBUGGER_TRIGGERED_EVENT_DETAILS EventDetails);
|
||||
|
||||
VOID
|
||||
KdHandleRegisteredMtfCallback(_In_ UINT32 CoreId);
|
||||
|
||||
VOID
|
||||
KdHandleHaltsWhenNmiReceivedFromVmxRoot(_Inout_ PROCESSOR_DEBUGGING_STATE * DbgState);
|
||||
|
||||
BOOLEAN
|
||||
KdHandleMtfCallback(UINT32 CoreId);
|
||||
|
||||
BOOLEAN
|
||||
KdCheckImmediateMessagingMechanism(UINT32 OperationCode);
|
||||
|
||||
|
|
@ -235,3 +233,6 @@ KdCheckTheHaltedCore(PROCESSOR_DEBUGGING_STATE * DbgState);
|
|||
BOOLEAN
|
||||
KdQueryDebuggerQueryThreadOrProcessTracingDetailsByCoreId(UINT32 CoreId,
|
||||
DEBUGGER_THREAD_PROCESS_TRACING TracingType);
|
||||
|
||||
BOOLEAN
|
||||
KdQueryIgnoreHandlingMov2DebugRegs(UINT32 CoreId);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,12 @@ volatile LONG LockForRequestAllocation;
|
|||
*/
|
||||
volatile LONG LockForReadingPool;
|
||||
|
||||
/**
|
||||
* @brief Pool manager memory allocator initialized
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_PoolManagerInitialized;
|
||||
|
||||
/**
|
||||
* @brief We set it when there is a new allocation
|
||||
*
|
||||
|
|
@ -114,18 +120,23 @@ static VOID PlmgrFreeRequestNewAllocation(VOID);
|
|||
// Public Interfaces
|
||||
//
|
||||
|
||||
/**
|
||||
* @brief Initializes the Pool Manager and pre-allocate some pools
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
PoolManagerInitialize();
|
||||
|
||||
/**
|
||||
* @brief De-allocate all the allocated pools
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
PoolManagerUninitialize();
|
||||
|
||||
VOID
|
||||
PoolManagerShowPreAllocatedPools();
|
||||
|
||||
BOOLEAN
|
||||
PoolManagerCheckAndPerformAllocationAndDeallocation();
|
||||
|
||||
BOOLEAN
|
||||
PoolManagerRequestAllocation(SIZE_T Size, UINT32 Count, POOL_ALLOCATION_INTENTION Intention);
|
||||
|
||||
UINT64
|
||||
PoolManagerRequestPool(POOL_ALLOCATION_INTENTION Intention, BOOLEAN RequestNewPool, UINT32 Size);
|
||||
|
||||
BOOLEAN
|
||||
PoolManagerFreePool(UINT64 AddressToFree);
|
||||
|
|
@ -45,7 +45,7 @@ typedef struct _RTL_USER_PROCESS_PARAMETERS
|
|||
* @brief Random windows type
|
||||
*
|
||||
*/
|
||||
typedef void(__stdcall * PPS_POST_PROCESS_INIT_ROUTINE)(void); // not exported
|
||||
typedef VOID(__stdcall * PPS_POST_PROCESS_INIT_ROUTINE)(VOID); // not exported
|
||||
|
||||
/**
|
||||
* @brief PEB 64-bit
|
||||
|
|
|
|||
|
|
@ -45,3 +45,15 @@ DrvUnsupported(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
|||
|
||||
NTSTATUS
|
||||
DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
|
||||
NTSTATUS
|
||||
DrvDispatchBasicIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation);
|
||||
|
||||
NTSTATUS
|
||||
DrvDispatchKdIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation);
|
||||
|
||||
NTSTATUS
|
||||
DrvDispatchVmmIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation);
|
||||
|
||||
NTSTATUS
|
||||
DrvDispatchHyperTraceIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotChangeInformation);
|
||||
|
|
|
|||
|
|
@ -17,10 +17,19 @@
|
|||
//////////////////////////////////////////////////
|
||||
|
||||
BOOLEAN
|
||||
LoaderInitVmmAndDebugger();
|
||||
LoaderInitHyperLog();
|
||||
|
||||
BOOLEAN
|
||||
LoaderInitHyperTrace(BOOLEAN RunningOnHypervisorEnvironment);
|
||||
LoaderInitHyperTrace(PDEBUGGER_INIT_HYPERTRACE_PACKET InitHyperTracePacket, BOOLEAN RunningOnHypervisorEnvironment);
|
||||
|
||||
BOOLEAN
|
||||
LoaderInitDebuggerAndVmm(PDEBUGGER_INIT_VMM_PACKET InitVmmPacket);
|
||||
|
||||
VOID
|
||||
LoaderUninitializeLogTracer();
|
||||
LoaderUninitVmmAndDebugger();
|
||||
|
||||
VOID
|
||||
LoaderUninitHyperTrace();
|
||||
|
||||
VOID
|
||||
LoaderUninitLogTracer();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,30 @@
|
|||
*/
|
||||
PROCESSOR_DEBUGGING_STATE * g_DbgState;
|
||||
|
||||
/**
|
||||
* @brief Shows whether the hyperlog module is initialized or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_HyperLogInitialized;
|
||||
|
||||
/**
|
||||
* @brief Shows whether the KD module is initialized or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_KdInitialized;
|
||||
|
||||
/**
|
||||
* @brief Shows whether the VMM is initialized or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_VmmInitialized;
|
||||
|
||||
/**
|
||||
* @brief Shows whether the hypertrace module is initialized or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_HyperTraceInitialized;
|
||||
|
||||
/**
|
||||
* @brief Event to show whether the user debugger is waiting for a command or not
|
||||
*
|
||||
|
|
@ -59,12 +83,6 @@ DEBUGGER_TRAP_FLAG_STATE g_TrapFlagState;
|
|||
*/
|
||||
BOOLEAN g_HandleInUse;
|
||||
|
||||
/**
|
||||
* @brief Determines whether the clients are allowed to send IOCTL to the drive or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_AllowIoctlFromUsermode;
|
||||
|
||||
/**
|
||||
* @brief events list (for debugger)
|
||||
*
|
||||
|
|
@ -112,7 +130,7 @@ UINT32 g_LastError;
|
|||
* @brief Determines whether the debugger events should be active or not
|
||||
*
|
||||
*/
|
||||
BOOLEAN g_EnableDebuggerEvents;
|
||||
BOOLEAN g_EnableDebuggerVmxEvents;
|
||||
|
||||
/**
|
||||
* @brief List header of breakpoints for debugger-mode
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue